pgsql-ast-parser icon indicating copy to clipboard operation
pgsql-ast-parser copied to clipboard

Double-escaped double-quotes in double-quoted identifiers (yes, really) are parsed and serialized incorrectly

Open gthb opened this issue 3 years ago • 3 comments

A query like SELECT 5 as "foo ""bar"" baz" works in psql and interprets the inner "" as one double-quote character, escaped:

 foo "bar" baz
---------------
             5
(1 row)

But pgsql-ast-parser does not account for this escaping. Adding this test to select.spec.ts:

    checkSelect(['select 42 as "alias with ""double-quoted"" part"'], aliased('alias with "double-quoted" part'));

fails like this:

  1) Select statements
       parses select 42 as "alias with ""double-quoted"" part":

      Parser has not returned the expected AST
      + expected - actual

       {
         "columns": [
           {
             "alias": {
      -        "name": "alias with \"\"double-quoted\"\" part"
      +        "name": "alias with \"double-quoted\" part"
             }
             "expr": {
               "type": "integer"
               "value": 42

      at Context.<anonymous> (src/syntax/spec-utils.ts:188:26)
      at processImmediate (node:internal/timers:466:21)

And adding this test to to-sql.spec.ts (and executing with npx mochapack src/to-sql.spec.ts)

    it('quotes quotes in identifiers', () => {
        expect(stm(`select "a ""quote"" you say?"`))
            .to.equal(`SELECT "a ""quote"" you say?"`);
        expect(stm(`select a AS "a ""quote"" you say?"`))
            .to.equal(`SELECT a AS "a ""quote"" you say?"`);
        expect(toSql.statement({
            columns: [
              {
                expr: { type: 'ref', name: 'a' },
                alias: { name: 'a "quote" you say?' }
              }
            ],
            type: 'select'
          }))
            .to.equal(`SELECT a AS "a ""quote"" you say?"`)
    })

also fails, like this:

  1) SQL builder
       quotes quotes in identifiers:

      AssertionError: expected 'SELECT a AS "a "quote" you say?"' to equal 'SELECT a AS "a ""quote"" you say?"'
      + expected - actual

      -SELECT a AS "a "quote" you say?"
      +SELECT a AS "a ""quote"" you say?"

      at Context.<anonymous> (src/to-sql.spec.ts:88:17)
      at processImmediate (node:internal/timers:466:21)

Note that the first two assertions pass, but that's just because the parse is also wrong :-) — so the third assertion has the explicit AST to reveal the failure.

gthb avatar Jun 22 '22 16:06 gthb

Sidenote: the tests in to-sql.spec.ts appear not to be executed when I run npm run test 🤔 ... the output for that ends with:

  668 passing (2s)
  1 failing

  1) Select statements
       parses select 42 as "alias with ""double-quoted"" part":

      Parser has not returned the expected AST
      + expected - actual

       {
         "columns": [
           {
             "alias": {
      -        "name": "alias with \"\"double-quoted\"\" part"
      +        "name": "alias with \"double-quoted\" part"
             }
             "expr": {
               "type": "integer"
               "value": 42

      at Context.<anonymous> (src/syntax/spec-utils.ts:188:26)
      at processImmediate (node:internal/timers:466:21)



 MOCHA  Tests completed with 1 failure(s)

but running directly with npx src/**/*.spec.ts runs them all:

  717 passing (2s)
  2 failing

  1) Select statements
       parses select 42 as "alias with ""double-quoted"" part":

      Parser has not returned the expected AST
      + expected - actual

       {
         "columns": [
           {
             "alias": {
      -        "name": "alias with \"\"double-quoted\"\" part"
      +        "name": "alias with \"double-quoted\" part"
             }
             "expr": {
               "type": "integer"
               "value": 42

      at Context.<anonymous> (src/syntax/spec-utils.ts:188:26)
      at processImmediate (node:internal/timers:466:21)

  2) SQL builder
       quotes quotes in identifiers:

      AssertionError: expected 'SELECT a AS "a "quote" you say?"' to equal 'SELECT a AS "a ""quote"" you say?"'
      + expected - actual

      -SELECT a AS "a "quote" you say?"
      +SELECT a AS "a ""quote"" you say?"

      at Context.<anonymous> (src/to-sql.spec.ts:88:17)
      at processImmediate (node:internal/timers:466:21)



 MOCHA  Tests completed with 2 failure(s)

... is that just something wrong with my environment, or does this happen for someone else?

gthb avatar Jun 22 '22 16:06 gthb

Sidenote: the tests in to-sql.spec.ts appear not to be executed when I run npm run test 🤔 ... the output for that ends with:

I think this is because the run-scripts run in /bin/sh (i.e. bash) by default, where ** doesn't mean anything different from *:

$ npm run test | grep ' passing '
  668 passing (1s)
$ npm_config_script_shell=/bin/sh npm run test | grep ' passing '
  668 passing (1s)
$ npm_config_script_shell=/bin/zsh npm run test | grep ' passing '
  717 passing (1s)

... @oguimbal do you maybe have npm configured to run scripts in zsh by default? Should there maybe be a .npmrc checked into the repository to enforce that, containing:

script-shell=/bin/zsh

?

gthb avatar Jun 22 '22 17:06 gthb

Wrote up a separate issue for that run-script problem. https://github.com/oguimbal/pgsql-ast-parser/issues/92

gthb avatar Jun 22 '22 17:06 gthb