Repository: sublimehq/Packages
Pull request #4259: [SQL] Postgre fixes
Author: login: keith-hall
Labels: name: C: Syntax
Created: 2025-05-21T20:52:52Z | Merged: 2025-05-23T12:54:06Z

Fixes https://github.com/sublimehq/Packages/issues/4258

- don't scope `#` inside quoted identifiers as a line comment
- support function declarations containing quoted parameter names
- other misc fixes


Diff:
diff --git a/Go/Embeddings/SQL (for Go Embedded Backtick Strings).sublime-syntax b/Go/Embeddings/SQL (for Go Embedded Backtick Strings).sublime-syntax
index 00e4668473..94336cc574 100644
--- a/Go/Embeddings/SQL (for Go Embedded Backtick Strings).sublime-syntax	
+++ b/Go/Embeddings/SQL (for Go Embedded Backtick Strings).sublime-syntax	
@@ -8,7 +8,7 @@ hidden: true
 extends: Packages/SQL/SQL.sublime-syntax
 
 contexts:
-  prototype:
+  prototype_without_comments:
     - meta_prepend: true
     - include: scope:source.go#match-raw-text-content
 
diff --git a/Go/tests/syntax_test_go.go b/Go/tests/syntax_test_go.go
index 3e487debde..a023d05acf 100644
--- a/Go/tests/syntax_test_go.go
+++ b/Go/tests/syntax_test_go.go
@@ -5998,9 +5998,13 @@ func lang_embedding() {
     require.Equal(t, 1, testdb.QueryInt(env.testDb, `select count(*) from "schema.{{.site.table}}" order by {{.order}}`))
     //                                              ^ meta.string.go string.quoted.backtick.go punctuation.definition.string.begin.go
     //                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.go meta.embedded.go source.sql.embedded.go
-    //                                                                            ^^^^^^^^^^^^^^^ meta.string.go meta.embedded.go source.sql.embedded.go meta.interpolation.go - string
-    //                                                                                           ^^^^^^^^^^^ meta.block.go meta.string.go meta.embedded.go source.sql.embedded.go
+    //                                                                            ^^^^^^^^^^^^^^^ meta.string.go meta.embedded.go source.sql.embedded.go meta.table-name.sql meta.interpolation.go - string
+    //                                                                            ^^ punctuation.section.interpolation.begin.go
+    //                                                                                         ^^ punctuation.section.interpolation.end.go
+    //                                                                                           ^^^^^^^^^^^ meta.block.go meta.string.go meta.embedded.go
     //                                                                                                      ^^^^^^^^^^ meta.string.go meta.embedded.go source.sql.embedded.go meta.interpolation.go - string
+    //                                                                                                      ^^ punctuation.section.interpolation.begin.go
+    //                                                                                                              ^^ punctuation.section.interpolation.end.go
     //                                                                                                                ^ meta.string.go string.quoted.backtick.go punctuation.definition.string.end.go
     //                                               ^^^^^^ keyword.other
     not_sql_string = `select not sql`
diff --git a/PHP/Embeddings/SQL (for PHP Interpolated).sublime-syntax b/PHP/Embeddings/SQL (for PHP Interpolated).sublime-syntax
index 33478fb091..705af7ecc8 100644
--- a/PHP/Embeddings/SQL (for PHP Interpolated).sublime-syntax	
+++ b/PHP/Embeddings/SQL (for PHP Interpolated).sublime-syntax	
@@ -7,7 +7,7 @@ hidden: true
 extends: Packages/SQL/SQL.sublime-syntax
 
 contexts:
-  prototype:
+  prototype_without_comments:
     - meta_prepend: true
     - include: Packages/PHP/PHP Source.sublime-syntax#interpolations
 
diff --git a/PHP/Embeddings/SQL (for PHP).sublime-syntax b/PHP/Embeddings/SQL (for PHP).sublime-syntax
index 4cfcf3467c..60fa99e562 100644
--- a/PHP/Embeddings/SQL (for PHP).sublime-syntax	
+++ b/PHP/Embeddings/SQL (for PHP).sublime-syntax	
@@ -7,7 +7,7 @@ hidden: true
 extends: Packages/SQL/SQL.sublime-syntax
 
 contexts:
-  prototype:
+  prototype_without_comments:
     - meta_prepend: true
     - include: php-single-quoted-strings
     - include: php-string-single-quoted-escapes
diff --git a/Ruby/syntax_test_ruby.rb b/Ruby/syntax_test_ruby.rb
index 036e4b3944..4608f8a084 100644
--- a/Ruby/syntax_test_ruby.rb
+++ b/Ruby/syntax_test_ruby.rb
@@ -1728,3 +1728,11 @@ def huh?(a, b=def huh?(a); "h?"; end)
 #                       ^^ keyword.control.conditional.if.ruby
 foo << bar.to_s if baz.include?(x)
 #               ^^ keyword.control.conditional.if.ruby
+
+_query = <<-SQL
+  INSERT INTO table
+#^^^^^^^^^^^^^^^^^^ meta.string.heredoc.ruby source.sql.embedded.ruby
+# ^^^^^^^^^^^ keyword.other.dml.sql
+#             ^^^^^ meta.table-name.sql
+  VALUES (1, 2, 3)
+SQL
diff --git a/SQL/PostgreSQL.sublime-syntax b/SQL/PostgreSQL.sublime-syntax
index 8c689e6104..69ac7b81d5 100644
--- a/SQL/PostgreSQL.sublime-syntax
+++ b/SQL/PostgreSQL.sublime-syntax
@@ -11,7 +11,7 @@ file_extensions:
 
 variables:
   simple_types: |-
-    (?xi: smallint | integer | bigint | real | double\s+precision
+    (?xi: smallint | int(?:eger)? | bigint | real | double\s+precision
     | smallserial | serial | bigserial
     | money
     | bytea
@@ -127,6 +127,14 @@ contexts:
     - match: \b(?i:concurrently)\b
       scope: keyword.other.ddl.psql
 
+  create-table-args:
+    # https://www.postgresql.org/docs/current/sql-createtable.html
+    - meta_prepend: true
+    - match: \b(?i:on)\b
+      scope: keyword.control.conditional.psql
+    - match: \b(?i:commit)\b
+      scope: variable.language.psql
+
   create-common-args:
     - meta_prepend: true
     - match: \b(?i:after(?:\s+(?:insert|update|or))+)\b
@@ -209,13 +217,6 @@ contexts:
     - match: \]
       scope: punctuation.section.brackets.end.psql
 
-###[ COLUMN EXPRESSIONS ]######################################################
-
-  inside-column-declaration-list:
-    - meta_prepend: true
-    - match: \b(?i:unique)\b
-      scope: keyword.other.psql
-
 ###[ EXTENSION EXPRESSIONS ]###################################################
 
   extension-attributes:
diff --git a/SQL/SQL (basic).sublime-syntax b/SQL/SQL (basic).sublime-syntax
index e28f51e893..7162f4ea1f 100644
--- a/SQL/SQL (basic).sublime-syntax	
+++ b/SQL/SQL (basic).sublime-syntax	
@@ -60,6 +60,9 @@ variables:
 contexts:
   prototype:
     - include: comments
+    - include: prototype_without_comments
+
+  prototype_without_comments: []
 
   main:
     - include: sql
@@ -799,9 +802,11 @@ contexts:
         \b(?xi:
           (?: (?: fulltext | primary | unique ) \s+ )? key
         | on \s+ (?: delete | update ) (?: \s+ cascade )?
-        | default
         )\b
       scope: storage.modifier.sql
+    - match: \b(?i:default)\b
+      scope: storage.modifier.sql
+      push: expression-or-pop
     - match: |-
         \b(?xi:
           foreign\s+key
@@ -863,10 +868,10 @@ contexts:
         - maybe-parameter-modifier
 
   expect-parameter-name:
-    - match: '{{simple_identifier}}'
-      scope: variable.parameter.sql
-      pop: 1
-    - include: else-pop
+    - match: (?=\S)
+      set:
+        - variable-parameter
+        - single-identifier
 
   maybe-parameter-modifier:
     - match: \b{{function_parameter_modifier}}\b
@@ -885,6 +890,7 @@ contexts:
     - match: \b(?i:returns)\b
       scope: keyword.other.ddl.sql
       push: expect-type
+    - include: column-modifiers
     - include: create-common-args
 
   expect-function-language-name:
@@ -1059,10 +1065,16 @@ contexts:
   after-type:
     - match: \b{{type_modifiers}}\b
       scope: storage.modifier.sql
-      pop: 1
+    - include: column-modifiers
     - include: assignment-operators
     - include: else-pop
 
+  expression-or-pop:
+    - match: (?=\))
+      pop: 1
+    - include: expressions
+    - include: else-pop
+
 ###[ IDENTIFIERS ]#############################################################
 
   expect-table-alias-name:
@@ -1348,6 +1360,11 @@ contexts:
     - meta_scope: meta.other-name.sql
     - include: immediately-pop
 
+  variable-parameter:
+    - meta_include_prototype: false
+    - meta_content_scope: variable.parameter.sql
+    - include: immediately-pop
+
   single-identifier:
     - meta_include_prototype: false
     - include: pop-on-top-level-reserved-word
@@ -1394,6 +1411,8 @@ contexts:
 
   inside-double-quoted-identifier-part:
     # note: may contain foreign variable interpolation
+    - meta_include_prototype: false
+    - include: prototype_without_comments
     - match: \"
       scope: punctuation.definition.identifier.end.sql
       pop: 1
@@ -1405,6 +1424,8 @@ contexts:
 
   inside-single-quoted-identifier-part:
     # note: may contain foreign variable interpolation
+    - meta_include_prototype: false
+    - include: prototype_without_comments
     - match: \'
       scope: punctuation.definition.identifier.end.sql
       pop: 1
diff --git a/SQL/tests/syntax/syntax_test_postgres.psql b/SQL/tests/syntax/syntax_test_postgres.psql
index 354dae88b9..b7485a4f83 100644
--- a/SQL/tests/syntax/syntax_test_postgres.psql
+++ b/SQL/tests/syntax/syntax_test_postgres.psql
@@ -73,6 +73,16 @@ CREATE TABLE IF NOT EXISTS public.dropzone_details
 --                                            ^ meta.function-call meta.group punctuation.section.arguments.end
 --                                             ^ punctuation.separator.sequence
     name text COLLATE pg_catalog."default",
+-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.statement.create.sql meta.table.sql meta.group.table-columns.sql
+--  ^^^^ meta.column-name.sql variable.other.member.declaration.sql
+--       ^^^^ storage.type.sql
+--            ^^^^^^^ keyword.other.sql
+--                    ^^^^^^^^^^ support.constant.sql
+--                              ^^^^^^^^^^ - keyword
+--                              ^ punctuation.accessor.dot.sql
+--                               ^ punctuation.definition.identifier.begin.sql
+--                                       ^ punctuation.definition.identifier.end.sql
+--                                        ^ punctuation.separator.sequence.sql
     doc jsonb,
 --  ^^^ meta.column-name variable.other.member.declaration
 --      ^^^^^ storage.type
@@ -88,7 +98,8 @@ CREATE TABLE IF NOT EXISTS public.dropzone_details
     CONSTRAINT id_name_uix UNIQUE (id, name)
 --  ^^^^^^^^^^ storage.modifier
 --             ^^^^^^^^^^^ meta.constraint-name
---                         ^^^^^^ keyword.other
+--                         ^^^^^^ storage.modifier.sql
+--                                ^^^^^^^^^^ meta.group.table-columns.sql meta.group.table-columns.sql
 --                                ^ punctuation.section.group.begin
 --                                 ^^ meta.column-name - variable.other.member.declaration
 --                                   ^ punctuation.separator.sequence
@@ -563,3 +574,97 @@ select no_comment_here;
 
 --this is also a comment
 --^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-dash.sql
+
+CREATE OR REPLACE FUNCTION public."AutAppB_getBatchOrders"(
+    "@sBatchTy" character varying,
+--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.statement.create.sql meta.function.parameters.sql meta.group.sql
+--  ^^^^^^^^^^^ variable.parameter.sql
+--  ^ punctuation.definition.identifier.begin.sql
+--            ^ punctuation.definition.identifier.end.sql
+--              ^^^^^^^^^^^^^^^^^ storage.type.sql
+--                               ^ punctuation.separator.sequence.sql
+    "@lBatchNum" character varying,
+    "@ValidAccess" character varying DEFAULT NULL::character varying)
+--                                   ^^^^^^^ storage.modifier.sql
+--                                           ^^^^ constant.language.null.sql
+--                                               ^^ keyword.operator.cast.psql
+--                                                 ^^^^^^^^^^^^^^^^^ storage.type.sql
+--                                                                  ^ punctuation.section.group.end.sql
+    RETURNS TABLE("sCliTS" character varying, "sCustID" character varying, "sCliAcctNum" character varying, "cCrdOrdAmt" numeric, "bLnRqst" smallint, "sDcsnCd" character varying, "sCrdTy" character varying, "cDecision" numeric, "sRsnCd1" character varying, "sPONum" character varying, "sApprNum" character varying, "dtShip" timestamp without time zone, "dtExp" timestamp without time zone, "sCliCmmt" character varying, "sCustNm" character varying, "sDesc" character varying, "sDcsnDesc" character varying, "sCrdDesc" character varying, "sRsnDesc" character varying, "sCliTrmCd" character varying, "lCARNum" integer, "sNotes" character varying, "sStsCd" character varying) 
+    LANGUAGE 'plpgsql'
+    COST 100
+    VOLATILE PARALLEL UNSAFE
+    ROWS 1000
+
+AS $BODY$
+
+# variable_conflict use_column
+DECLARE
+    "@@iIndex" INT;
+    "@@iTotal" INT;
+    "@@bLog" SMALLINT;
+    "@@dtLate" TIMESTAMP;
+    "@@dtEff" TIMESTAMP;
+BEGIN
+  IF "isAuth"("@ValidAccess") = 1 THEN
+    "@sBatchTy" = left("@sBatchTy", 1);
+    "@lBatchNum" = left("@lBatchNum", 10);
+
+    CREATE TEMPORARY TABLE "#ProcParms" (
+--  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.statement.create.sql - comment
+--  ^^^^^^ keyword.other.ddl.sql
+--         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.table.sql
+--         ^^^^^^^^^ keyword.other.ddl.sql
+--                   ^^^^^ keyword.other.ddl.sql
+--                         ^^^^^^^^^^^^ entity.name.struct.table.sql
+--                         ^ punctuation.definition.identifier.begin.sql
+--                                    ^ punctuation.definition.identifier.end.sql
+--                                      ^ meta.group.table-columns.sql punctuation.section.group.begin.sql
+         "MySPID" VARCHAR(15)
+        ,"lBatchNum" INT
+--      ^^^^^^^^^^^^^^^^ meta.statement.create.sql meta.table.sql meta.group.table-columns.sql
+--      ^ punctuation.separator.sequence.sql
+--       ^^^^^^^^^^^ meta.string.sql string.quoted.double.sql
+--       ^ punctuation.definition.string.begin.sql
+--                 ^ punctuation.definition.string.end.sql
+--                   ^^^ storage.type.sql
+
+        ,"bLog" SMALLINT
+        ,"bCPU" SMALLINT
+        ,"dtEff" TIMESTAMP WITHOUT TIME ZONE
+    )ON COMMIT DROP;
+--^^^^^^^^^^^^^ meta.statement.create.sql meta.table.sql
+--^^^ meta.group.table-columns.sql
+--  ^ punctuation.section.group.end.sql
+--   ^^ keyword.control.conditional.psql
+--      ^^^^^^ variable.language.psql
+--             ^^^^ meta.statement.drop.sql keyword.other.ddl.sql
+--                 ^ punctuation.terminator.statement.sql
+
+
+    CREATE TEMPORARY TABLE "#Order" ON COMMIT DROP AS
+--  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.statement.create.sql
+--  ^^^^^^ keyword.other.ddl.sql
+--         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.table.sql
+--         ^^^^^^^^^ keyword.other.ddl.sql
+--                   ^^^^^ keyword.other.ddl.sql
+--                         ^^^^^^^^ entity.name.struct.table.sql
+--                         ^ punctuation.definition.identifier.begin.sql
+--                                ^ punctuation.definition.identifier.end.sql
+--                                  ^^ keyword.control.conditional.psql
+--                                     ^^^^^^ variable.language.psql
+--                                            ^^^^^ meta.statement.drop.sql
+--                                            ^^^^ keyword.other.ddl.sql
+--                                                 ^^ keyword.operator.assignment.alias.sql
+    SELECT convert_int( 0) AS "lSeqNum", "lBatchNum", "lRefNum", "sCliID", "sTSID", "sCustID", "sCliAcctNum", "sOrdEmpID", "dtCrdOrder", "cCrdOrdAmt", "bLnRqst", "dtShip", "sCliTrmCd", '   ' AS "sOffID", "sStsCd"
+    FROM "CrdOrdMnl"
+    WHERE  1 = 2
+    ;
+
+    SELECT convert_int( "@lBatchNum"), 'MYID' || convert_varchar( 6, "@@SPID"()), coalesce( A."iValue1", 0), coalesce( A."lValue1", 0), D."dtValue1"
+    INTO "@@lBatchNum", "@@MySPID", "@@bLog", "@@bCPU", "@@dtEff"
+    FROM "RunControl" AS D
+    , "RunControl" AS A
+    WHERE  D."sKey" = 'dtEff'
+    AND A."sKey" = 'AutApprBLog'
+    ;


Reviews:
user: login: keith-hall
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-21T20:58:57Z
user: login: deathaxe
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-22T14:00:50Z
user: login: deathaxe
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-22T15:26:28Z
user: login: deathaxe
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-23T07:16:36Z
user: login: michaelblyons
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-23T12:44:37Z

Review comments:
diff_hunk: @@ -5998,8 +5998,8 @@ func lang_embedding() {
     require.Equal(t, 1, testdb.QueryInt(env.testDb, `select count(*) from "schema.{{.site.table}}" order by {{.order}}`))
     //                                              ^ meta.string.go string.quoted.backtick.go punctuation.definition.string.begin.go
     //                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.go meta.embedded.go source.sql.embedded.go
-    //                                                                            ^^^^^^^^^^^^^^^ meta.string.go meta.embedded.go source.sql.embedded.go meta.interpolation.go - string
-    //                                                                                           ^^^^^^^^^^^ meta.block.go meta.string.go meta.embedded.go source.sql.embedded.go
path: Go/tests/syntax_test_go.go
user: login: keith-hall
body: might need to revisit this one - I disabled prototype inside quoted sql strings to prevent `#` from being scoped as a comment, but it had the side effect of disabling interpolation here... TBH I really think interpolation in SQL strings is a bad idea open to SQL injections, so I'd be okay with not highlighting it as a Go template here...
created_at: 2025-05-21T20:58:57Z
author_association: COLLABORATOR
diff_hunk: @@ -209,6 +209,13 @@ contexts:
     - match: \b(?i:unique)\b
       scope: keyword.other.psql
 
+  after-column-declaration-list:
path: SQL/PostgreSQL.sublime-syntax
user: login: deathaxe
body: With regards to https://www.postgresql.org/docs/current/sql-createtable.html `ON COMMIT` appears to belong to `CREATE TABLE`, but doesn't neccessarily appear (directly) after each column declaration.

Maybe just prepend it to `create-table-args` instead of createing new forced code path after each column list?
created_at: 2025-05-22T14:00:49Z
author_association: COLLABORATOR
diff_hunk: @@ -551,3 +561,90 @@ value := E'\u1234 \U9876A001'
 --         ^^^^^^ constant.character.escape
 --               ^ - constant
 --                ^^^^^^^^^^ constant.character.escape
+
+CREATE OR REPLACE FUNCTION public."AutAppB_getBatchOrders"(
+    "@sBatchTy" character varying,
+--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.statement.create.sql meta.function.parameters.sql meta.group.sql
+--  ^^^^^^^^^^^ variable.parameter.sql
+--  ^ punctuation.definition.identifier.begin.sql
+--            ^ punctuation.definition.identifier.end.sql
+--              ^^^^^^^^^^^^^^^^^ storage.type.sql
+--                               ^ punctuation.separator.sequence.sql
+    "@lBatchNum" character varying,
+    "@ValidAccess" character varying DEFAULT NULL::character varying)
+--                                   ^^^^^^^ storage.modifier.sql
+--                                           ^^^^ constant.language.null.sql
+--                                               ^^ keyword.operator.cast.psql
+--                                                 ^^^^^^^^^^^^^^^^^ storage.type.sql
+--                                                                  ^ punctuation.section.group.end.sql
+    RETURNS TABLE("sCliTS" character varying, "sCustID" character varying, "sCliAcctNum" character varying, "cCrdOrdAmt" numeric, "bLnRqst" smallint, "sDcsnCd" character varying, "sCrdTy" character varying, "cDecision" numeric, "sRsnCd1" character varying, "sPONum" character varying, "sApprNum" character varying, "dtShip" timestamp without time zone, "dtExp" timestamp without time zone, "sCliCmmt" character varying, "sCustNm" character varying, "sDesc" character varying, "sDcsnDesc" character varying, "sCrdDesc" character varying, "sRsnDesc" character varying, "sCliTrmCd" character varying, "lCARNum" integer, "sNotes" character varying, "sStsCd" character varying) 
+    LANGUAGE 'plpgsql'
+    COST 100
+    VOLATILE PARALLEL UNSAFE
+    ROWS 1000
+
+AS $BODY$
+
+# variable_conflict use_column
+DECLARE
+    "@@iIndex" INT;
+    "@@iTotal" INT;
+    "@@bLog" SMALLINT;
+    "@@dtLate" TIMESTAMP;
+    "@@dtEff" TIMESTAMP;
path: SQL/tests/syntax/syntax_test_postgres.psql
user: login: deathaxe
body: All of them should be scoped equally - like the first one.
created_at: 2025-05-22T15:24:50Z
author_association: COLLABORATOR
diff_hunk: @@ -551,3 +561,90 @@ value := E'\u1234 \U9876A001'
 --         ^^^^^^ constant.character.escape
 --               ^ - constant
 --                ^^^^^^^^^^ constant.character.escape
+
+CREATE OR REPLACE FUNCTION public."AutAppB_getBatchOrders"(
+    "@sBatchTy" character varying,
+--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.statement.create.sql meta.function.parameters.sql meta.group.sql
+--  ^^^^^^^^^^^ variable.parameter.sql
+--  ^ punctuation.definition.identifier.begin.sql
+--            ^ punctuation.definition.identifier.end.sql
+--              ^^^^^^^^^^^^^^^^^ storage.type.sql
+--                               ^ punctuation.separator.sequence.sql
+    "@lBatchNum" character varying,
+    "@ValidAccess" character varying DEFAULT NULL::character varying)
+--                                   ^^^^^^^ storage.modifier.sql
+--                                           ^^^^ constant.language.null.sql
+--                                               ^^ keyword.operator.cast.psql
+--                                                 ^^^^^^^^^^^^^^^^^ storage.type.sql
+--                                                                  ^ punctuation.section.group.end.sql
+    RETURNS TABLE("sCliTS" character varying, "sCustID" character varying, "sCliAcctNum" character varying, "cCrdOrdAmt" numeric, "bLnRqst" smallint, "sDcsnCd" character varying, "sCrdTy" character varying, "cDecision" numeric, "sRsnCd1" character varying, "sPONum" character varying, "sApprNum" character varying, "dtShip" timestamp without time zone, "dtExp" timestamp without time zone, "sCliCmmt" character varying, "sCustNm" character varying, "sDesc" character varying, "sDcsnDesc" character varying, "sCrdDesc" character varying, "sRsnDesc" character varying, "sCliTrmCd" character varying, "lCARNum" integer, "sNotes" character varying, "sStsCd" character varying) 
+    LANGUAGE 'plpgsql'
+    COST 100
+    VOLATILE PARALLEL UNSAFE
+    ROWS 1000
+
+AS $BODY$
+
+# variable_conflict use_column
+DECLARE
+    "@@iIndex" INT;
+    "@@iTotal" INT;
+    "@@bLog" SMALLINT;
+    "@@dtLate" TIMESTAMP;
+    "@@dtEff" TIMESTAMP;
+BEGIN
+  IF "isAuth"("@ValidAccess") = 1 THEN
+    "@sBatchTy" = left("@sBatchTy", 1);
+    "@lBatchNum" = left("@lBatchNum", 10);
+
+    CREATE TEMPORARY TABLE "#ProcParms" (
+--  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.statement.create.sql - comment
+--  ^^^^^^ keyword.other.ddl.sql
+--         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.table.sql
+--         ^^^^^^^^^ keyword.other.ddl.sql
+--                   ^^^^^ keyword.other.ddl.sql
+--                         ^^^^^^^^^^^^ entity.name.struct.table.sql
+--                         ^ punctuation.definition.identifier.begin.sql
+--                                    ^ punctuation.definition.identifier.end.sql
+--                                      ^ meta.group.table-columns.sql punctuation.section.group.begin.sql
+         "MySPID" VARCHAR(15)
+        ,"lBatchNum" INT
+        ,"bLog" SMALLINT
+        ,"bCPU" SMALLINT
+        ,"dtEff" TIMESTAMP WITHOUT TIME ZONE
path: SQL/tests/syntax/syntax_test_postgres.psql
user: login: deathaxe
body: Note all quoted identifiers being table names. They are scoped literal string due to `expressions` being included into column declaration list without any restrictions.
created_at: 2025-05-22T15:25:50Z
author_association: COLLABORATOR
diff_hunk: @@ -551,3 +561,90 @@ value := E'\u1234 \U9876A001'
 --         ^^^^^^ constant.character.escape
 --               ^ - constant
 --                ^^^^^^^^^^ constant.character.escape
+
+CREATE OR REPLACE FUNCTION public."AutAppB_getBatchOrders"(
+    "@sBatchTy" character varying,
+--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.statement.create.sql meta.function.parameters.sql meta.group.sql
+--  ^^^^^^^^^^^ variable.parameter.sql
+--  ^ punctuation.definition.identifier.begin.sql
+--            ^ punctuation.definition.identifier.end.sql
+--              ^^^^^^^^^^^^^^^^^ storage.type.sql
+--                               ^ punctuation.separator.sequence.sql
+    "@lBatchNum" character varying,
+    "@ValidAccess" character varying DEFAULT NULL::character varying)
+--                                   ^^^^^^^ storage.modifier.sql
+--                                           ^^^^ constant.language.null.sql
+--                                               ^^ keyword.operator.cast.psql
+--                                                 ^^^^^^^^^^^^^^^^^ storage.type.sql
+--                                                                  ^ punctuation.section.group.end.sql
+    RETURNS TABLE("sCliTS" character varying, "sCustID" character varying, "sCliAcctNum" character varying, "cCrdOrdAmt" numeric, "bLnRqst" smallint, "sDcsnCd" character varying, "sCrdTy" character varying, "cDecision" numeric, "sRsnCd1" character varying, "sPONum" character varying, "sApprNum" character varying, "dtShip" timestamp without time zone, "dtExp" timestamp without time zone, "sCliCmmt" character varying, "sCustNm" character varying, "sDesc" character varying, "sDcsnDesc" character varying, "sCrdDesc" character varying, "sRsnDesc" character varying, "sCliTrmCd" character varying, "lCARNum" integer, "sNotes" character varying, "sStsCd" character varying) 
+    LANGUAGE 'plpgsql'
+    COST 100
+    VOLATILE PARALLEL UNSAFE
+    ROWS 1000
+
+AS $BODY$
+
+# variable_conflict use_column
+DECLARE
+    "@@iIndex" INT;
+    "@@iTotal" INT;
+    "@@bLog" SMALLINT;
+    "@@dtLate" TIMESTAMP;
+    "@@dtEff" TIMESTAMP;
+BEGIN
+  IF "isAuth"("@ValidAccess") = 1 THEN
+    "@sBatchTy" = left("@sBatchTy", 1);
+    "@lBatchNum" = left("@lBatchNum", 10);
+
+    CREATE TEMPORARY TABLE "#ProcParms" (
+--  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.statement.create.sql - comment
+--  ^^^^^^ keyword.other.ddl.sql
+--         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.table.sql
+--         ^^^^^^^^^ keyword.other.ddl.sql
+--                   ^^^^^ keyword.other.ddl.sql
+--                         ^^^^^^^^^^^^ entity.name.struct.table.sql
+--                         ^ punctuation.definition.identifier.begin.sql
+--                                    ^ punctuation.definition.identifier.end.sql
+--                                      ^ meta.group.table-columns.sql punctuation.section.group.begin.sql
+         "MySPID" VARCHAR(15)
+        ,"lBatchNum" INT
+        ,"bLog" SMALLINT
+        ,"bCPU" SMALLINT
+        ,"dtEff" TIMESTAMP WITHOUT TIME ZONE
+    )ON COMMIT DROP;
+--^^^^^^^^^^^^^ meta.statement.create.sql meta.table.sql
+--^^^ meta.group.table-columns.sql
+--  ^ punctuation.section.group.end.sql
+--   ^^ keyword.control.conditional.psql
+--      ^^^^^^ variable.language.psql
+--             ^^^^ meta.statement.drop.sql keyword.other.ddl.sql
+--                 ^ punctuation.terminator.statement.sql
+
+
+    CREATE TEMPORARY TABLE "#Order" ON COMMIT DROP AS
+--  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.statement.create.sql
+--  ^^^^^^ keyword.other.ddl.sql
+--         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.table.sql
+--         ^^^^^^^^^ keyword.other.ddl.sql
+--                   ^^^^^ keyword.other.ddl.sql
+--                         ^^^^^^^^ entity.name.struct.table.sql
+--                         ^ punctuation.definition.identifier.begin.sql
+--                                ^ punctuation.definition.identifier.end.sql
+--                                  ^^ keyword.control.conditional.psql
+--                                     ^^^^^^ variable.language.psql
+--                                            ^^^^^ meta.statement.drop.sql
+--                                            ^^^^ keyword.other.ddl.sql
+--                                                 ^^ keyword.operator.assignment.alias.sql
+    SELECT convert_int( 0) AS "lSeqNum", "lBatchNum", "lRefNum", "sCliID", "sTSID", "sCustID", "sCliAcctNum", "sOrdEmpID", "dtCrdOrder", "cCrdOrdAmt", "bLnRqst", "dtShip", "sCliTrmCd", '   ' AS "sOffID", "sStsCd"
path: SQL/tests/syntax/syntax_test_postgres.psql
user: login: deathaxe
body: All identifiers after `AS` keyword should be scoped the same.
created_at: 2025-05-22T15:26:23Z
author_association: COLLABORATOR

PR comments:
user: login: deathaxe
created_at: 2025-05-22T20:21:04Z
body: FWIW, we can merge this one and address outstanding comments in dedicated PRs, once conflicts are resolved. Postgre requires more work anyway.
author_association: COLLABORATOR
user: login: keith-hall
created_at: 2025-05-22T20:41:59Z
body: I resolved the conflicts, but syntax tests are failing again due to `comments` from `prototype` being included inside single quoted identifiers... https://github.com/forkeith/Packages/pull/34#issue-3083807020

EDIT: came up with a fix :) 
author_association: COLLABORATOR
user: login: deathaxe
created_at: 2025-05-23T07:16:26Z
body: Already realized in other syntaxes, handling comments via `prototype` in base syntaxes being problematic for exactly such reasons. Even if cumbersome, it's probably better in the long term to explicitly include them where needed, especially if `prototype` is to be used by extending syntaxes to inject interpolation with least efforts.
author_association: COLLABORATOR