pgsql-deparser 18.4.1 → 18.4.3

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/deparser.d.ts CHANGED
@@ -172,6 +172,8 @@ export declare class Deparser implements DeparserVisitor {
172
172
  CheckPointStmt(node: t.CheckPointStmt, context: DeparserContext): string;
173
173
  LoadStmt(node: t.LoadStmt, context: DeparserContext): string;
174
174
  DiscardStmt(node: t.DiscardStmt, context: DeparserContext): string;
175
+ /** `schema.op` for an operator name list: schema parts quoted, the operator symbol as is. */
176
+ private qualifiedOperatorName;
175
177
  CommentStmt(node: t.CommentStmt, context: DeparserContext): string;
176
178
  LockStmt(node: t.LockStmt, context: DeparserContext): string;
177
179
  CreatePolicyStmt(node: t.CreatePolicyStmt, context: DeparserContext): string;
package/deparser.js CHANGED
@@ -4363,7 +4363,7 @@ class Deparser {
4363
4363
  if (objList && objList.List && objList.List.items) {
4364
4364
  const items = objList.List.items.map((item) => {
4365
4365
  if (item.String && item.String.sval) {
4366
- return item.String.sval;
4366
+ return quotes_1.QuoteUtils.quoteIdentifier(item.String.sval);
4367
4367
  }
4368
4368
  return this.visit(item, context);
4369
4369
  });
@@ -5557,10 +5557,13 @@ class Deparser {
5557
5557
  if (node.arg && this.getNodeType(node.arg) === 'List') {
5558
5558
  const listData = this.getNodeData(node.arg);
5559
5559
  const listItems = list_utils_1.ListUtils.unwrapList(listData.items);
5560
+ const preservedName = this.preserveOperatorDefElemCase(node.defname);
5560
5561
  if (listItems.length === 1 && listItems[0].String) {
5561
- const preservedName = this.preserveOperatorDefElemCase(node.defname);
5562
5562
  return `${preservedName} = ${listItems[0].String.sval}`;
5563
5563
  }
5564
+ if (listItems.length > 1 && listItems.every((item) => item.String)) {
5565
+ return `${preservedName} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
5566
+ }
5564
5567
  }
5565
5568
  }
5566
5569
  // Handle IndexElem opclassopts - MUST be first to preserve string types
@@ -5662,6 +5665,9 @@ class Deparser {
5662
5665
  if (listItems.length === 1 && listItems[0].String) {
5663
5666
  return `${node.defname} = ${listItems[0].String.sval}`;
5664
5667
  }
5668
+ if (listItems.length > 1 && listItems.every((item) => item.String)) {
5669
+ return `${node.defname} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
5670
+ }
5665
5671
  }
5666
5672
  }
5667
5673
  if (context.parentNodeTypes.includes('CreatedbStmt') || context.parentNodeTypes.includes('DropdbStmt')) {
@@ -6475,6 +6481,13 @@ class Deparser {
6475
6481
  throw new Error(`Unsupported DiscardStmt target: ${node.target}`);
6476
6482
  }
6477
6483
  }
6484
+ /** `schema.op` for an operator name list: schema parts quoted, the operator symbol as is. */
6485
+ qualifiedOperatorName(objname) {
6486
+ const names = list_utils_1.ListUtils.unwrapList(objname ?? []).map((n) => (n.String ? n.String.sval : 'unknown'));
6487
+ if (names.length === 0)
6488
+ return 'unknown';
6489
+ return [...names.slice(0, -1).map((n) => quotes_1.QuoteUtils.quoteIdentifier(n)), names[names.length - 1]].join('.');
6490
+ }
6478
6491
  CommentStmt(node, context) {
6479
6492
  const output = ['COMMENT ON'];
6480
6493
  if (node.objtype) {
@@ -6595,22 +6608,20 @@ class Deparser {
6595
6608
  }
6596
6609
  }
6597
6610
  else if (node.objtype === 'OBJECT_TRIGGER') {
6598
- if (objectParts.length === 2) {
6599
- const [table, trigger] = objectParts;
6600
- output.push(trigger);
6611
+ if (objectParts.length >= 2) {
6612
+ output.push(objectParts[objectParts.length - 1]);
6601
6613
  output.push('ON');
6602
- output.push(table);
6614
+ output.push(objectParts.slice(0, -1).join('.'));
6603
6615
  }
6604
6616
  else {
6605
6617
  output.push(objectParts.join('.'));
6606
6618
  }
6607
6619
  }
6608
6620
  else if (node.objtype === 'OBJECT_RULE') {
6609
- if (objectParts.length === 2) {
6610
- const [table, rule] = objectParts;
6611
- output.push(rule);
6621
+ if (objectParts.length >= 2) {
6622
+ output.push(objectParts[objectParts.length - 1]);
6612
6623
  output.push('ON');
6613
- output.push(table);
6624
+ output.push(objectParts.slice(0, -1).join('.'));
6614
6625
  }
6615
6626
  else {
6616
6627
  output.push(objectParts.join('.'));
@@ -6621,8 +6632,7 @@ class Deparser {
6621
6632
  // For operators, we need to handle ObjectWithArgs structure
6622
6633
  if (node.object && node.object.ObjectWithArgs) {
6623
6634
  const objWithArgs = node.object.ObjectWithArgs;
6624
- let operatorName = objWithArgs.objname && objWithArgs.objname[0] && objWithArgs.objname[0].String
6625
- ? objWithArgs.objname[0].String.sval : 'unknown';
6635
+ let operatorName = this.qualifiedOperatorName(objWithArgs.objname);
6626
6636
  if (operatorName.startsWith('"') && operatorName.endsWith('"')) {
6627
6637
  operatorName = operatorName.slice(1, -1);
6628
6638
  }
@@ -6660,7 +6670,13 @@ class Deparser {
6660
6670
  }
6661
6671
  else if (node.objtype === 'OBJECT_POLICY') {
6662
6672
  // Handle POLICY syntax: COMMENT ON POLICY policy_name ON table_name IS 'comment'
6663
- if (objectParts.length === 2) {
6673
+ if (objectParts.length === 3) {
6674
+ const [schema, table, policy] = objectParts;
6675
+ output.push(policy);
6676
+ output.push('ON');
6677
+ output.push(`${schema}.${table}`);
6678
+ }
6679
+ else if (objectParts.length === 2) {
6664
6680
  const [table, policy] = objectParts;
6665
6681
  output.push(policy);
6666
6682
  output.push('ON');
@@ -6683,6 +6699,9 @@ class Deparser {
6683
6699
  output.push(objectParts.join('.'));
6684
6700
  }
6685
6701
  }
6702
+ else if (node.objtype === 'OBJECT_CAST' && objectParts.length === 2) {
6703
+ output.push(`(${objectParts[0]} AS ${objectParts[1]})`);
6704
+ }
6686
6705
  else {
6687
6706
  output.push(objectParts.join('.'));
6688
6707
  }
@@ -6691,8 +6710,7 @@ class Deparser {
6691
6710
  else if (node.objtype === 'OBJECT_OPERATOR' && node.object && node.object.ObjectWithArgs) {
6692
6711
  // Handle direct ObjectWithArgs for OPERATOR syntax: COMMENT ON OPERATOR -(NONE, integer) IS 'comment'
6693
6712
  const objWithArgs = node.object.ObjectWithArgs;
6694
- let operatorName = objWithArgs.objname && objWithArgs.objname[0] && objWithArgs.objname[0].String
6695
- ? objWithArgs.objname[0].String.sval : 'unknown';
6713
+ let operatorName = this.qualifiedOperatorName(objWithArgs.objname);
6696
6714
  // Remove quotes from operator name if present
6697
6715
  if (operatorName.startsWith('"') && operatorName.endsWith('"')) {
6698
6716
  operatorName = operatorName.slice(1, -1);
@@ -8060,8 +8078,11 @@ class Deparser {
8060
8078
  output.push('DATABASE');
8061
8079
  }
8062
8080
  if (node.objects && node.objects.length > 0) {
8081
+ const qualifiedKinds = ['OBJECT_TYPE', 'OBJECT_DOMAIN'];
8063
8082
  const objects = list_utils_1.ListUtils.unwrapList(node.objects)
8064
- .map(obj => this.visit(obj, context))
8083
+ .map(obj => qualifiedKinds.includes(node.objtype) && obj.List
8084
+ ? list_utils_1.ListUtils.unwrapList(obj.List.items).map((item) => this.visit(item, context)).join('.')
8085
+ : this.visit(obj, context))
8065
8086
  .join(', ');
8066
8087
  output.push(objects);
8067
8088
  }
@@ -8100,8 +8121,11 @@ class Deparser {
8100
8121
  break;
8101
8122
  default:
8102
8123
  if (node.objects && node.objects.length > 0) {
8124
+ const qualifiedKinds = ['OBJECT_TYPE', 'OBJECT_DOMAIN'];
8103
8125
  const objects = list_utils_1.ListUtils.unwrapList(node.objects)
8104
- .map(obj => this.visit(obj, context))
8126
+ .map(obj => qualifiedKinds.includes(node.objtype) && obj.List
8127
+ ? list_utils_1.ListUtils.unwrapList(obj.List.items).map((item) => this.visit(item, context)).join('.')
8128
+ : this.visit(obj, context))
8105
8129
  .join(', ');
8106
8130
  output.push(objects);
8107
8131
  }
@@ -9271,6 +9295,9 @@ class Deparser {
9271
9295
  if (listItems.length === 1 && listItems[0].String) {
9272
9296
  return `${preservedDefName} = ${listItems[0].String.sval}`;
9273
9297
  }
9298
+ if (listItems.length > 1 && listItems.every(item => item.String)) {
9299
+ return `${preservedDefName} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
9300
+ }
9274
9301
  }
9275
9302
  // For commutator/negator, we already handled them above
9276
9303
  if ((defName.toLowerCase() === 'commutator' || defName.toLowerCase() === 'negator')) {
package/esm/deparser.js CHANGED
@@ -4360,7 +4360,7 @@ export class Deparser {
4360
4360
  if (objList && objList.List && objList.List.items) {
4361
4361
  const items = objList.List.items.map((item) => {
4362
4362
  if (item.String && item.String.sval) {
4363
- return item.String.sval;
4363
+ return QuoteUtils.quoteIdentifier(item.String.sval);
4364
4364
  }
4365
4365
  return this.visit(item, context);
4366
4366
  });
@@ -5554,10 +5554,13 @@ export class Deparser {
5554
5554
  if (node.arg && this.getNodeType(node.arg) === 'List') {
5555
5555
  const listData = this.getNodeData(node.arg);
5556
5556
  const listItems = ListUtils.unwrapList(listData.items);
5557
+ const preservedName = this.preserveOperatorDefElemCase(node.defname);
5557
5558
  if (listItems.length === 1 && listItems[0].String) {
5558
- const preservedName = this.preserveOperatorDefElemCase(node.defname);
5559
5559
  return `${preservedName} = ${listItems[0].String.sval}`;
5560
5560
  }
5561
+ if (listItems.length > 1 && listItems.every((item) => item.String)) {
5562
+ return `${preservedName} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
5563
+ }
5561
5564
  }
5562
5565
  }
5563
5566
  // Handle IndexElem opclassopts - MUST be first to preserve string types
@@ -5659,6 +5662,9 @@ export class Deparser {
5659
5662
  if (listItems.length === 1 && listItems[0].String) {
5660
5663
  return `${node.defname} = ${listItems[0].String.sval}`;
5661
5664
  }
5665
+ if (listItems.length > 1 && listItems.every((item) => item.String)) {
5666
+ return `${node.defname} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
5667
+ }
5662
5668
  }
5663
5669
  }
5664
5670
  if (context.parentNodeTypes.includes('CreatedbStmt') || context.parentNodeTypes.includes('DropdbStmt')) {
@@ -6472,6 +6478,13 @@ export class Deparser {
6472
6478
  throw new Error(`Unsupported DiscardStmt target: ${node.target}`);
6473
6479
  }
6474
6480
  }
6481
+ /** `schema.op` for an operator name list: schema parts quoted, the operator symbol as is. */
6482
+ qualifiedOperatorName(objname) {
6483
+ const names = ListUtils.unwrapList(objname ?? []).map((n) => (n.String ? n.String.sval : 'unknown'));
6484
+ if (names.length === 0)
6485
+ return 'unknown';
6486
+ return [...names.slice(0, -1).map((n) => QuoteUtils.quoteIdentifier(n)), names[names.length - 1]].join('.');
6487
+ }
6475
6488
  CommentStmt(node, context) {
6476
6489
  const output = ['COMMENT ON'];
6477
6490
  if (node.objtype) {
@@ -6592,22 +6605,20 @@ export class Deparser {
6592
6605
  }
6593
6606
  }
6594
6607
  else if (node.objtype === 'OBJECT_TRIGGER') {
6595
- if (objectParts.length === 2) {
6596
- const [table, trigger] = objectParts;
6597
- output.push(trigger);
6608
+ if (objectParts.length >= 2) {
6609
+ output.push(objectParts[objectParts.length - 1]);
6598
6610
  output.push('ON');
6599
- output.push(table);
6611
+ output.push(objectParts.slice(0, -1).join('.'));
6600
6612
  }
6601
6613
  else {
6602
6614
  output.push(objectParts.join('.'));
6603
6615
  }
6604
6616
  }
6605
6617
  else if (node.objtype === 'OBJECT_RULE') {
6606
- if (objectParts.length === 2) {
6607
- const [table, rule] = objectParts;
6608
- output.push(rule);
6618
+ if (objectParts.length >= 2) {
6619
+ output.push(objectParts[objectParts.length - 1]);
6609
6620
  output.push('ON');
6610
- output.push(table);
6621
+ output.push(objectParts.slice(0, -1).join('.'));
6611
6622
  }
6612
6623
  else {
6613
6624
  output.push(objectParts.join('.'));
@@ -6618,8 +6629,7 @@ export class Deparser {
6618
6629
  // For operators, we need to handle ObjectWithArgs structure
6619
6630
  if (node.object && node.object.ObjectWithArgs) {
6620
6631
  const objWithArgs = node.object.ObjectWithArgs;
6621
- let operatorName = objWithArgs.objname && objWithArgs.objname[0] && objWithArgs.objname[0].String
6622
- ? objWithArgs.objname[0].String.sval : 'unknown';
6632
+ let operatorName = this.qualifiedOperatorName(objWithArgs.objname);
6623
6633
  if (operatorName.startsWith('"') && operatorName.endsWith('"')) {
6624
6634
  operatorName = operatorName.slice(1, -1);
6625
6635
  }
@@ -6657,7 +6667,13 @@ export class Deparser {
6657
6667
  }
6658
6668
  else if (node.objtype === 'OBJECT_POLICY') {
6659
6669
  // Handle POLICY syntax: COMMENT ON POLICY policy_name ON table_name IS 'comment'
6660
- if (objectParts.length === 2) {
6670
+ if (objectParts.length === 3) {
6671
+ const [schema, table, policy] = objectParts;
6672
+ output.push(policy);
6673
+ output.push('ON');
6674
+ output.push(`${schema}.${table}`);
6675
+ }
6676
+ else if (objectParts.length === 2) {
6661
6677
  const [table, policy] = objectParts;
6662
6678
  output.push(policy);
6663
6679
  output.push('ON');
@@ -6680,6 +6696,9 @@ export class Deparser {
6680
6696
  output.push(objectParts.join('.'));
6681
6697
  }
6682
6698
  }
6699
+ else if (node.objtype === 'OBJECT_CAST' && objectParts.length === 2) {
6700
+ output.push(`(${objectParts[0]} AS ${objectParts[1]})`);
6701
+ }
6683
6702
  else {
6684
6703
  output.push(objectParts.join('.'));
6685
6704
  }
@@ -6688,8 +6707,7 @@ export class Deparser {
6688
6707
  else if (node.objtype === 'OBJECT_OPERATOR' && node.object && node.object.ObjectWithArgs) {
6689
6708
  // Handle direct ObjectWithArgs for OPERATOR syntax: COMMENT ON OPERATOR -(NONE, integer) IS 'comment'
6690
6709
  const objWithArgs = node.object.ObjectWithArgs;
6691
- let operatorName = objWithArgs.objname && objWithArgs.objname[0] && objWithArgs.objname[0].String
6692
- ? objWithArgs.objname[0].String.sval : 'unknown';
6710
+ let operatorName = this.qualifiedOperatorName(objWithArgs.objname);
6693
6711
  // Remove quotes from operator name if present
6694
6712
  if (operatorName.startsWith('"') && operatorName.endsWith('"')) {
6695
6713
  operatorName = operatorName.slice(1, -1);
@@ -8057,8 +8075,11 @@ export class Deparser {
8057
8075
  output.push('DATABASE');
8058
8076
  }
8059
8077
  if (node.objects && node.objects.length > 0) {
8078
+ const qualifiedKinds = ['OBJECT_TYPE', 'OBJECT_DOMAIN'];
8060
8079
  const objects = ListUtils.unwrapList(node.objects)
8061
- .map(obj => this.visit(obj, context))
8080
+ .map(obj => qualifiedKinds.includes(node.objtype) && obj.List
8081
+ ? ListUtils.unwrapList(obj.List.items).map((item) => this.visit(item, context)).join('.')
8082
+ : this.visit(obj, context))
8062
8083
  .join(', ');
8063
8084
  output.push(objects);
8064
8085
  }
@@ -8097,8 +8118,11 @@ export class Deparser {
8097
8118
  break;
8098
8119
  default:
8099
8120
  if (node.objects && node.objects.length > 0) {
8121
+ const qualifiedKinds = ['OBJECT_TYPE', 'OBJECT_DOMAIN'];
8100
8122
  const objects = ListUtils.unwrapList(node.objects)
8101
- .map(obj => this.visit(obj, context))
8123
+ .map(obj => qualifiedKinds.includes(node.objtype) && obj.List
8124
+ ? ListUtils.unwrapList(obj.List.items).map((item) => this.visit(item, context)).join('.')
8125
+ : this.visit(obj, context))
8102
8126
  .join(', ');
8103
8127
  output.push(objects);
8104
8128
  }
@@ -9268,6 +9292,9 @@ export class Deparser {
9268
9292
  if (listItems.length === 1 && listItems[0].String) {
9269
9293
  return `${preservedDefName} = ${listItems[0].String.sval}`;
9270
9294
  }
9295
+ if (listItems.length > 1 && listItems.every(item => item.String)) {
9296
+ return `${preservedDefName} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
9297
+ }
9271
9298
  }
9272
9299
  // For commutator/negator, we already handled them above
9273
9300
  if ((defName.toLowerCase() === 'commutator' || defName.toLowerCase() === 'negator')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgsql-deparser",
3
- "version": "18.4.1",
3
+ "version": "18.4.3",
4
4
  "author": "Constructive <developers@constructive.io>",
5
5
  "description": "PostgreSQL AST Deparser",
6
6
  "main": "index.js",
@@ -60,5 +60,5 @@
60
60
  "@pgsql/quotes": "18.2.4",
61
61
  "@pgsql/types": "^18.0.0"
62
62
  },
63
- "gitHead": "e30cff75ed4b36a64aad5dd9d335c389e8b9c744"
63
+ "gitHead": "ce03e09604aea4b0fd7d62cf23e72d0de8ad33c1"
64
64
  }