pgsql-deparser 17.12.2 → 17.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/esm/deparser.js CHANGED
@@ -1188,12 +1188,12 @@ export class Deparser {
1188
1188
  ResTarget(node, context) {
1189
1189
  const output = [];
1190
1190
  if (context.update && node.name) {
1191
- output.push(QuoteUtils.quote(node.name));
1191
+ output.push(QuoteUtils.quoteIdentifier(node.name));
1192
1192
  // Handle indirection (array indexing, field access, etc.)
1193
1193
  if (node.indirection && node.indirection.length > 0) {
1194
1194
  const indirectionStrs = ListUtils.unwrapList(node.indirection).map(item => {
1195
1195
  if (item.String) {
1196
- return `.${QuoteUtils.quote(item.String.sval || item.String.str)}`;
1196
+ return `.${QuoteUtils.quoteIdentifierAfterDot(item.String.sval || item.String.str)}`;
1197
1197
  }
1198
1198
  return this.visit(item, context);
1199
1199
  });
@@ -1205,12 +1205,12 @@ export class Deparser {
1205
1205
  }
1206
1206
  }
1207
1207
  else if (context.insertColumns && node.name) {
1208
- output.push(QuoteUtils.quote(node.name));
1208
+ output.push(QuoteUtils.quoteIdentifier(node.name));
1209
1209
  // Handle indirection for INSERT column lists (e.g., q.c1.r)
1210
1210
  if (node.indirection && node.indirection.length > 0) {
1211
1211
  const indirectionStrs = ListUtils.unwrapList(node.indirection).map(item => {
1212
1212
  if (item.String) {
1213
- return `.${QuoteUtils.quote(item.String.sval || item.String.str)}`;
1213
+ return `.${QuoteUtils.quoteIdentifierAfterDot(item.String.sval || item.String.str)}`;
1214
1214
  }
1215
1215
  return this.visit(item, context);
1216
1216
  });
@@ -1223,7 +1223,7 @@ export class Deparser {
1223
1223
  }
1224
1224
  if (node.name) {
1225
1225
  output.push('AS');
1226
- output.push(QuoteUtils.quote(node.name));
1226
+ output.push(QuoteUtils.quoteIdentifier(node.name));
1227
1227
  }
1228
1228
  }
1229
1229
  return output.join(' ');
@@ -1237,7 +1237,7 @@ export class Deparser {
1237
1237
  if (this.getNodeType(item) === 'ResTarget') {
1238
1238
  const resTarget = this.getNodeData(item);
1239
1239
  const val = resTarget.val ? this.visit(resTarget.val, context) : '';
1240
- const alias = resTarget.name ? ` AS ${QuoteUtils.quote(resTarget.name)}` : '';
1240
+ const alias = resTarget.name ? ` AS ${QuoteUtils.quoteIdentifier(resTarget.name)}` : '';
1241
1241
  return val + alias;
1242
1242
  }
1243
1243
  else {
@@ -1292,7 +1292,8 @@ export class Deparser {
1292
1292
  FuncCall(node, context) {
1293
1293
  const funcname = ListUtils.unwrapList(node.funcname);
1294
1294
  const args = ListUtils.unwrapList(node.args);
1295
- const name = funcname.map(n => this.visit(n, context)).join('.');
1295
+ const funcnameParts = funcname.map((n) => n.String?.sval || n.String?.str || '').filter((s) => s);
1296
+ const name = QuoteUtils.quoteDottedName(funcnameParts);
1296
1297
  // Handle special SQL syntax functions like XMLEXISTS and EXTRACT
1297
1298
  if (node.funcformat === 'COERCE_SQL_SYNTAX' && name === 'pg_catalog.xmlexists' && args.length >= 2) {
1298
1299
  const xpath = this.visit(args[0], context);
@@ -1674,7 +1675,7 @@ export class Deparser {
1674
1675
  const fields = ListUtils.unwrapList(node.fields);
1675
1676
  return fields.map(field => {
1676
1677
  if (field.String) {
1677
- return QuoteUtils.quote(field.String.sval || field.String.str);
1678
+ return QuoteUtils.quoteIdentifier(field.String.sval || field.String.str);
1678
1679
  }
1679
1680
  else if (field.A_Star) {
1680
1681
  return '*';
@@ -1751,8 +1752,7 @@ export class Deparser {
1751
1752
  }
1752
1753
  return output.join(' ');
1753
1754
  }
1754
- const quotedTypeName = QuoteUtils.quote(typeName);
1755
- let result = mods(quotedTypeName, args);
1755
+ let result = mods(typeName, args);
1756
1756
  if (node.arrayBounds && node.arrayBounds.length > 0) {
1757
1757
  result += formatArrayBounds(node.arrayBounds);
1758
1758
  }
@@ -1848,7 +1848,7 @@ export class Deparser {
1848
1848
  return output.join(' ');
1849
1849
  }
1850
1850
  }
1851
- const quotedNames = names.map((name) => QuoteUtils.quote(name));
1851
+ const quotedNames = names.map((name) => QuoteUtils.quoteIdentifier(name));
1852
1852
  let result = mods(quotedNames.join('.'), args);
1853
1853
  if (node.arrayBounds && node.arrayBounds.length > 0) {
1854
1854
  result += formatArrayBounds(node.arrayBounds);
@@ -1887,17 +1887,17 @@ export class Deparser {
1887
1887
  }
1888
1888
  let tableName = '';
1889
1889
  if (node.catalogname) {
1890
- tableName = QuoteUtils.quote(node.catalogname);
1890
+ tableName = QuoteUtils.quoteIdentifier(node.catalogname);
1891
1891
  if (node.schemaname) {
1892
- tableName += '.' + QuoteUtils.quote(node.schemaname);
1892
+ tableName += '.' + QuoteUtils.quoteIdentifierAfterDot(node.schemaname);
1893
1893
  }
1894
- tableName += '.' + QuoteUtils.quote(node.relname);
1894
+ tableName += '.' + QuoteUtils.quoteIdentifierAfterDot(node.relname);
1895
1895
  }
1896
1896
  else if (node.schemaname) {
1897
- tableName = QuoteUtils.quote(node.schemaname) + '.' + QuoteUtils.quote(node.relname);
1897
+ tableName = QuoteUtils.quoteQualifiedIdentifier(node.schemaname, node.relname);
1898
1898
  }
1899
1899
  else {
1900
- tableName = QuoteUtils.quote(node.relname);
1900
+ tableName = QuoteUtils.quoteIdentifier(node.relname);
1901
1901
  }
1902
1902
  output.push(tableName);
1903
1903
  if (node.alias) {
@@ -2123,7 +2123,7 @@ export class Deparser {
2123
2123
  const indirection = ListUtils.unwrapList(node.indirection);
2124
2124
  for (const subnode of indirection) {
2125
2125
  if (subnode.String || subnode.A_Star) {
2126
- const value = subnode.A_Star ? '*' : QuoteUtils.quote(subnode.String.sval || subnode.String.str);
2126
+ const value = subnode.A_Star ? '*' : QuoteUtils.quoteIdentifier(subnode.String.sval || subnode.String.str);
2127
2127
  output.push(`.${value}`);
2128
2128
  }
2129
2129
  else {
@@ -2268,32 +2268,8 @@ export class Deparser {
2268
2268
  }
2269
2269
  return output.join(' ');
2270
2270
  }
2271
- static RESERVED_WORDS = new Set([
2272
- 'all', 'analyse', 'analyze', 'and', 'any', 'array', 'as', 'asc', 'asymmetric', 'both',
2273
- 'case', 'cast', 'check', 'collate', 'column', 'constraint', 'create', 'current_catalog',
2274
- 'current_date', 'current_role', 'current_time', 'current_timestamp', 'current_user',
2275
- 'default', 'deferrable', 'desc', 'distinct', 'do', 'else', 'end', 'except', 'false',
2276
- 'fetch', 'for', 'foreign', 'from', 'grant', 'group', 'having', 'in', 'initially',
2277
- 'intersect', 'into', 'lateral', 'leading', 'limit', 'localtime', 'localtimestamp',
2278
- 'not', 'null', 'offset', 'on', 'only', 'or', 'order', 'placing', 'primary',
2279
- 'references', 'returning', 'select', 'session_user', 'some', 'symmetric', 'table',
2280
- 'then', 'to', 'trailing', 'true', 'union', 'unique', 'user', 'using', 'variadic',
2281
- 'when', 'where', 'window', 'with'
2282
- ]);
2283
- static needsQuotes(value) {
2284
- if (!value)
2285
- return false;
2286
- const needsQuotesRegex = /[a-z]+[\W\w]*[A-Z]+|[A-Z]+[\W\w]*[a-z]+|\W/;
2287
- const isAllUppercase = /^[A-Z]+$/.test(value);
2288
- return needsQuotesRegex.test(value) ||
2289
- Deparser.RESERVED_WORDS.has(value.toLowerCase()) ||
2290
- isAllUppercase;
2291
- }
2292
2271
  quoteIfNeeded(value) {
2293
- if (Deparser.needsQuotes(value)) {
2294
- return `"${value}"`;
2295
- }
2296
- return value;
2272
+ return QuoteUtils.quoteIdentifier(value);
2297
2273
  }
2298
2274
  preserveOperatorDefElemCase(defName) {
2299
2275
  const caseMap = {
@@ -2326,7 +2302,7 @@ export class Deparser {
2326
2302
  return value; // Don't quote pure operator symbols like "=" or "-"
2327
2303
  }
2328
2304
  }
2329
- return Deparser.needsQuotes(value) ? `"${value}"` : value;
2305
+ return QuoteUtils.quoteIdentifier(value);
2330
2306
  }
2331
2307
  Integer(node, context) {
2332
2308
  return node.ival?.toString() || '0';
@@ -2503,7 +2479,7 @@ export class Deparser {
2503
2479
  ColumnDef(node, context) {
2504
2480
  const output = [];
2505
2481
  if (node.colname) {
2506
- output.push(QuoteUtils.quote(node.colname));
2482
+ output.push(QuoteUtils.quoteIdentifier(node.colname));
2507
2483
  }
2508
2484
  if (node.typeName) {
2509
2485
  output.push(this.TypeName(node.typeName, context));
@@ -2544,7 +2520,7 @@ export class Deparser {
2544
2520
  // Handle constraint name if present
2545
2521
  if (node.conname && (node.contype === 'CONSTR_CHECK' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_FOREIGN')) {
2546
2522
  output.push('CONSTRAINT');
2547
- output.push(QuoteUtils.quote(node.conname));
2523
+ output.push(QuoteUtils.quoteIdentifier(node.conname));
2548
2524
  }
2549
2525
  switch (node.contype) {
2550
2526
  case 'CONSTR_NULL':
@@ -3441,7 +3417,7 @@ export class Deparser {
3441
3417
  output.push('IF NOT EXISTS');
3442
3418
  }
3443
3419
  if (node.idxname) {
3444
- output.push(QuoteUtils.quote(node.idxname));
3420
+ output.push(QuoteUtils.quoteIdentifier(node.idxname));
3445
3421
  }
3446
3422
  output.push('ON');
3447
3423
  if (node.relation) {
@@ -3475,14 +3451,14 @@ export class Deparser {
3475
3451
  }
3476
3452
  if (node.tableSpace) {
3477
3453
  output.push('TABLESPACE');
3478
- output.push(QuoteUtils.quote(node.tableSpace));
3454
+ output.push(QuoteUtils.quoteIdentifier(node.tableSpace));
3479
3455
  }
3480
3456
  return output.join(' ');
3481
3457
  }
3482
3458
  IndexElem(node, context) {
3483
3459
  const output = [];
3484
3460
  if (node.name) {
3485
- output.push(QuoteUtils.quote(node.name));
3461
+ output.push(QuoteUtils.quoteIdentifier(node.name));
3486
3462
  }
3487
3463
  else if (node.expr) {
3488
3464
  output.push(context.parens(this.visit(node.expr, context)));
@@ -3533,7 +3509,7 @@ export class Deparser {
3533
3509
  PartitionElem(node, context) {
3534
3510
  const output = [];
3535
3511
  if (node.name) {
3536
- output.push(QuoteUtils.quote(node.name));
3512
+ output.push(QuoteUtils.quoteIdentifier(node.name));
3537
3513
  }
3538
3514
  else if (node.expr) {
3539
3515
  output.push(context.parens(this.visit(node.expr, context)));
@@ -3783,19 +3759,19 @@ export class Deparser {
3783
3759
  case 'TRANS_STMT_SAVEPOINT':
3784
3760
  output.push('SAVEPOINT');
3785
3761
  if (node.savepoint_name) {
3786
- output.push(QuoteUtils.quote(node.savepoint_name));
3762
+ output.push(QuoteUtils.quoteIdentifier(node.savepoint_name));
3787
3763
  }
3788
3764
  break;
3789
3765
  case 'TRANS_STMT_RELEASE':
3790
3766
  output.push('RELEASE SAVEPOINT');
3791
3767
  if (node.savepoint_name) {
3792
- output.push(QuoteUtils.quote(node.savepoint_name));
3768
+ output.push(QuoteUtils.quoteIdentifier(node.savepoint_name));
3793
3769
  }
3794
3770
  break;
3795
3771
  case 'TRANS_STMT_ROLLBACK_TO':
3796
3772
  output.push('ROLLBACK TO');
3797
3773
  if (node.savepoint_name) {
3798
- output.push(QuoteUtils.quote(node.savepoint_name));
3774
+ output.push(QuoteUtils.quoteIdentifier(node.savepoint_name));
3799
3775
  }
3800
3776
  break;
3801
3777
  case 'TRANS_STMT_PREPARE':
@@ -3892,16 +3868,16 @@ export class Deparser {
3892
3868
  return this.visit(arg, context);
3893
3869
  }).join(', ') : '';
3894
3870
  // Handle args - always include TO clause if args exist (even if empty string)
3895
- const paramName = node.name && (node.name.includes('.') || node.name.includes('-') || /[A-Z]/.test(node.name)) ? `"${node.name}"` : node.name;
3871
+ const paramName = QuoteUtils.quoteIdentifier(node.name);
3896
3872
  if (!node.args || node.args.length === 0) {
3897
3873
  return `SET ${localPrefix}${paramName}`;
3898
3874
  }
3899
3875
  return `SET ${localPrefix}${paramName} TO ${args}`;
3900
3876
  case 'VAR_SET_DEFAULT':
3901
- const defaultParamName = node.name && (node.name.includes('.') || node.name.includes('-') || /[A-Z]/.test(node.name)) ? `"${node.name}"` : node.name;
3877
+ const defaultParamName = QuoteUtils.quoteIdentifier(node.name);
3902
3878
  return `SET ${defaultParamName} TO DEFAULT`;
3903
3879
  case 'VAR_SET_CURRENT':
3904
- const currentParamName = node.name && (node.name.includes('.') || node.name.includes('-') || /[A-Z]/.test(node.name)) ? `"${node.name}"` : node.name;
3880
+ const currentParamName = QuoteUtils.quoteIdentifier(node.name);
3905
3881
  return `SET ${currentParamName} FROM CURRENT`;
3906
3882
  case 'VAR_SET_MULTI':
3907
3883
  if (node.name === 'TRANSACTION' || node.name === 'SESSION CHARACTERISTICS') {
@@ -3975,7 +3951,7 @@ export class Deparser {
3975
3951
  return `SET ${assignments}`;
3976
3952
  }
3977
3953
  case 'VAR_RESET':
3978
- const resetParamName = node.name && (node.name.includes('.') || node.name.includes('-') || /[A-Z]/.test(node.name)) ? `"${node.name}"` : node.name;
3954
+ const resetParamName = QuoteUtils.quoteIdentifier(node.name);
3979
3955
  return `RESET ${resetParamName}`;
3980
3956
  case 'VAR_RESET_ALL':
3981
3957
  return 'RESET ALL';
@@ -4244,7 +4220,7 @@ export class Deparser {
4244
4220
  if (objList && objList.List && objList.List.items) {
4245
4221
  const items = objList.List.items.map((item) => {
4246
4222
  if (item.String && item.String.sval) {
4247
- return QuoteUtils.quote(item.String.sval);
4223
+ return QuoteUtils.quoteIdentifier(item.String.sval);
4248
4224
  }
4249
4225
  return this.visit(item, context);
4250
4226
  }).filter((name) => name && name.trim());
@@ -4278,13 +4254,13 @@ export class Deparser {
4278
4254
  if (items.length === 2) {
4279
4255
  const accessMethod = items[0];
4280
4256
  const objectName = items[1];
4281
- return `${QuoteUtils.quote(objectName)} USING ${accessMethod}`;
4257
+ return `${QuoteUtils.quoteIdentifier(objectName)} USING ${accessMethod}`;
4282
4258
  }
4283
4259
  else if (items.length === 3) {
4284
4260
  const accessMethod = items[0];
4285
4261
  const schemaName = items[1];
4286
4262
  const objectName = items[2];
4287
- return `${QuoteUtils.quote(schemaName)}.${QuoteUtils.quote(objectName)} USING ${accessMethod}`;
4263
+ return `${QuoteUtils.quoteQualifiedIdentifier(schemaName, objectName)} USING ${accessMethod}`;
4288
4264
  }
4289
4265
  return items.join('.');
4290
4266
  }
@@ -4327,7 +4303,7 @@ export class Deparser {
4327
4303
  if (objList && objList.List && objList.List.items) {
4328
4304
  const items = objList.List.items.map((item) => {
4329
4305
  if (item.String && item.String.sval) {
4330
- return QuoteUtils.quote(item.String.sval);
4306
+ return QuoteUtils.quoteIdentifier(item.String.sval);
4331
4307
  }
4332
4308
  return this.visit(item, context);
4333
4309
  }).filter((name) => name && name.trim());
@@ -4375,7 +4351,7 @@ export class Deparser {
4375
4351
  PLAssignStmt(node, context) {
4376
4352
  const output = [];
4377
4353
  if (node.name) {
4378
- let nameWithIndirection = QuoteUtils.quote(node.name);
4354
+ let nameWithIndirection = QuoteUtils.quoteIdentifier(node.name);
4379
4355
  if (node.indirection && node.indirection.length > 0) {
4380
4356
  const indirectionStr = node.indirection
4381
4357
  .map((ind) => this.visit(ind, context))
@@ -4524,7 +4500,7 @@ export class Deparser {
4524
4500
  const parts = [];
4525
4501
  const indentedParts = [];
4526
4502
  if (colDefData.colname) {
4527
- parts.push(QuoteUtils.quote(colDefData.colname));
4503
+ parts.push(QuoteUtils.quoteIdentifier(colDefData.colname));
4528
4504
  }
4529
4505
  if (colDefData.typeName) {
4530
4506
  parts.push(this.TypeName(colDefData.typeName, context));
@@ -4582,7 +4558,7 @@ export class Deparser {
4582
4558
  else {
4583
4559
  const parts = [];
4584
4560
  if (colDefData.colname) {
4585
- parts.push(QuoteUtils.quote(colDefData.colname));
4561
+ parts.push(QuoteUtils.quoteIdentifier(colDefData.colname));
4586
4562
  }
4587
4563
  if (colDefData.typeName) {
4588
4564
  parts.push(this.TypeName(colDefData.typeName, context));
@@ -4636,7 +4612,7 @@ export class Deparser {
4636
4612
  }
4637
4613
  }
4638
4614
  if (node.name) {
4639
- output.push(QuoteUtils.quote(node.name));
4615
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4640
4616
  }
4641
4617
  if (node.behavior === 'DROP_CASCADE') {
4642
4618
  output.push('CASCADE');
@@ -4653,7 +4629,7 @@ export class Deparser {
4653
4629
  output.push('ALTER COLUMN');
4654
4630
  }
4655
4631
  if (node.name) {
4656
- output.push(QuoteUtils.quote(node.name));
4632
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4657
4633
  }
4658
4634
  output.push('TYPE');
4659
4635
  if (node.def) {
@@ -4680,7 +4656,7 @@ export class Deparser {
4680
4656
  case 'AT_SetTableSpace':
4681
4657
  output.push('SET TABLESPACE');
4682
4658
  if (node.name) {
4683
- output.push(QuoteUtils.quote(node.name));
4659
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4684
4660
  }
4685
4661
  break;
4686
4662
  case 'AT_AddConstraint':
@@ -4698,7 +4674,7 @@ export class Deparser {
4698
4674
  output.push('DROP CONSTRAINT');
4699
4675
  }
4700
4676
  if (node.name) {
4701
- output.push(QuoteUtils.quote(node.name));
4677
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4702
4678
  }
4703
4679
  if (node.behavior === 'DROP_CASCADE') {
4704
4680
  output.push('CASCADE');
@@ -4736,7 +4712,7 @@ export class Deparser {
4736
4712
  case 'AT_ColumnDefault':
4737
4713
  output.push('ALTER COLUMN');
4738
4714
  if (node.name) {
4739
- output.push(QuoteUtils.quote(node.name));
4715
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4740
4716
  }
4741
4717
  if (node.def) {
4742
4718
  output.push('SET DEFAULT');
@@ -4749,7 +4725,7 @@ export class Deparser {
4749
4725
  case 'AT_SetStorage':
4750
4726
  output.push('ALTER COLUMN');
4751
4727
  if (node.name) {
4752
- output.push(QuoteUtils.quote(node.name));
4728
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4753
4729
  }
4754
4730
  output.push('SET STORAGE');
4755
4731
  if (node.def) {
@@ -4760,7 +4736,7 @@ export class Deparser {
4760
4736
  case 'AT_ClusterOn':
4761
4737
  output.push('CLUSTER ON');
4762
4738
  if (node.name) {
4763
- output.push(QuoteUtils.quote(node.name));
4739
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4764
4740
  }
4765
4741
  break;
4766
4742
  case 'AT_DropCluster':
@@ -4787,21 +4763,21 @@ export class Deparser {
4787
4763
  case 'AT_SetNotNull':
4788
4764
  output.push('ALTER COLUMN');
4789
4765
  if (node.name) {
4790
- output.push(QuoteUtils.quote(node.name));
4766
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4791
4767
  }
4792
4768
  output.push('SET NOT NULL');
4793
4769
  break;
4794
4770
  case 'AT_DropNotNull':
4795
4771
  output.push('ALTER COLUMN');
4796
4772
  if (node.name) {
4797
- output.push(QuoteUtils.quote(node.name));
4773
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4798
4774
  }
4799
4775
  output.push('DROP NOT NULL');
4800
4776
  break;
4801
4777
  case 'AT_SetStatistics':
4802
4778
  output.push('ALTER COLUMN');
4803
4779
  if (node.name) {
4804
- output.push(QuoteUtils.quote(node.name));
4780
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4805
4781
  }
4806
4782
  else if (node.num !== undefined && node.num !== null) {
4807
4783
  output.push(node.num.toString());
@@ -4814,7 +4790,7 @@ export class Deparser {
4814
4790
  case 'AT_SetOptions':
4815
4791
  output.push('ALTER COLUMN');
4816
4792
  if (node.name) {
4817
- output.push(QuoteUtils.quote(node.name));
4793
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4818
4794
  }
4819
4795
  output.push('SET');
4820
4796
  if (node.def) {
@@ -4831,7 +4807,7 @@ export class Deparser {
4831
4807
  case 'AT_ResetOptions':
4832
4808
  output.push('ALTER COLUMN');
4833
4809
  if (node.name) {
4834
- output.push(QuoteUtils.quote(node.name));
4810
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4835
4811
  }
4836
4812
  output.push('RESET');
4837
4813
  if (node.def) {
@@ -4848,7 +4824,7 @@ export class Deparser {
4848
4824
  case 'AT_SetCompression':
4849
4825
  output.push('ALTER COLUMN');
4850
4826
  if (node.name) {
4851
- output.push(QuoteUtils.quote(node.name));
4827
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4852
4828
  }
4853
4829
  output.push('SET COMPRESSION');
4854
4830
  if (node.def) {
@@ -4858,31 +4834,31 @@ export class Deparser {
4858
4834
  case 'AT_ValidateConstraint':
4859
4835
  output.push('VALIDATE CONSTRAINT');
4860
4836
  if (node.name) {
4861
- output.push(QuoteUtils.quote(node.name));
4837
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4862
4838
  }
4863
4839
  break;
4864
4840
  case 'AT_EnableTrig':
4865
4841
  output.push('ENABLE TRIGGER');
4866
4842
  if (node.name) {
4867
- output.push(QuoteUtils.quote(node.name));
4843
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4868
4844
  }
4869
4845
  break;
4870
4846
  case 'AT_EnableAlwaysTrig':
4871
4847
  output.push('ENABLE ALWAYS TRIGGER');
4872
4848
  if (node.name) {
4873
- output.push(QuoteUtils.quote(node.name));
4849
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4874
4850
  }
4875
4851
  break;
4876
4852
  case 'AT_EnableReplicaTrig':
4877
4853
  output.push('ENABLE REPLICA TRIGGER');
4878
4854
  if (node.name) {
4879
- output.push(QuoteUtils.quote(node.name));
4855
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4880
4856
  }
4881
4857
  break;
4882
4858
  case 'AT_DisableTrig':
4883
4859
  output.push('DISABLE TRIGGER');
4884
4860
  if (node.name) {
4885
- output.push(QuoteUtils.quote(node.name));
4861
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4886
4862
  }
4887
4863
  break;
4888
4864
  case 'AT_EnableTrigAll':
@@ -4900,31 +4876,31 @@ export class Deparser {
4900
4876
  case 'AT_EnableRule':
4901
4877
  output.push('ENABLE RULE');
4902
4878
  if (node.name) {
4903
- output.push(QuoteUtils.quote(node.name));
4879
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4904
4880
  }
4905
4881
  break;
4906
4882
  case 'AT_EnableAlwaysRule':
4907
4883
  output.push('ENABLE ALWAYS RULE');
4908
4884
  if (node.name) {
4909
- output.push(QuoteUtils.quote(node.name));
4885
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4910
4886
  }
4911
4887
  break;
4912
4888
  case 'AT_EnableReplicaRule':
4913
4889
  output.push('ENABLE REPLICA RULE');
4914
4890
  if (node.name) {
4915
- output.push(QuoteUtils.quote(node.name));
4891
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4916
4892
  }
4917
4893
  break;
4918
4894
  case 'AT_DisableRule':
4919
4895
  output.push('DISABLE RULE');
4920
4896
  if (node.name) {
4921
- output.push(QuoteUtils.quote(node.name));
4897
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4922
4898
  }
4923
4899
  break;
4924
4900
  case 'AT_SetAccessMethod':
4925
4901
  output.push('SET ACCESS METHOD');
4926
4902
  if (node.name) {
4927
- output.push(QuoteUtils.quote(node.name));
4903
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4928
4904
  }
4929
4905
  else {
4930
4906
  // Handle DEFAULT access method case
@@ -4978,7 +4954,7 @@ export class Deparser {
4978
4954
  case 'AT_CookedColumnDefault':
4979
4955
  output.push('ALTER COLUMN');
4980
4956
  if (node.name) {
4981
- output.push(QuoteUtils.quote(node.name));
4957
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4982
4958
  }
4983
4959
  if (node.def) {
4984
4960
  output.push('SET DEFAULT');
@@ -4991,7 +4967,7 @@ export class Deparser {
4991
4967
  case 'AT_SetExpression':
4992
4968
  output.push('ALTER COLUMN');
4993
4969
  if (node.name) {
4994
- output.push(QuoteUtils.quote(node.name));
4970
+ output.push(QuoteUtils.quoteIdentifier(node.name));
4995
4971
  }
4996
4972
  output.push('SET EXPRESSION');
4997
4973
  if (node.def) {
@@ -5001,14 +4977,14 @@ export class Deparser {
5001
4977
  case 'AT_DropExpression':
5002
4978
  output.push('ALTER COLUMN');
5003
4979
  if (node.name) {
5004
- output.push(QuoteUtils.quote(node.name));
4980
+ output.push(QuoteUtils.quoteIdentifier(node.name));
5005
4981
  }
5006
4982
  output.push('DROP EXPRESSION');
5007
4983
  break;
5008
4984
  case 'AT_CheckNotNull':
5009
4985
  output.push('ALTER COLUMN');
5010
4986
  if (node.name) {
5011
- output.push(QuoteUtils.quote(node.name));
4987
+ output.push(QuoteUtils.quoteIdentifier(node.name));
5012
4988
  }
5013
4989
  output.push('SET NOT NULL');
5014
4990
  break;
@@ -5041,7 +5017,7 @@ export class Deparser {
5041
5017
  if (node.def && this.getNodeType(node.def) === 'Constraint') {
5042
5018
  const constraintData = this.getNodeData(node.def);
5043
5019
  if (constraintData.conname) {
5044
- output.push(QuoteUtils.quote(constraintData.conname));
5020
+ output.push(QuoteUtils.quoteIdentifier(constraintData.conname));
5045
5021
  if (constraintData.deferrable !== undefined) {
5046
5022
  output.push(constraintData.deferrable ? 'DEFERRABLE' : 'NOT DEFERRABLE');
5047
5023
  }
@@ -5051,7 +5027,7 @@ export class Deparser {
5051
5027
  }
5052
5028
  }
5053
5029
  else if (node.name) {
5054
- output.push(QuoteUtils.quote(node.name));
5030
+ output.push(QuoteUtils.quoteIdentifier(node.name));
5055
5031
  if (node.def) {
5056
5032
  output.push(this.visit(node.def, context));
5057
5033
  }
@@ -5072,7 +5048,7 @@ export class Deparser {
5072
5048
  case 'AT_AlterColumnGenericOptions':
5073
5049
  output.push('ALTER COLUMN');
5074
5050
  if (node.name) {
5075
- output.push(QuoteUtils.quote(node.name));
5051
+ output.push(QuoteUtils.quoteIdentifier(node.name));
5076
5052
  }
5077
5053
  output.push('OPTIONS');
5078
5054
  if (node.def) {
@@ -5126,7 +5102,7 @@ export class Deparser {
5126
5102
  case 'AT_AddIdentity':
5127
5103
  output.push('ALTER COLUMN');
5128
5104
  if (node.name) {
5129
- output.push(QuoteUtils.quote(node.name));
5105
+ output.push(QuoteUtils.quoteIdentifier(node.name));
5130
5106
  }
5131
5107
  output.push('ADD');
5132
5108
  if (node.def) {
@@ -5136,7 +5112,7 @@ export class Deparser {
5136
5112
  case 'AT_SetIdentity':
5137
5113
  output.push('ALTER COLUMN');
5138
5114
  if (node.name) {
5139
- output.push(QuoteUtils.quote(node.name));
5115
+ output.push(QuoteUtils.quoteIdentifier(node.name));
5140
5116
  }
5141
5117
  output.push('SET');
5142
5118
  if (node.def) {
@@ -5146,7 +5122,7 @@ export class Deparser {
5146
5122
  case 'AT_DropIdentity':
5147
5123
  output.push('ALTER COLUMN');
5148
5124
  if (node.name) {
5149
- output.push(QuoteUtils.quote(node.name));
5125
+ output.push(QuoteUtils.quoteIdentifier(node.name));
5150
5126
  }
5151
5127
  output.push('DROP IDENTITY');
5152
5128
  if (node.behavior === 'DROP_CASCADE') {
@@ -5180,7 +5156,8 @@ export class Deparser {
5180
5156
  output.push('FUNCTION');
5181
5157
  }
5182
5158
  if (node.funcname && node.funcname.length > 0) {
5183
- const funcName = node.funcname.map((name) => this.visit(name, context)).join('.');
5159
+ const funcnameParts = node.funcname.map((name) => name.String?.sval || name.String?.str || '').filter((s) => s);
5160
+ const funcName = QuoteUtils.quoteDottedName(funcnameParts);
5184
5161
  if (node.parameters && node.parameters.length > 0) {
5185
5162
  const params = node.parameters
5186
5163
  .filter((param) => {
@@ -5285,7 +5262,7 @@ export class Deparser {
5285
5262
  }
5286
5263
  }
5287
5264
  if (node.name) {
5288
- output.push(QuoteUtils.quote(node.name));
5265
+ output.push(QuoteUtils.quoteIdentifier(node.name));
5289
5266
  }
5290
5267
  if (node.argType) {
5291
5268
  output.push(this.TypeName(node.argType, context));
@@ -5357,7 +5334,7 @@ export class Deparser {
5357
5334
  output.push('ROLE');
5358
5335
  }
5359
5336
  if (node.role) {
5360
- const roleName = Deparser.needsQuotes(node.role) ? `"${node.role}"` : node.role;
5337
+ const roleName = QuoteUtils.quoteIdentifier(node.role);
5361
5338
  output.push(roleName);
5362
5339
  }
5363
5340
  if (node.options) {
@@ -5399,7 +5376,7 @@ export class Deparser {
5399
5376
  if (context.parentNodeTypes.includes('DefineStmt') &&
5400
5377
  ['hashes', 'merges'].includes(node.defname.toLowerCase()) && !node.arg) {
5401
5378
  if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
5402
- return `"${node.defname}"`;
5379
+ return QuoteUtils.quoteIdentifier(node.defname);
5403
5380
  }
5404
5381
  return node.defname.charAt(0).toUpperCase() + node.defname.slice(1).toLowerCase();
5405
5382
  }
@@ -5421,9 +5398,7 @@ export class Deparser {
5421
5398
  const finalValue = typeof argValue === 'string' && !argValue.startsWith("'")
5422
5399
  ? `'${argValue}'`
5423
5400
  : argValue;
5424
- const quotedDefname = node.defname.includes(' ') || node.defname.includes('-') || Deparser.needsQuotes(node.defname)
5425
- ? `"${node.defname}"`
5426
- : node.defname;
5401
+ const quotedDefname = QuoteUtils.quoteIdentifier(node.defname);
5427
5402
  if (node.defaction === 'DEFELEM_ADD') {
5428
5403
  return `ADD ${quotedDefname} ${finalValue}`;
5429
5404
  }
@@ -5447,9 +5422,7 @@ export class Deparser {
5447
5422
  else if (node.defaction === 'DEFELEM_SET') {
5448
5423
  return `SET ${node.defname} ${quotedValue}`;
5449
5424
  }
5450
- const quotedDefname = node.defname.includes(' ') || node.defname.includes('-')
5451
- ? `"${node.defname}"`
5452
- : node.defname;
5425
+ const quotedDefname = QuoteUtils.quoteIdentifier(node.defname);
5453
5426
  return `${quotedDefname} ${quotedValue}`;
5454
5427
  }
5455
5428
  else if (node.defaction === 'DEFELEM_DROP') {
@@ -5509,9 +5482,7 @@ export class Deparser {
5509
5482
  const quotedValue = typeof argValue === 'string'
5510
5483
  ? QuoteUtils.escape(argValue)
5511
5484
  : argValue;
5512
- const quotedDefname = node.defname.includes(' ') || node.defname.includes('-')
5513
- ? `"${node.defname}"`
5514
- : node.defname;
5485
+ const quotedDefname = QuoteUtils.quoteIdentifier(node.defname);
5515
5486
  return `${quotedDefname} ${quotedValue}`;
5516
5487
  }
5517
5488
  if (context.parentNodeTypes.includes('CreateRoleStmt') || context.parentNodeTypes.includes('AlterRoleStmt')) {
@@ -5586,10 +5557,7 @@ export class Deparser {
5586
5557
  if (this.getNodeType(item) === 'String') {
5587
5558
  // Check if this identifier needs quotes to preserve case
5588
5559
  const value = itemData.sval;
5589
- if (Deparser.needsQuotes(value)) {
5590
- return `"${value}"`;
5591
- }
5592
- return value;
5560
+ return QuoteUtils.quoteIdentifier(value);
5593
5561
  }
5594
5562
  return this.visit(item, context);
5595
5563
  });
@@ -5837,13 +5805,13 @@ export class Deparser {
5837
5805
  // Handle boolean flags (no arguments) - preserve quoted case
5838
5806
  if (['hashes', 'merges'].includes(node.defname.toLowerCase())) {
5839
5807
  if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
5840
- return `"${node.defname}"`;
5808
+ return QuoteUtils.quoteIdentifier(node.defname);
5841
5809
  }
5842
5810
  return preservedName.toUpperCase();
5843
5811
  }
5844
5812
  // Handle CREATE AGGREGATE quoted identifiers - preserve quotes when needed
5845
- if (Deparser.needsQuotes(node.defname)) {
5846
- const quotedDefname = `"${node.defname}"`;
5813
+ const quotedDefname = QuoteUtils.quoteIdentifier(node.defname);
5814
+ if (quotedDefname !== node.defname) {
5847
5815
  if (node.arg) {
5848
5816
  if (this.getNodeType(node.arg) === 'String') {
5849
5817
  const stringData = this.getNodeData(node.arg);
@@ -5903,7 +5871,7 @@ export class Deparser {
5903
5871
  if (context.parentNodeTypes.includes('DefineStmt') && !node.arg) {
5904
5872
  // Check if the original defname appears to be quoted (mixed case that's not all upper/lower)
5905
5873
  if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
5906
- return `"${node.defname}"`;
5874
+ return QuoteUtils.quoteIdentifier(node.defname);
5907
5875
  }
5908
5876
  }
5909
5877
  return node.defname.toUpperCase();
@@ -6087,7 +6055,7 @@ export class Deparser {
6087
6055
  case 'REPLICA_IDENTITY_INDEX':
6088
6056
  output.push('USING', 'INDEX');
6089
6057
  if (node.name) {
6090
- output.push(QuoteUtils.quote(node.name));
6058
+ output.push(QuoteUtils.quoteIdentifier(node.name));
6091
6059
  }
6092
6060
  break;
6093
6061
  default:
@@ -6146,7 +6114,7 @@ export class Deparser {
6146
6114
  output.push('IF', 'EXISTS');
6147
6115
  }
6148
6116
  if (node.name) {
6149
- output.push(QuoteUtils.quote(node.name));
6117
+ output.push(QuoteUtils.quoteIdentifier(node.name));
6150
6118
  }
6151
6119
  if (node.behavior === 'DROP_CASCADE') {
6152
6120
  output.push('CASCADE');
@@ -6155,7 +6123,7 @@ export class Deparser {
6155
6123
  case 'AT_ValidateConstraint':
6156
6124
  output.push('VALIDATE', 'CONSTRAINT');
6157
6125
  if (node.name) {
6158
- output.push(QuoteUtils.quote(node.name));
6126
+ output.push(QuoteUtils.quoteIdentifier(node.name));
6159
6127
  }
6160
6128
  break;
6161
6129
  case 'C':
@@ -6172,7 +6140,7 @@ export class Deparser {
6172
6140
  output.push('IF', 'EXISTS');
6173
6141
  }
6174
6142
  if (node.name) {
6175
- output.push(QuoteUtils.quote(node.name));
6143
+ output.push(QuoteUtils.quoteIdentifier(node.name));
6176
6144
  }
6177
6145
  if (node.behavior === 'DROP_CASCADE') {
6178
6146
  output.push('CASCADE');
@@ -6181,7 +6149,7 @@ export class Deparser {
6181
6149
  case 'V':
6182
6150
  output.push('VALIDATE', 'CONSTRAINT');
6183
6151
  if (node.name) {
6184
- output.push(QuoteUtils.quote(node.name));
6152
+ output.push(QuoteUtils.quoteIdentifier(node.name));
6185
6153
  }
6186
6154
  break;
6187
6155
  case 'O':
@@ -6570,7 +6538,7 @@ export class Deparser {
6570
6538
  const output = [];
6571
6539
  const initialParts = ['CREATE', 'POLICY'];
6572
6540
  if (node.policy_name) {
6573
- initialParts.push(QuoteUtils.quote(node.policy_name));
6541
+ initialParts.push(QuoteUtils.quoteIdentifier(node.policy_name));
6574
6542
  }
6575
6543
  output.push(initialParts.join(' '));
6576
6544
  // Add ON clause on new line in pretty mode
@@ -6647,7 +6615,7 @@ export class Deparser {
6647
6615
  AlterPolicyStmt(node, context) {
6648
6616
  const output = ['ALTER', 'POLICY'];
6649
6617
  if (node.policy_name) {
6650
- output.push(QuoteUtils.quote(node.policy_name));
6618
+ output.push(QuoteUtils.quoteIdentifier(node.policy_name));
6651
6619
  }
6652
6620
  if (node.table) {
6653
6621
  output.push('ON');
@@ -6683,7 +6651,7 @@ export class Deparser {
6683
6651
  }
6684
6652
  output.push('SERVER');
6685
6653
  if (node.servername) {
6686
- output.push(`"${node.servername}"`);
6654
+ output.push(QuoteUtils.quoteIdentifier(node.servername));
6687
6655
  }
6688
6656
  if (node.options && node.options.length > 0) {
6689
6657
  output.push('OPTIONS');
@@ -6731,7 +6699,7 @@ export class Deparser {
6731
6699
  CreatePublicationStmt(node, context) {
6732
6700
  const output = ['CREATE', 'PUBLICATION'];
6733
6701
  if (node.pubname) {
6734
- output.push(`"${node.pubname}"`);
6702
+ output.push(QuoteUtils.quoteIdentifier(node.pubname));
6735
6703
  }
6736
6704
  if (node.pubobjects && node.pubobjects.length > 0) {
6737
6705
  output.push('FOR', 'TABLE');
@@ -6751,7 +6719,7 @@ export class Deparser {
6751
6719
  CreateSubscriptionStmt(node, context) {
6752
6720
  const output = ['CREATE', 'SUBSCRIPTION'];
6753
6721
  if (node.subname) {
6754
- output.push(`"${node.subname}"`);
6722
+ output.push(QuoteUtils.quoteIdentifier(node.subname));
6755
6723
  }
6756
6724
  output.push('CONNECTION');
6757
6725
  if (node.conninfo) {
@@ -6772,7 +6740,7 @@ export class Deparser {
6772
6740
  AlterPublicationStmt(node, context) {
6773
6741
  const output = ['ALTER', 'PUBLICATION'];
6774
6742
  if (node.pubname) {
6775
- output.push(`"${node.pubname}"`);
6743
+ output.push(QuoteUtils.quoteIdentifier(node.pubname));
6776
6744
  }
6777
6745
  if (node.action) {
6778
6746
  switch (node.action) {
@@ -6807,7 +6775,7 @@ export class Deparser {
6807
6775
  AlterSubscriptionStmt(node, context) {
6808
6776
  const output = ['ALTER', 'SUBSCRIPTION'];
6809
6777
  if (node.subname) {
6810
- output.push(`"${node.subname}"`);
6778
+ output.push(QuoteUtils.quoteIdentifier(node.subname));
6811
6779
  }
6812
6780
  if (node.kind) {
6813
6781
  switch (node.kind) {
@@ -6853,7 +6821,7 @@ export class Deparser {
6853
6821
  output.push('IF EXISTS');
6854
6822
  }
6855
6823
  if (node.subname) {
6856
- output.push(`"${node.subname}"`);
6824
+ output.push(QuoteUtils.quoteIdentifier(node.subname));
6857
6825
  }
6858
6826
  if (node.behavior) {
6859
6827
  switch (node.behavior) {
@@ -7098,7 +7066,7 @@ export class Deparser {
7098
7066
  ClosePortalStmt(node, context) {
7099
7067
  const output = ['CLOSE'];
7100
7068
  if (node.portalname) {
7101
- output.push(QuoteUtils.quote(node.portalname));
7069
+ output.push(QuoteUtils.quoteIdentifier(node.portalname));
7102
7070
  }
7103
7071
  else {
7104
7072
  output.push('ALL');
@@ -7156,7 +7124,7 @@ export class Deparser {
7156
7124
  output.push('ALL');
7157
7125
  }
7158
7126
  if (node.portalname) {
7159
- output.push(QuoteUtils.quote(node.portalname));
7127
+ output.push(QuoteUtils.quoteIdentifier(node.portalname));
7160
7128
  }
7161
7129
  return output.join(' ');
7162
7130
  }
@@ -7226,7 +7194,7 @@ export class Deparser {
7226
7194
  AlterFdwStmt(node, context) {
7227
7195
  const output = ['ALTER', 'FOREIGN', 'DATA', 'WRAPPER'];
7228
7196
  if (node.fdwname) {
7229
- output.push(QuoteUtils.quote(node.fdwname));
7197
+ output.push(QuoteUtils.quoteIdentifier(node.fdwname));
7230
7198
  }
7231
7199
  if (node.func_options && node.func_options.length > 0) {
7232
7200
  const fdwContext = context.spawn('AlterFdwStmt');
@@ -7247,7 +7215,7 @@ export class Deparser {
7247
7215
  output.push('IF', 'NOT', 'EXISTS');
7248
7216
  }
7249
7217
  if (node.servername) {
7250
- output.push(QuoteUtils.quote(node.servername));
7218
+ output.push(QuoteUtils.quoteIdentifier(node.servername));
7251
7219
  }
7252
7220
  if (node.servertype) {
7253
7221
  output.push('TYPE', QuoteUtils.escape(node.servertype));
@@ -7256,7 +7224,7 @@ export class Deparser {
7256
7224
  output.push('VERSION', QuoteUtils.escape(node.version));
7257
7225
  }
7258
7226
  if (node.fdwname) {
7259
- output.push('FOREIGN', 'DATA', 'WRAPPER', QuoteUtils.quote(node.fdwname));
7227
+ output.push('FOREIGN', 'DATA', 'WRAPPER', QuoteUtils.quoteIdentifier(node.fdwname));
7260
7228
  }
7261
7229
  if (node.options && node.options.length > 0) {
7262
7230
  output.push('OPTIONS');
@@ -7271,7 +7239,7 @@ export class Deparser {
7271
7239
  AlterForeignServerStmt(node, context) {
7272
7240
  const output = ['ALTER', 'SERVER'];
7273
7241
  if (node.servername) {
7274
- output.push(QuoteUtils.quote(node.servername));
7242
+ output.push(QuoteUtils.quoteIdentifier(node.servername));
7275
7243
  }
7276
7244
  if (node.version) {
7277
7245
  output.push('VERSION', QuoteUtils.escape(node.version));
@@ -7296,7 +7264,7 @@ export class Deparser {
7296
7264
  }
7297
7265
  output.push('SERVER');
7298
7266
  if (node.servername) {
7299
- output.push(QuoteUtils.quote(node.servername));
7267
+ output.push(QuoteUtils.quoteIdentifier(node.servername));
7300
7268
  }
7301
7269
  if (node.options && node.options.length > 0) {
7302
7270
  output.push('OPTIONS');
@@ -7320,14 +7288,14 @@ export class Deparser {
7320
7288
  }
7321
7289
  output.push('SERVER');
7322
7290
  if (node.servername) {
7323
- output.push(QuoteUtils.quote(node.servername));
7291
+ output.push(QuoteUtils.quoteIdentifier(node.servername));
7324
7292
  }
7325
7293
  return output.join(' ');
7326
7294
  }
7327
7295
  ImportForeignSchemaStmt(node, context) {
7328
7296
  const output = ['IMPORT', 'FOREIGN', 'SCHEMA'];
7329
7297
  if (node.remote_schema) {
7330
- output.push(QuoteUtils.quote(node.remote_schema));
7298
+ output.push(QuoteUtils.quoteIdentifier(node.remote_schema));
7331
7299
  }
7332
7300
  if (node.list_type) {
7333
7301
  switch (node.list_type) {
@@ -7353,11 +7321,11 @@ export class Deparser {
7353
7321
  }
7354
7322
  output.push('FROM', 'SERVER');
7355
7323
  if (node.server_name) {
7356
- output.push(QuoteUtils.quote(node.server_name));
7324
+ output.push(QuoteUtils.quoteIdentifier(node.server_name));
7357
7325
  }
7358
7326
  output.push('INTO');
7359
7327
  if (node.local_schema) {
7360
- output.push(QuoteUtils.quote(node.local_schema));
7328
+ output.push(QuoteUtils.quoteIdentifier(node.local_schema));
7361
7329
  }
7362
7330
  if (node.options && node.options.length > 0) {
7363
7331
  const importSchemaContext = context.spawn('ImportForeignSchemaStmt');
@@ -7371,7 +7339,7 @@ export class Deparser {
7371
7339
  if (node.relation) {
7372
7340
  output.push(this.RangeVar(node.relation, context));
7373
7341
  if (node.indexname) {
7374
- output.push('USING', `"${node.indexname}"`);
7342
+ output.push('USING', QuoteUtils.quoteIdentifier(node.indexname));
7375
7343
  }
7376
7344
  }
7377
7345
  if (node.params && node.params.length > 0) {
@@ -7435,7 +7403,7 @@ export class Deparser {
7435
7403
  output.push(this.RangeVar(node.relation, context));
7436
7404
  }
7437
7405
  if (node.name) {
7438
- output.push(`"${node.name}"`);
7406
+ output.push(QuoteUtils.quoteIdentifier(node.name));
7439
7407
  }
7440
7408
  return output.join(' ');
7441
7409
  }
@@ -7475,7 +7443,7 @@ export class Deparser {
7475
7443
  if (!node.dbname) {
7476
7444
  throw new Error('CreatedbStmt requires dbname');
7477
7445
  }
7478
- output.push(`"${node.dbname}"`);
7446
+ output.push(QuoteUtils.quoteIdentifier(node.dbname));
7479
7447
  if (node.options && node.options.length > 0) {
7480
7448
  const options = ListUtils.unwrapList(node.options)
7481
7449
  .map(option => this.visit(option, context))
@@ -7492,7 +7460,7 @@ export class Deparser {
7492
7460
  if (!node.dbname) {
7493
7461
  throw new Error('DropdbStmt requires dbname');
7494
7462
  }
7495
- output.push(`"${node.dbname}"`);
7463
+ output.push(QuoteUtils.quoteIdentifier(node.dbname));
7496
7464
  if (node.options && node.options.length > 0) {
7497
7465
  const options = ListUtils.unwrapList(node.options)
7498
7466
  .map(option => this.visit(option, context))
@@ -7590,7 +7558,7 @@ export class Deparser {
7590
7558
  case 'OBJECT_POLICY':
7591
7559
  output.push('POLICY');
7592
7560
  if (node.subname) {
7593
- output.push(QuoteUtils.quote(node.subname));
7561
+ output.push(QuoteUtils.quoteIdentifier(node.subname));
7594
7562
  }
7595
7563
  break;
7596
7564
  case 'OBJECT_PUBLICATION':
@@ -7648,7 +7616,7 @@ export class Deparser {
7648
7616
  }
7649
7617
  // Handle OBJECT_RULE special case: rule_name ON table_name format
7650
7618
  if (node.renameType === 'OBJECT_RULE' && node.subname && node.relation) {
7651
- output.push(QuoteUtils.quote(node.subname));
7619
+ output.push(QuoteUtils.quoteIdentifier(node.subname));
7652
7620
  output.push('ON');
7653
7621
  output.push(this.RangeVar(node.relation, context));
7654
7622
  }
@@ -7667,7 +7635,7 @@ export class Deparser {
7667
7635
  if (items.length === 2) {
7668
7636
  const accessMethod = items[0].String?.sval || '';
7669
7637
  const objectName = items[1].String?.sval || '';
7670
- output.push(`${QuoteUtils.quote(objectName)} USING ${accessMethod}`);
7638
+ output.push(`${QuoteUtils.quoteIdentifier(objectName)} USING ${accessMethod}`);
7671
7639
  }
7672
7640
  else {
7673
7641
  output.push(this.visit(node.object, context));
@@ -7688,19 +7656,19 @@ export class Deparser {
7688
7656
  }
7689
7657
  }
7690
7658
  if (node.renameType === 'OBJECT_COLUMN' && node.subname) {
7691
- output.push('RENAME COLUMN', `"${node.subname}"`, 'TO');
7659
+ output.push('RENAME COLUMN', QuoteUtils.quoteIdentifier(node.subname), 'TO');
7692
7660
  }
7693
7661
  else if (node.renameType === 'OBJECT_DOMCONSTRAINT' && node.subname) {
7694
- output.push('RENAME CONSTRAINT', `"${node.subname}"`, 'TO');
7662
+ output.push('RENAME CONSTRAINT', QuoteUtils.quoteIdentifier(node.subname), 'TO');
7695
7663
  }
7696
7664
  else if (node.renameType === 'OBJECT_TABCONSTRAINT' && node.subname) {
7697
- output.push('RENAME CONSTRAINT', `"${node.subname}"`, 'TO');
7665
+ output.push('RENAME CONSTRAINT', QuoteUtils.quoteIdentifier(node.subname), 'TO');
7698
7666
  }
7699
7667
  else if (node.renameType === 'OBJECT_ATTRIBUTE' && node.subname) {
7700
- output.push('RENAME ATTRIBUTE', `"${node.subname}"`, 'TO');
7668
+ output.push('RENAME ATTRIBUTE', QuoteUtils.quoteIdentifier(node.subname), 'TO');
7701
7669
  }
7702
7670
  else if (node.renameType === 'OBJECT_ROLE' && node.subname) {
7703
- output.push(`"${node.subname}"`, 'RENAME TO');
7671
+ output.push(QuoteUtils.quoteIdentifier(node.subname), 'RENAME TO');
7704
7672
  }
7705
7673
  else if (node.renameType === 'OBJECT_SCHEMA' && node.subname) {
7706
7674
  output.push(this.quoteIfNeeded(node.subname), 'RENAME TO');
@@ -7714,7 +7682,7 @@ export class Deparser {
7714
7682
  if (!node.newname) {
7715
7683
  throw new Error('RenameStmt requires newname');
7716
7684
  }
7717
- output.push(QuoteUtils.quote(node.newname));
7685
+ output.push(QuoteUtils.quoteIdentifier(node.newname));
7718
7686
  // Handle CASCADE/RESTRICT behavior for RENAME operations
7719
7687
  if (node.behavior === 'DROP_CASCADE') {
7720
7688
  output.push('CASCADE');
@@ -7737,7 +7705,7 @@ export class Deparser {
7737
7705
  if (items.length === 2) {
7738
7706
  const accessMethod = items[0].String?.sval || '';
7739
7707
  const objectName = items[1].String?.sval || '';
7740
- output.push(`${QuoteUtils.quote(objectName)} USING ${accessMethod}`);
7708
+ output.push(`${QuoteUtils.quoteIdentifier(objectName)} USING ${accessMethod}`);
7741
7709
  }
7742
7710
  else {
7743
7711
  output.push(this.visit(node.object, context));
@@ -8007,7 +7975,7 @@ export class Deparser {
8007
7975
  SecLabelStmt(node, context) {
8008
7976
  const output = ['SECURITY LABEL'];
8009
7977
  if (node.provider) {
8010
- output.push('FOR', `"${node.provider}"`);
7978
+ output.push('FOR', QuoteUtils.quoteIdentifier(node.provider));
8011
7979
  }
8012
7980
  output.push('ON');
8013
7981
  if (node.objtype) {
@@ -8160,7 +8128,7 @@ export class Deparser {
8160
8128
  }
8161
8129
  output.push('LANGUAGE');
8162
8130
  if (node.plname) {
8163
- output.push(QuoteUtils.quote(node.plname));
8131
+ output.push(QuoteUtils.quoteIdentifier(node.plname));
8164
8132
  }
8165
8133
  if (node.plhandler && node.plhandler.length > 0) {
8166
8134
  output.push('HANDLER');
@@ -8196,7 +8164,7 @@ export class Deparser {
8196
8164
  }
8197
8165
  output.push('LANGUAGE');
8198
8166
  if (node.lang) {
8199
- output.push(QuoteUtils.quote(node.lang));
8167
+ output.push(QuoteUtils.quoteIdentifier(node.lang));
8200
8168
  }
8201
8169
  output.push('(');
8202
8170
  const transforms = [];
@@ -8224,7 +8192,7 @@ export class Deparser {
8224
8192
  }
8225
8193
  output.push('TRIGGER');
8226
8194
  if (node.trigname) {
8227
- output.push(QuoteUtils.quote(node.trigname));
8195
+ output.push(QuoteUtils.quoteIdentifier(node.trigname));
8228
8196
  }
8229
8197
  if (context.isPretty()) {
8230
8198
  const components = [];
@@ -8388,14 +8356,14 @@ export class Deparser {
8388
8356
  output.push('OLD TABLE AS');
8389
8357
  }
8390
8358
  if (node.name) {
8391
- output.push(QuoteUtils.quote(node.name));
8359
+ output.push(QuoteUtils.quoteIdentifier(node.name));
8392
8360
  }
8393
8361
  return output.join(' ');
8394
8362
  }
8395
8363
  CreateEventTrigStmt(node, context) {
8396
8364
  const output = ['CREATE EVENT TRIGGER'];
8397
8365
  if (node.trigname) {
8398
- output.push(QuoteUtils.quote(node.trigname));
8366
+ output.push(QuoteUtils.quoteIdentifier(node.trigname));
8399
8367
  }
8400
8368
  output.push('ON');
8401
8369
  if (node.eventname) {
@@ -8421,7 +8389,7 @@ export class Deparser {
8421
8389
  AlterEventTrigStmt(node, context) {
8422
8390
  const output = ['ALTER EVENT TRIGGER'];
8423
8391
  if (node.trigname) {
8424
- output.push(QuoteUtils.quote(node.trigname));
8392
+ output.push(QuoteUtils.quoteIdentifier(node.trigname));
8425
8393
  }
8426
8394
  if (node.tgenabled) {
8427
8395
  switch (node.tgenabled) {
@@ -8556,11 +8524,11 @@ export class Deparser {
8556
8524
  }
8557
8525
  output.push('ALL', 'IN', 'TABLESPACE');
8558
8526
  if (node.orig_tablespacename) {
8559
- output.push(QuoteUtils.quote(node.orig_tablespacename));
8527
+ output.push(QuoteUtils.quoteIdentifier(node.orig_tablespacename));
8560
8528
  }
8561
8529
  output.push('SET', 'TABLESPACE');
8562
8530
  if (node.new_tablespacename) {
8563
- output.push(QuoteUtils.quote(node.new_tablespacename));
8531
+ output.push(QuoteUtils.quoteIdentifier(node.new_tablespacename));
8564
8532
  }
8565
8533
  if (node.nowait) {
8566
8534
  output.push('NOWAIT');
@@ -8584,10 +8552,10 @@ export class Deparser {
8584
8552
  const sequenceName = [];
8585
8553
  const seq = node.sequence;
8586
8554
  if (seq.schemaname) {
8587
- sequenceName.push(QuoteUtils.quote(seq.schemaname));
8555
+ sequenceName.push(QuoteUtils.quoteIdentifier(seq.schemaname));
8588
8556
  }
8589
8557
  if (seq.relname) {
8590
- sequenceName.push(QuoteUtils.quote(seq.relname));
8558
+ sequenceName.push(QuoteUtils.quoteIdentifier(seq.relname));
8591
8559
  }
8592
8560
  output.push(sequenceName.join('.'));
8593
8561
  }
@@ -8621,10 +8589,10 @@ export class Deparser {
8621
8589
  const sequenceName = [];
8622
8590
  const seq = node.sequence;
8623
8591
  if (seq.schemaname) {
8624
- sequenceName.push(QuoteUtils.quote(seq.schemaname));
8592
+ sequenceName.push(QuoteUtils.quoteIdentifier(seq.schemaname));
8625
8593
  }
8626
8594
  if (seq.relname) {
8627
- sequenceName.push(QuoteUtils.quote(seq.relname));
8595
+ sequenceName.push(QuoteUtils.quoteIdentifier(seq.relname));
8628
8596
  }
8629
8597
  output.push(sequenceName.join('.'));
8630
8598
  }
@@ -8971,7 +8939,7 @@ export class Deparser {
8971
8939
  }
8972
8940
  aliasname(node, context) {
8973
8941
  if (typeof node === 'string') {
8974
- return QuoteUtils.quote(node);
8942
+ return QuoteUtils.quoteIdentifier(node);
8975
8943
  }
8976
8944
  return this.visit(node, context);
8977
8945
  }
@@ -9003,13 +8971,8 @@ export class Deparser {
9003
8971
  const defName = defElem.defname;
9004
8972
  const defValue = defElem.arg;
9005
8973
  if (defName && defValue) {
9006
- let preservedDefName;
9007
- if (Deparser.needsQuotes(defName)) {
9008
- preservedDefName = `"${defName}"`;
9009
- }
9010
- else {
9011
- preservedDefName = this.preserveOperatorDefElemCase(defName);
9012
- }
8974
+ const quotedDefName = QuoteUtils.quoteIdentifier(defName);
8975
+ const preservedDefName = quotedDefName !== defName ? quotedDefName : this.preserveOperatorDefElemCase(defName);
9013
8976
  if ((defName.toLowerCase() === 'commutator' || defName.toLowerCase() === 'negator') && defValue.List) {
9014
8977
  const listItems = ListUtils.unwrapList(defValue.List.items);
9015
8978
  if (listItems.length === 1 && listItems[0].String) {
@@ -9025,7 +8988,7 @@ export class Deparser {
9025
8988
  else if (defName && !defValue) {
9026
8989
  // Handle boolean flags like HASHES, MERGES - preserve original case
9027
8990
  if (defName === 'Hashes' || defName === 'Merges') {
9028
- return `"${defName}"`;
8991
+ return QuoteUtils.quoteIdentifier(defName);
9029
8992
  }
9030
8993
  return this.preserveOperatorDefElemCase(defName).toUpperCase();
9031
8994
  }
@@ -9164,13 +9127,8 @@ export class Deparser {
9164
9127
  const defName = defElem.defname;
9165
9128
  const defValue = defElem.arg;
9166
9129
  if (defName && defValue) {
9167
- let preservedDefName;
9168
- if (Deparser.needsQuotes(defName)) {
9169
- preservedDefName = `"${defName}"`;
9170
- }
9171
- else {
9172
- preservedDefName = defName;
9173
- }
9130
+ const quotedDefName = QuoteUtils.quoteIdentifier(defName);
9131
+ const preservedDefName = quotedDefName !== defName ? quotedDefName : defName;
9174
9132
  // Handle String arguments with single quotes for string literals
9175
9133
  if (defValue.String) {
9176
9134
  return `${preservedDefName} = '${defValue.String.sval}'`;
@@ -9325,7 +9283,7 @@ export class Deparser {
9325
9283
  AlterDatabaseStmt(node, context) {
9326
9284
  const output = ['ALTER', 'DATABASE'];
9327
9285
  if (node.dbname) {
9328
- output.push(QuoteUtils.quote(node.dbname));
9286
+ output.push(QuoteUtils.quoteIdentifier(node.dbname));
9329
9287
  }
9330
9288
  if (node.options && node.options.length > 0) {
9331
9289
  const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context));
@@ -9336,7 +9294,7 @@ export class Deparser {
9336
9294
  AlterDatabaseRefreshCollStmt(node, context) {
9337
9295
  const output = ['ALTER', 'DATABASE'];
9338
9296
  if (node.dbname) {
9339
- output.push(QuoteUtils.quote(node.dbname));
9297
+ output.push(QuoteUtils.quoteIdentifier(node.dbname));
9340
9298
  }
9341
9299
  output.push('REFRESH', 'COLLATION', 'VERSION');
9342
9300
  return output.join(' ');
@@ -9344,7 +9302,7 @@ export class Deparser {
9344
9302
  AlterDatabaseSetStmt(node, context) {
9345
9303
  const output = ['ALTER', 'DATABASE'];
9346
9304
  if (node.dbname) {
9347
- output.push(QuoteUtils.quote(node.dbname));
9305
+ output.push(QuoteUtils.quoteIdentifier(node.dbname));
9348
9306
  }
9349
9307
  if (node.setstmt) {
9350
9308
  const setClause = this.VariableSetStmt(node.setstmt, context);
@@ -9355,7 +9313,7 @@ export class Deparser {
9355
9313
  DeclareCursorStmt(node, context) {
9356
9314
  const output = ['DECLARE'];
9357
9315
  if (node.portalname) {
9358
- output.push(QuoteUtils.quote(node.portalname));
9316
+ output.push(QuoteUtils.quoteIdentifier(node.portalname));
9359
9317
  }
9360
9318
  // Handle cursor options before CURSOR keyword
9361
9319
  const cursorOptions = [];
@@ -9397,7 +9355,7 @@ export class Deparser {
9397
9355
  else if (node.pubobjtype === 'PUBLICATIONOBJ_TABLES_IN_SCHEMA') {
9398
9356
  output.push('TABLES IN SCHEMA');
9399
9357
  if (node.name) {
9400
- output.push(QuoteUtils.quote(node.name));
9358
+ output.push(QuoteUtils.quoteIdentifier(node.name));
9401
9359
  }
9402
9360
  }
9403
9361
  else if (node.pubobjtype === 'PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA') {
@@ -9423,7 +9381,7 @@ export class Deparser {
9423
9381
  CreateAmStmt(node, context) {
9424
9382
  const output = ['CREATE', 'ACCESS', 'METHOD'];
9425
9383
  if (node.amname) {
9426
- output.push(QuoteUtils.quote(node.amname));
9384
+ output.push(QuoteUtils.quoteIdentifier(node.amname));
9427
9385
  }
9428
9386
  output.push('TYPE');
9429
9387
  switch (node.amtype) {
@@ -9483,7 +9441,7 @@ export class Deparser {
9483
9441
  }
9484
9442
  }
9485
9443
  if (node.tableSpaceName) {
9486
- output.push('TABLESPACE', QuoteUtils.quote(node.tableSpaceName));
9444
+ output.push('TABLESPACE', QuoteUtils.quoteIdentifier(node.tableSpaceName));
9487
9445
  }
9488
9446
  return output.join(' ');
9489
9447
  }
@@ -9641,7 +9599,7 @@ export class Deparser {
9641
9599
  RangeTableFuncCol(node, context) {
9642
9600
  const output = [];
9643
9601
  if (node.colname) {
9644
- output.push(QuoteUtils.quote(node.colname));
9602
+ output.push(QuoteUtils.quoteIdentifier(node.colname));
9645
9603
  }
9646
9604
  if (node.for_ordinality) {
9647
9605
  output.push('FOR ORDINALITY');
@@ -9787,10 +9745,10 @@ export class Deparser {
9787
9745
  if (node.op === 'IS_XMLPI') {
9788
9746
  if (node.name && node.args && node.args.length > 0) {
9789
9747
  const argStrs = ListUtils.unwrapList(node.args).map(arg => this.visit(arg, context));
9790
- return `xmlpi(name ${QuoteUtils.quote(node.name)}, ${argStrs.join(', ')})`;
9748
+ return `xmlpi(name ${QuoteUtils.quoteIdentifier(node.name)}, ${argStrs.join(', ')})`;
9791
9749
  }
9792
9750
  else if (node.name) {
9793
- return `xmlpi(name ${QuoteUtils.quote(node.name)})`;
9751
+ return `xmlpi(name ${QuoteUtils.quoteIdentifier(node.name)})`;
9794
9752
  }
9795
9753
  else {
9796
9754
  return 'XMLPI()';
@@ -9805,7 +9763,7 @@ export class Deparser {
9805
9763
  output.push('XMLELEMENT');
9806
9764
  const elementParts = [];
9807
9765
  if (node.name) {
9808
- elementParts.push(`NAME ${QuoteUtils.quote(node.name)}`);
9766
+ elementParts.push(`NAME ${QuoteUtils.quoteIdentifier(node.name)}`);
9809
9767
  }
9810
9768
  if (node.named_args && node.named_args.length > 0) {
9811
9769
  const namedArgStrs = ListUtils.unwrapList(node.named_args).map(arg => this.visit(arg, context));
@@ -9905,7 +9863,7 @@ export class Deparser {
9905
9863
  // Handle name and args for operations that don't have special handling
9906
9864
  if (node.op !== 'IS_XMLELEMENT' && node.op !== 'IS_XMLPARSE' && node.op !== 'IS_XMLROOT' && node.op !== 'IS_DOCUMENT') {
9907
9865
  if (node.name) {
9908
- const quotedName = QuoteUtils.quote(node.name);
9866
+ const quotedName = QuoteUtils.quoteIdentifier(node.name);
9909
9867
  output.push(`NAME ${quotedName}`);
9910
9868
  }
9911
9869
  if (node.args && node.args.length > 0) {
@@ -9926,26 +9884,26 @@ export class Deparser {
9926
9884
  }
9927
9885
  schemaname(node, context) {
9928
9886
  if (typeof node === 'string') {
9929
- return QuoteUtils.quote(node);
9887
+ return QuoteUtils.quoteIdentifier(node);
9930
9888
  }
9931
9889
  if (node && node.String && node.String.sval) {
9932
- return QuoteUtils.quote(node.String.sval);
9890
+ return QuoteUtils.quoteIdentifier(node.String.sval);
9933
9891
  }
9934
9892
  // Handle other node types without recursion
9935
9893
  if (node && typeof node === 'object') {
9936
9894
  if (node.sval !== undefined) {
9937
- return QuoteUtils.quote(node.sval);
9895
+ return QuoteUtils.quoteIdentifier(node.sval);
9938
9896
  }
9939
9897
  // Handle List nodes that might contain schema names
9940
9898
  if (node.List && Array.isArray(node.List.items)) {
9941
9899
  const items = node.List.items;
9942
9900
  if (items.length > 0 && items[0].String && items[0].String.sval) {
9943
- return QuoteUtils.quote(items[0].String.sval);
9901
+ return QuoteUtils.quoteIdentifier(items[0].String.sval);
9944
9902
  }
9945
9903
  }
9946
9904
  // For other complex nodes, try to extract string value without recursion
9947
9905
  if (node.val !== undefined) {
9948
- return QuoteUtils.quote(node.val);
9906
+ return QuoteUtils.quoteIdentifier(node.val);
9949
9907
  }
9950
9908
  return '';
9951
9909
  }
@@ -10008,7 +9966,7 @@ export class Deparser {
10008
9966
  }
10009
9967
  output.push('RULE');
10010
9968
  if (node.rulename) {
10011
- output.push(QuoteUtils.quote(node.rulename));
9969
+ output.push(QuoteUtils.quoteIdentifier(node.rulename));
10012
9970
  }
10013
9971
  output.push('AS ON');
10014
9972
  if (node.event) {
@@ -10075,42 +10033,42 @@ export class Deparser {
10075
10033
  }
10076
10034
  relname(node, context) {
10077
10035
  if (typeof node === 'string') {
10078
- return QuoteUtils.quote(node);
10036
+ return QuoteUtils.quoteIdentifier(node);
10079
10037
  }
10080
10038
  if (node && node.String && node.String.sval) {
10081
- return QuoteUtils.quote(node.String.sval);
10039
+ return QuoteUtils.quoteIdentifier(node.String.sval);
10082
10040
  }
10083
10041
  if (node && typeof node === 'object' && node.relname) {
10084
- return QuoteUtils.quote(node.relname);
10042
+ return QuoteUtils.quoteIdentifier(node.relname);
10085
10043
  }
10086
10044
  return this.visit(node, context);
10087
10045
  }
10088
10046
  rel(node, context) {
10089
10047
  if (typeof node === 'string') {
10090
- return QuoteUtils.quote(node);
10048
+ return QuoteUtils.quoteIdentifier(node);
10091
10049
  }
10092
10050
  if (node && node.String && node.String.sval) {
10093
- return QuoteUtils.quote(node.String.sval);
10051
+ return QuoteUtils.quoteIdentifier(node.String.sval);
10094
10052
  }
10095
10053
  if (node && node.RangeVar) {
10096
10054
  return this.RangeVar(node.RangeVar, context);
10097
10055
  }
10098
10056
  if (node && typeof node === 'object' && node.relname) {
10099
- return QuoteUtils.quote(node.relname);
10057
+ return QuoteUtils.quoteIdentifier(node.relname);
10100
10058
  }
10101
10059
  return this.visit(node, context);
10102
10060
  }
10103
10061
  objname(node, context) {
10104
10062
  if (typeof node === 'string') {
10105
- return QuoteUtils.quote(node);
10063
+ return QuoteUtils.quoteIdentifier(node);
10106
10064
  }
10107
10065
  if (node && node.String && node.String.sval) {
10108
- return QuoteUtils.quote(node.String.sval);
10066
+ return QuoteUtils.quoteIdentifier(node.String.sval);
10109
10067
  }
10110
10068
  if (Array.isArray(node)) {
10111
10069
  const parts = node.map(part => {
10112
10070
  if (part && part.String && part.String.sval) {
10113
- return QuoteUtils.quote(part.String.sval);
10071
+ return QuoteUtils.quoteIdentifier(part.String.sval);
10114
10072
  }
10115
10073
  return this.visit(part, context);
10116
10074
  });
@@ -10181,7 +10139,7 @@ export class Deparser {
10181
10139
  CurrentOfExpr(node, context) {
10182
10140
  const output = ['CURRENT OF'];
10183
10141
  if (node.cursor_name) {
10184
- output.push(QuoteUtils.quote(node.cursor_name));
10142
+ output.push(QuoteUtils.quoteIdentifier(node.cursor_name));
10185
10143
  }
10186
10144
  if (node.cursor_param > 0) {
10187
10145
  output.push(`$${node.cursor_param}`);
@@ -10264,7 +10222,7 @@ export class Deparser {
10264
10222
  if (items.length === 2) {
10265
10223
  const schemaName = items[0].String?.sval || '';
10266
10224
  const domainName = items[1].String?.sval || '';
10267
- output.push(`${QuoteUtils.quote(schemaName)}.${QuoteUtils.quote(domainName)}`);
10225
+ output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, domainName));
10268
10226
  }
10269
10227
  else {
10270
10228
  output.push(this.visit(node.object, context));
@@ -10276,7 +10234,7 @@ export class Deparser {
10276
10234
  if (items.length === 2) {
10277
10235
  const schemaName = items[0].String?.sval || '';
10278
10236
  const typeName = items[1].String?.sval || '';
10279
- output.push(`${QuoteUtils.quote(schemaName)}.${QuoteUtils.quote(typeName)}`);
10237
+ output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, typeName));
10280
10238
  }
10281
10239
  else {
10282
10240
  output.push(this.visit(node.object, context));
@@ -10288,7 +10246,7 @@ export class Deparser {
10288
10246
  if (items.length === 2) {
10289
10247
  const schemaName = items[0].String?.sval || '';
10290
10248
  const conversionName = items[1].String?.sval || '';
10291
- output.push(`${QuoteUtils.quote(schemaName)}.${QuoteUtils.quote(conversionName)}`);
10249
+ output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, conversionName));
10292
10250
  }
10293
10251
  else {
10294
10252
  output.push(this.visit(node.object, context));
@@ -10300,7 +10258,7 @@ export class Deparser {
10300
10258
  if (items.length === 2) {
10301
10259
  const schemaName = items[0].String?.sval || '';
10302
10260
  const parserName = items[1].String?.sval || '';
10303
- output.push(`${QuoteUtils.quote(schemaName)}.${QuoteUtils.quote(parserName)}`);
10261
+ output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, parserName));
10304
10262
  }
10305
10263
  else {
10306
10264
  output.push(this.visit(node.object, context));
@@ -10312,7 +10270,7 @@ export class Deparser {
10312
10270
  if (items.length === 2) {
10313
10271
  const schemaName = items[0].String?.sval || '';
10314
10272
  const configName = items[1].String?.sval || '';
10315
- output.push(`${QuoteUtils.quote(schemaName)}.${QuoteUtils.quote(configName)}`);
10273
+ output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, configName));
10316
10274
  }
10317
10275
  else {
10318
10276
  output.push(this.visit(node.object, context));
@@ -10324,7 +10282,7 @@ export class Deparser {
10324
10282
  if (items.length === 2) {
10325
10283
  const schemaName = items[0].String?.sval || '';
10326
10284
  const templateName = items[1].String?.sval || '';
10327
- output.push(`${QuoteUtils.quote(schemaName)}.${QuoteUtils.quote(templateName)}`);
10285
+ output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, templateName));
10328
10286
  }
10329
10287
  else {
10330
10288
  output.push(this.visit(node.object, context));
@@ -10336,7 +10294,7 @@ export class Deparser {
10336
10294
  if (items.length === 2) {
10337
10295
  const schemaName = items[0].String?.sval || '';
10338
10296
  const dictionaryName = items[1].String?.sval || '';
10339
- output.push(`${QuoteUtils.quote(schemaName)}.${QuoteUtils.quote(dictionaryName)}`);
10297
+ output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, dictionaryName));
10340
10298
  }
10341
10299
  else {
10342
10300
  output.push(this.visit(node.object, context));
@@ -10348,13 +10306,13 @@ export class Deparser {
10348
10306
  if (items.length === 2) {
10349
10307
  const accessMethod = items[0].String?.sval || '';
10350
10308
  const opClassName = items[1].String?.sval || '';
10351
- output.push(`${QuoteUtils.quote(opClassName)} USING ${accessMethod}`);
10309
+ output.push(`${QuoteUtils.quoteIdentifier(opClassName)} USING ${accessMethod}`);
10352
10310
  }
10353
10311
  else if (items.length === 3) {
10354
10312
  const accessMethod = items[0].String?.sval || '';
10355
10313
  const schemaName = items[1].String?.sval || '';
10356
10314
  const opClassName = items[2].String?.sval || '';
10357
- output.push(`${QuoteUtils.quote(schemaName)}.${QuoteUtils.quote(opClassName)} USING ${accessMethod}`);
10315
+ output.push(`${QuoteUtils.quoteQualifiedIdentifier(schemaName, opClassName)} USING ${accessMethod}`);
10358
10316
  }
10359
10317
  else {
10360
10318
  output.push(this.visit(node.object, context));
@@ -10366,13 +10324,13 @@ export class Deparser {
10366
10324
  if (items.length === 2) {
10367
10325
  const accessMethod = items[0].String?.sval || '';
10368
10326
  const opFamilyName = items[1].String?.sval || '';
10369
- output.push(`${QuoteUtils.quote(opFamilyName)} USING ${accessMethod}`);
10327
+ output.push(`${QuoteUtils.quoteIdentifier(opFamilyName)} USING ${accessMethod}`);
10370
10328
  }
10371
10329
  else if (items.length === 3) {
10372
10330
  const accessMethod = items[0].String?.sval || '';
10373
10331
  const schemaName = items[1].String?.sval || '';
10374
10332
  const opFamilyName = items[2].String?.sval || '';
10375
- output.push(`${QuoteUtils.quote(schemaName)}.${QuoteUtils.quote(opFamilyName)} USING ${accessMethod}`);
10333
+ output.push(`${QuoteUtils.quoteQualifiedIdentifier(schemaName, opFamilyName)} USING ${accessMethod}`);
10376
10334
  }
10377
10335
  else {
10378
10336
  output.push(this.visit(node.object, context));
@@ -10384,7 +10342,7 @@ export class Deparser {
10384
10342
  }
10385
10343
  output.push('SET SCHEMA');
10386
10344
  if (node.newschema) {
10387
- output.push(QuoteUtils.quote(node.newschema));
10345
+ output.push(QuoteUtils.quoteIdentifier(node.newschema));
10388
10346
  }
10389
10347
  return output.join(' ');
10390
10348
  }
@@ -10453,7 +10411,7 @@ export class Deparser {
10453
10411
  }
10454
10412
  if (node.servername) {
10455
10413
  output.push('SERVER');
10456
- output.push(QuoteUtils.quote(node.servername));
10414
+ output.push(QuoteUtils.quoteIdentifier(node.servername));
10457
10415
  }
10458
10416
  if (node.options && node.options.length > 0) {
10459
10417
  const foreignTableContext = context.spawn('CreateForeignTableStmt');