Skip to content

Commit 7caeee9

Browse files
committed
refactor: centralize all inline quoting to use QuoteUtils methods
Co-Authored-By: Dan Lynch <[email protected]>
1 parent ba5bac2 commit 7caeee9

File tree

1 file changed

+112
-121
lines changed

1 file changed

+112
-121
lines changed

packages/deparser/src/deparser.ts

Lines changed: 112 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -4162,18 +4162,18 @@ export class Deparser implements DeparserVisitor {
41624162
return this.visit(arg, context);
41634163
}).join(', ') : '';
41644164

4165-
// Handle args - always include TO clause if args exist (even if empty string)
4166-
const paramName = node.name && (node.name.includes('.') || node.name.includes('-') || /[A-Z]/.test(node.name)) ? `"${node.name}"` : node.name;
4167-
if (!node.args || node.args.length === 0) {
4168-
return `SET ${localPrefix}${paramName}`;
4169-
}
4170-
return `SET ${localPrefix}${paramName} TO ${args}`;
4171-
case 'VAR_SET_DEFAULT':
4172-
const defaultParamName = node.name && (node.name.includes('.') || node.name.includes('-') || /[A-Z]/.test(node.name)) ? `"${node.name}"` : node.name;
4173-
return `SET ${defaultParamName} TO DEFAULT`;
4174-
case 'VAR_SET_CURRENT':
4175-
const currentParamName = node.name && (node.name.includes('.') || node.name.includes('-') || /[A-Z]/.test(node.name)) ? `"${node.name}"` : node.name;
4176-
return `SET ${currentParamName} FROM CURRENT`;
4165+
// Handle args - always include TO clause if args exist (even if empty string)
4166+
const paramName = QuoteUtils.quoteString(node.name);
4167+
if (!node.args || node.args.length === 0) {
4168+
return `SET ${localPrefix}${paramName}`;
4169+
}
4170+
return `SET ${localPrefix}${paramName} TO ${args}`;
4171+
case 'VAR_SET_DEFAULT':
4172+
const defaultParamName = QuoteUtils.quoteString(node.name);
4173+
return `SET ${defaultParamName} TO DEFAULT`;
4174+
case 'VAR_SET_CURRENT':
4175+
const currentParamName = QuoteUtils.quoteString(node.name);
4176+
return `SET ${currentParamName} FROM CURRENT`;
41774177
case 'VAR_SET_MULTI':
41784178
if (node.name === 'TRANSACTION' || node.name === 'SESSION CHARACTERISTICS') {
41794179
// Handle SET TRANSACTION statements specially
@@ -4239,9 +4239,9 @@ export class Deparser implements DeparserVisitor {
42394239
}).join(', ') : '';
42404240
return `SET ${assignments}`;
42414241
}
4242-
case 'VAR_RESET':
4243-
const resetParamName = node.name && (node.name.includes('.') || node.name.includes('-') || /[A-Z]/.test(node.name)) ? `"${node.name}"` : node.name;
4244-
return `RESET ${resetParamName}`;
4242+
case 'VAR_RESET':
4243+
const resetParamName = QuoteUtils.quoteString(node.name);
4244+
return `RESET ${resetParamName}`;
42454245
case 'VAR_RESET_ALL':
42464246
return 'RESET ALL';
42474247
default:
@@ -5731,14 +5731,14 @@ export class Deparser implements DeparserVisitor {
57315731
return `${node.defname}=${this.visit(node.arg, context.spawn('DefElem'))}`;
57325732
}
57335733

5734-
// Handle CREATE OPERATOR boolean flags - MUST be first to preserve case
5735-
if (context.parentNodeTypes.includes('DefineStmt') &&
5736-
['hashes', 'merges'].includes(node.defname.toLowerCase()) && !node.arg) {
5737-
if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
5738-
return `"${node.defname}"`;
5739-
}
5740-
return node.defname.charAt(0).toUpperCase() + node.defname.slice(1).toLowerCase();
5741-
}
5734+
// Handle CREATE OPERATOR boolean flags - MUST be first to preserve case
5735+
if (context.parentNodeTypes.includes('DefineStmt') &&
5736+
['hashes', 'merges'].includes(node.defname.toLowerCase()) && !node.arg) {
5737+
if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
5738+
return QuoteUtils.quoteString(node.defname);
5739+
}
5740+
return node.defname.charAt(0).toUpperCase() + node.defname.slice(1).toLowerCase();
5741+
}
57425742

57435743
// Handle FDW-related statements and ALTER OPTIONS that use space format for options
57445744
if (context.parentNodeTypes.includes('AlterFdwStmt') || context.parentNodeTypes.includes('CreateFdwStmt') || context.parentNodeTypes.includes('CreateForeignServerStmt') || context.parentNodeTypes.includes('AlterForeignServerStmt') || context.parentNodeTypes.includes('CreateUserMappingStmt') || context.parentNodeTypes.includes('AlterUserMappingStmt') || context.parentNodeTypes.includes('ColumnDef') || context.parentNodeTypes.includes('CreateForeignTableStmt') || context.parentNodeTypes.includes('ImportForeignSchemaStmt') || context.alterColumnOptions || context.alterTableOptions) {
@@ -5760,9 +5760,7 @@ export class Deparser implements DeparserVisitor {
57605760
? `'${argValue}'`
57615761
: argValue;
57625762

5763-
const quotedDefname = node.defname.includes(' ') || node.defname.includes('-') || QuoteUtils.needsQuotesForString(node.defname)
5764-
? `"${node.defname}"`
5765-
: node.defname;
5763+
const quotedDefname = QuoteUtils.quoteString(node.defname);
57665764

57675765
if (node.defaction === 'DEFELEM_ADD') {
57685766
return `ADD ${quotedDefname} ${finalValue}`;
@@ -5787,10 +5785,8 @@ export class Deparser implements DeparserVisitor {
57875785
return `SET ${node.defname} ${quotedValue}`;
57885786
}
57895787

5790-
const quotedDefname = node.defname.includes(' ') || node.defname.includes('-')
5791-
? `"${node.defname}"`
5792-
: node.defname;
5793-
return `${quotedDefname} ${quotedValue}`;
5788+
const quotedDefname = QuoteUtils.quoteString(node.defname);
5789+
return `${quotedDefname} ${quotedValue}`;
57945790
} else if (node.defaction === 'DEFELEM_DROP') {
57955791
// Handle DROP without argument
57965792
return `DROP ${node.defname}`;
@@ -5855,10 +5851,8 @@ export class Deparser implements DeparserVisitor {
58555851
const quotedValue = typeof argValue === 'string'
58565852
? QuoteUtils.escape(argValue)
58575853
: argValue;
5858-
const quotedDefname = node.defname.includes(' ') || node.defname.includes('-')
5859-
? `"${node.defname}"`
5860-
: node.defname;
5861-
return `${quotedDefname} ${quotedValue}`;
5854+
const quotedDefname = QuoteUtils.quoteString(node.defname);
5855+
return `${quotedDefname} ${quotedValue}`;
58625856
}
58635857

58645858

@@ -5937,14 +5931,11 @@ export class Deparser implements DeparserVisitor {
59375931
const listItems = ListUtils.unwrapList(listData.items);
59385932
const parts = listItems.map(item => {
59395933
const itemData = this.getNodeData(item);
5940-
if (this.getNodeType(item) === 'String') {
5941-
// Check if this identifier needs quotes to preserve case
5942-
const value = itemData.sval;
5943-
if (QuoteUtils.needsQuotesForString(value)) {
5944-
return `"${value}"`;
5945-
}
5946-
return value;
5947-
}
5934+
if (this.getNodeType(item) === 'String') {
5935+
// Check if this identifier needs quotes to preserve case
5936+
const value = itemData.sval;
5937+
return QuoteUtils.quoteString(value);
5938+
}
59485939
return this.visit(item, context);
59495940
});
59505941
return `OWNED BY ${parts.join('.')}`;
@@ -6208,18 +6199,18 @@ export class Deparser implements DeparserVisitor {
62086199
return preservedName;
62096200
}
62106201

6211-
// Handle boolean flags (no arguments) - preserve quoted case
6212-
if (['hashes', 'merges'].includes(node.defname.toLowerCase())) {
6213-
if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
6214-
return `"${node.defname}"`;
6215-
}
6216-
return preservedName.toUpperCase();
6217-
}
6202+
// Handle boolean flags (no arguments) - preserve quoted case
6203+
if (['hashes', 'merges'].includes(node.defname.toLowerCase())) {
6204+
if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
6205+
return QuoteUtils.quoteString(node.defname);
6206+
}
6207+
return preservedName.toUpperCase();
6208+
}
62186209

6219-
// Handle CREATE AGGREGATE quoted identifiers - preserve quotes when needed
6220-
if (QuoteUtils.needsQuotesForString(node.defname)) {
6221-
const quotedDefname = `"${node.defname}"`;
6222-
if (node.arg) {
6210+
// Handle CREATE AGGREGATE quoted identifiers - preserve quotes when needed
6211+
if (QuoteUtils.needsQuotesForString(node.defname)) {
6212+
const quotedDefname = QuoteUtils.quoteString(node.defname);
6213+
if (node.arg) {
62236214
if (this.getNodeType(node.arg) === 'String') {
62246215
const stringData = this.getNodeData(node.arg);
62256216
// Handle boolean string values without quotes
@@ -6278,13 +6269,13 @@ export class Deparser implements DeparserVisitor {
62786269
return `${node.defname} = ${quotedValue}`;
62796270
}
62806271

6281-
// Handle CREATE TYPE boolean flags - preserve quoted case for attributes like "Passedbyvalue"
6282-
if (context.parentNodeTypes.includes('DefineStmt') && !node.arg) {
6283-
// Check if the original defname appears to be quoted (mixed case that's not all upper/lower)
6284-
if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
6285-
return `"${node.defname}"`;
6286-
}
6287-
}
6272+
// Handle CREATE TYPE boolean flags - preserve quoted case for attributes like "Passedbyvalue"
6273+
if (context.parentNodeTypes.includes('DefineStmt') && !node.arg) {
6274+
// Check if the original defname appears to be quoted (mixed case that's not all upper/lower)
6275+
if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
6276+
return QuoteUtils.quoteString(node.defname);
6277+
}
6278+
}
62886279

62896280
return node.defname.toUpperCase();
62906281
}
@@ -7146,7 +7137,7 @@ export class Deparser implements DeparserVisitor {
71467137
output.push('SERVER');
71477138

71487139
if (node.servername) {
7149-
output.push(`"${node.servername}"`);
7140+
output.push(QuoteUtils.quoteString(node.servername));
71507141
}
71517142

71527143
if (node.options && node.options.length > 0) {
@@ -7207,7 +7198,7 @@ export class Deparser implements DeparserVisitor {
72077198
const output: string[] = ['CREATE', 'PUBLICATION'];
72087199

72097200
if (node.pubname) {
7210-
output.push(`"${node.pubname}"`);
7201+
output.push(QuoteUtils.quoteString(node.pubname));
72117202
}
72127203

72137204
if (node.pubobjects && node.pubobjects.length > 0) {
@@ -7231,7 +7222,7 @@ export class Deparser implements DeparserVisitor {
72317222
const output: string[] = ['CREATE', 'SUBSCRIPTION'];
72327223

72337224
if (node.subname) {
7234-
output.push(`"${node.subname}"`);
7225+
output.push(QuoteUtils.quoteString(node.subname));
72357226
}
72367227

72377228
output.push('CONNECTION');
@@ -7260,7 +7251,7 @@ export class Deparser implements DeparserVisitor {
72607251
const output: string[] = ['ALTER', 'PUBLICATION'];
72617252

72627253
if (node.pubname) {
7263-
output.push(`"${node.pubname}"`);
7254+
output.push(QuoteUtils.quoteString(node.pubname));
72647255
}
72657256

72667257
if (node.action) {
@@ -7300,7 +7291,7 @@ export class Deparser implements DeparserVisitor {
73007291
const output: string[] = ['ALTER', 'SUBSCRIPTION'];
73017292

73027293
if (node.subname) {
7303-
output.push(`"${node.subname}"`);
7294+
output.push(QuoteUtils.quoteString(node.subname));
73047295
}
73057296

73067297
if (node.kind) {
@@ -7352,7 +7343,7 @@ export class Deparser implements DeparserVisitor {
73527343
}
73537344

73547345
if (node.subname) {
7355-
output.push(`"${node.subname}"`);
7346+
output.push(QuoteUtils.quoteString(node.subname));
73567347
}
73577348

73587349
if (node.behavior) {
@@ -7963,7 +7954,7 @@ export class Deparser implements DeparserVisitor {
79637954
output.push(this.RangeVar(node.relation, context));
79647955

79657956
if (node.indexname) {
7966-
output.push('USING', `"${node.indexname}"`);
7957+
output.push('USING', QuoteUtils.quoteString(node.indexname));
79677958
}
79687959
}
79697960

@@ -8042,7 +8033,7 @@ export class Deparser implements DeparserVisitor {
80428033
}
80438034

80448035
if (node.name) {
8045-
output.push(`"${node.name}"`);
8036+
output.push(QuoteUtils.quoteString(node.name));
80468037
}
80478038

80488039
return output.join(' ');
@@ -8089,7 +8080,7 @@ export class Deparser implements DeparserVisitor {
80898080
throw new Error('CreatedbStmt requires dbname');
80908081
}
80918082

8092-
output.push(`"${node.dbname}"`);
8083+
output.push(QuoteUtils.quoteString(node.dbname));
80938084

80948085
if (node.options && node.options.length > 0) {
80958086
const options = ListUtils.unwrapList(node.options)
@@ -8112,7 +8103,7 @@ export class Deparser implements DeparserVisitor {
81128103
throw new Error('DropdbStmt requires dbname');
81138104
}
81148105

8115-
output.push(`"${node.dbname}"`);
8106+
output.push(QuoteUtils.quoteString(node.dbname));
81168107

81178108
if (node.options && node.options.length > 0) {
81188109
const options = ListUtils.unwrapList(node.options)
@@ -8308,16 +8299,16 @@ export class Deparser implements DeparserVisitor {
83088299
}
83098300
}
83108301

8311-
if (node.renameType === 'OBJECT_COLUMN' && node.subname) {
8312-
output.push('RENAME COLUMN', `"${node.subname}"`, 'TO');
8313-
} else if (node.renameType === 'OBJECT_DOMCONSTRAINT' && node.subname) {
8314-
output.push('RENAME CONSTRAINT', `"${node.subname}"`, 'TO');
8315-
} else if (node.renameType === 'OBJECT_TABCONSTRAINT' && node.subname) {
8316-
output.push('RENAME CONSTRAINT', `"${node.subname}"`, 'TO');
8317-
} else if (node.renameType === 'OBJECT_ATTRIBUTE' && node.subname) {
8318-
output.push('RENAME ATTRIBUTE', `"${node.subname}"`, 'TO');
8319-
} else if (node.renameType === 'OBJECT_ROLE' && node.subname) {
8320-
output.push(`"${node.subname}"`, 'RENAME TO');
8302+
if (node.renameType === 'OBJECT_COLUMN' && node.subname) {
8303+
output.push('RENAME COLUMN', QuoteUtils.quoteString(node.subname), 'TO');
8304+
} else if (node.renameType === 'OBJECT_DOMCONSTRAINT' && node.subname) {
8305+
output.push('RENAME CONSTRAINT', QuoteUtils.quoteString(node.subname), 'TO');
8306+
} else if (node.renameType === 'OBJECT_TABCONSTRAINT' && node.subname) {
8307+
output.push('RENAME CONSTRAINT', QuoteUtils.quoteString(node.subname), 'TO');
8308+
} else if (node.renameType === 'OBJECT_ATTRIBUTE' && node.subname) {
8309+
output.push('RENAME ATTRIBUTE', QuoteUtils.quoteString(node.subname), 'TO');
8310+
} else if (node.renameType === 'OBJECT_ROLE' && node.subname) {
8311+
output.push(QuoteUtils.quoteString(node.subname), 'RENAME TO');
83218312
} else if (node.renameType === 'OBJECT_SCHEMA' && node.subname) {
83228313
output.push(this.quoteIfNeeded(node.subname), 'RENAME TO');
83238314
} else if (node.renameType === 'OBJECT_RULE') {
@@ -8649,7 +8640,7 @@ export class Deparser implements DeparserVisitor {
86498640
const output: string[] = ['SECURITY LABEL'];
86508641

86518642
if (node.provider) {
8652-
output.push('FOR', `"${node.provider}"`);
8643+
output.push('FOR', QuoteUtils.quoteString(node.provider));
86538644
}
86548645

86558646
output.push('ON');
@@ -9818,32 +9809,32 @@ export class Deparser implements DeparserVisitor {
98189809
const defName = defElem.defname;
98199810
const defValue = defElem.arg;
98209811

9821-
if (defName && defValue) {
9822-
let preservedDefName;
9823-
if (QuoteUtils.needsQuotesForString(defName)) {
9824-
preservedDefName = `"${defName}"`;
9825-
} else {
9826-
preservedDefName = this.preserveOperatorDefElemCase(defName);
9827-
}
9828-
9829-
if ((defName.toLowerCase() === 'commutator' || defName.toLowerCase() === 'negator') && defValue.List) {
9830-
const listItems = ListUtils.unwrapList(defValue.List.items);
9831-
if (listItems.length === 1 && listItems[0].String) {
9832-
return `${preservedDefName} = ${listItems[0].String.sval}`;
9833-
}
9834-
}
9835-
// For commutator/negator, we already handled them above
9836-
if ((defName.toLowerCase() === 'commutator' || defName.toLowerCase() === 'negator')) {
9837-
return `${preservedDefName} = ${this.visit(defValue, context)}`;
9838-
}
9839-
return `${preservedDefName} = ${this.visit(defValue, context)}`;
9840-
} else if (defName && !defValue) {
9841-
// Handle boolean flags like HASHES, MERGES - preserve original case
9842-
if (defName === 'Hashes' || defName === 'Merges') {
9843-
return `"${defName}"`;
9844-
}
9845-
return this.preserveOperatorDefElemCase(defName).toUpperCase();
9846-
}
9812+
if (defName && defValue) {
9813+
let preservedDefName;
9814+
if (QuoteUtils.needsQuotesForString(defName)) {
9815+
preservedDefName = QuoteUtils.quoteString(defName);
9816+
} else {
9817+
preservedDefName = this.preserveOperatorDefElemCase(defName);
9818+
}
9819+
9820+
if ((defName.toLowerCase() === 'commutator' || defName.toLowerCase() === 'negator') && defValue.List) {
9821+
const listItems = ListUtils.unwrapList(defValue.List.items);
9822+
if (listItems.length === 1 && listItems[0].String) {
9823+
return `${preservedDefName} = ${listItems[0].String.sval}`;
9824+
}
9825+
}
9826+
// For commutator/negator, we already handled them above
9827+
if ((defName.toLowerCase() === 'commutator' || defName.toLowerCase() === 'negator')) {
9828+
return `${preservedDefName} = ${this.visit(defValue, context)}`;
9829+
}
9830+
return `${preservedDefName} = ${this.visit(defValue, context)}`;
9831+
} else if (defName && !defValue) {
9832+
// Handle boolean flags like HASHES, MERGES - preserve original case
9833+
if (defName === 'Hashes' || defName === 'Merges') {
9834+
return QuoteUtils.quoteString(defName);
9835+
}
9836+
return this.preserveOperatorDefElemCase(defName).toUpperCase();
9837+
}
98479838
}
98489839
return this.visit(def, context);
98499840
});
@@ -9982,20 +9973,20 @@ export class Deparser implements DeparserVisitor {
99829973
const defName = defElem.defname;
99839974
const defValue = defElem.arg;
99849975

9985-
if (defName && defValue) {
9986-
let preservedDefName;
9987-
if (QuoteUtils.needsQuotesForString(defName)) {
9988-
preservedDefName = `"${defName}"`;
9989-
} else {
9990-
preservedDefName = defName;
9991-
}
9992-
9993-
// Handle String arguments with single quotes for string literals
9994-
if (defValue.String) {
9995-
return `${preservedDefName} = '${defValue.String.sval}'`;
9996-
}
9997-
return `${preservedDefName} = ${this.visit(defValue, context)}`;
9998-
}
9976+
if (defName && defValue) {
9977+
let preservedDefName;
9978+
if (QuoteUtils.needsQuotesForString(defName)) {
9979+
preservedDefName = QuoteUtils.quoteString(defName);
9980+
} else {
9981+
preservedDefName = defName;
9982+
}
9983+
9984+
// Handle String arguments with single quotes for string literals
9985+
if (defValue.String) {
9986+
return `${preservedDefName} = '${defValue.String.sval}'`;
9987+
}
9988+
return `${preservedDefName} = ${this.visit(defValue, context)}`;
9989+
}
99999990
}
100009991
return this.visit(def, context);
100019992
});

0 commit comments

Comments
 (0)