sqlstack 1.0.16 → 1.0.17

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.
@@ -1 +1 @@
1
- {"version":3,"file":"sqlBinder.d.ts","sourceRoot":"","sources":["../../../src/binders/sqlBinder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,UAAU,CAAC;CAC1E;AAED,KAAK,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE/C,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAqQxD;AAED,eAAO,MAAM,iBAAiB,iBAA8B,CAAC;AAC7D,eAAO,MAAM,kBAAkB,iBAA+B,CAAC;AAC/D,eAAO,MAAM,oBAAoB,iBAAiC,CAAC;AAGnE,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"sqlBinder.d.ts","sourceRoot":"","sources":["../../../src/binders/sqlBinder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,UAAU,CAAC;CAC1E;AAED,KAAK,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE/C,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAoXxD;AAED,eAAO,MAAM,iBAAiB,iBAA8B,CAAC;AAC7D,eAAO,MAAM,kBAAkB,iBAA+B,CAAC;AAC/D,eAAO,MAAM,oBAAoB,iBAAiC,CAAC;AAGnE,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -151,28 +151,130 @@ function createBinder(dialect) {
151
151
  // Extract column list (between the parentheses)
152
152
  const columnList = sql.slice(columnStart, j).trim();
153
153
  const updateEnd = j + 1; // Include closing ')'
154
- // Parse column names (split by comma, trim whitespace)
155
- const columns = columnList
156
- .split(',')
157
- .map(col => col.trim())
158
- .filter(col => col.length > 0);
159
- if (columns.length === 0) {
154
+ // Parse column list (split by comma, respecting quotes and parentheses)
155
+ const items = [];
156
+ let current = '';
157
+ let inSQ = false; // single quote string
158
+ let inDQ = false; // double quote identifier
159
+ let itemParenDepth = 0;
160
+ for (let k = 0; k < columnList.length; k++) {
161
+ const ch = columnList[k];
162
+ const next = k + 1 < columnList.length ? columnList[k + 1] : '';
163
+ if (inSQ) {
164
+ current += ch;
165
+ if (ch === "'" && next === "'") {
166
+ current += next;
167
+ k++;
168
+ }
169
+ else if (ch === "'") {
170
+ inSQ = false;
171
+ }
172
+ continue;
173
+ }
174
+ if (inDQ) {
175
+ current += ch;
176
+ if (ch === '"' && next === '"') {
177
+ current += next;
178
+ k++;
179
+ }
180
+ else if (ch === '"') {
181
+ inDQ = false;
182
+ }
183
+ continue;
184
+ }
185
+ if (ch === "'") {
186
+ current += ch;
187
+ inSQ = true;
188
+ continue;
189
+ }
190
+ if (ch === '"') {
191
+ current += ch;
192
+ inDQ = true;
193
+ continue;
194
+ }
195
+ if (ch === '(') {
196
+ current += ch;
197
+ itemParenDepth++;
198
+ continue;
199
+ }
200
+ if (ch === ')') {
201
+ current += ch;
202
+ itemParenDepth--;
203
+ continue;
204
+ }
205
+ if (ch === ',' && itemParenDepth === 0) {
206
+ const trimmed = current.trim();
207
+ if (trimmed.length > 0) {
208
+ items.push(trimmed);
209
+ }
210
+ current = '';
211
+ continue;
212
+ }
213
+ current += ch;
214
+ }
215
+ // Add the last item
216
+ const trimmed = current.trim();
217
+ if (trimmed.length > 0) {
218
+ items.push(trimmed);
219
+ }
220
+ if (items.length === 0) {
160
221
  throw new Error(':update() requires at least one column name');
161
222
  }
162
- // Build SET clause with only defined columns
223
+ // Build SET clause with literal expressions and parameterized columns
163
224
  const obj = args;
164
225
  const setParts = [];
165
226
  const updateParams = [];
166
- for (const col of columns) {
167
- // Check if column exists in args and is not undefined
168
- if (Object.prototype.hasOwnProperty.call(obj, col) && obj[col] !== undefined) {
169
- setParts.push(`${col} = ${placeholder(pgIndex)}`);
170
- updateParams.push(obj[col]);
227
+ let hasParameterized = false;
228
+ for (const item of items) {
229
+ const trimmed = item.trim();
230
+ // Check if this is a literal expression (contains = not inside quotes)
231
+ let isLiteral = false;
232
+ let eqIndex = -1;
233
+ let inString = false;
234
+ let stringChar = '';
235
+ for (let k = 0; k < trimmed.length; k++) {
236
+ const ch = trimmed[k];
237
+ const next = k + 1 < trimmed.length ? trimmed[k + 1] : '';
238
+ if (!inString && (ch === "'" || ch === '"')) {
239
+ inString = true;
240
+ stringChar = ch;
241
+ }
242
+ else if (inString) {
243
+ if (ch === stringChar) {
244
+ if (next === stringChar) {
245
+ k++; // Skip escaped quote
246
+ }
247
+ else {
248
+ inString = false;
249
+ }
250
+ }
251
+ }
252
+ else if (ch === '=') {
253
+ eqIndex = k;
254
+ isLiteral = true;
255
+ break;
256
+ }
257
+ }
258
+ if (isLiteral && eqIndex >= 0) {
259
+ // Literal SQL expression - include as-is
260
+ setParts.push(trimmed);
261
+ }
262
+ else {
263
+ // Parameterized column - check if defined in args
264
+ hasParameterized = true;
265
+ if (Object.prototype.hasOwnProperty.call(obj, trimmed) && obj[trimmed] !== undefined) {
266
+ setParts.push(`${trimmed} = ${placeholder(pgIndex)}`);
267
+ updateParams.push(obj[trimmed]);
268
+ }
171
269
  }
172
270
  }
173
- if (setParts.length === 0) {
271
+ // Only throw error if all parameterized columns are undefined (literals are always included)
272
+ if (hasParameterized && setParts.length === 0) {
174
273
  throw new Error('All columns in :update() are undefined');
175
274
  }
275
+ if (setParts.length === 0) {
276
+ throw new Error(':update() requires at least one column name');
277
+ }
176
278
  // Replace :update(...) with SET clause
177
279
  out.push('SET ', setParts.join(', '));
178
280
  params.push(...updateParams);
@@ -1 +1 @@
1
- {"version":3,"file":"sqlBinder.js","sourceRoot":"","sources":["../../../src/binders/sqlBinder.ts"],"names":[],"mappings":"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","sourcesContent":["import { extractNamedParams } from '../core/sqlParams';\n\nexport type BindResult = {\n sql: string;\n params: unknown[];\n};\n\nexport interface SqlBinder {\n bind(sql: string, args: Record<string, unknown> | unknown[]): BindResult;\n}\n\ntype Dialect = 'mysql' | 'sqlite' | 'postgres';\n\nexport function createBinder(dialect: Dialect): SqlBinder {\n const placeholder = (indexRef: { i: number }) => {\n if (dialect === 'postgres') return `$${indexRef.i++}`;\n return '?'; // mysql + sqlite\n };\n\n return {\n bind(sql: string, args: Record<string, unknown> | unknown[]): BindResult {\n const isArrayArgs = Array.isArray(args);\n const params: unknown[] = [];\n const out: string[] = [];\n\n let i = 0;\n let inSQ = false; // single quote string\n let inDQ = false; // double quote identifier\n let inLC = false; // line comment -- ...\\n\n let inBC = false; // block comment /* ... */\n const pgIndex = { i: 1 };\n\n let sawNamed = false;\n let sawPositional = false;\n\n const len = sql.length;\n while (i < len) {\n const ch = sql[i];\n const next = i + 1 < len ? sql[i + 1] : '';\n\n // Handle exiting comments/strings first\n if (inLC) {\n out.push(ch);\n i++;\n if (ch === '\\n') inLC = false;\n continue;\n }\n if (inBC) {\n out.push(ch);\n i++;\n if (ch === '*' && next === '/') {\n out.push(next);\n i++;\n inBC = false;\n }\n continue;\n }\n if (inSQ) {\n out.push(ch);\n i++;\n // escape '' inside string\n if (ch === \"'\" && next === \"'\") {\n out.push(next);\n i++;\n } else if (ch === \"'\") {\n inSQ = false;\n }\n continue;\n }\n if (inDQ) {\n out.push(ch);\n i++;\n // escape \"\" inside identifier\n if (ch === '\"' && next === '\"') {\n out.push(next);\n i++;\n } else if (ch === '\"') {\n inDQ = false;\n }\n continue;\n }\n\n // Not inside string/comment\n if (ch === '-' && next === '-') {\n out.push(ch, next);\n i += 2;\n inLC = true;\n continue;\n }\n if (ch === '/' && next === '*') {\n out.push(ch, next);\n i += 2;\n inBC = true;\n continue;\n }\n if (ch === \"'\") {\n out.push(ch);\n i++;\n inSQ = true;\n continue;\n }\n if (ch === '\"') {\n out.push(ch);\n i++;\n inDQ = true;\n continue;\n }\n\n // Postgres cast :: — skip as literal\n if (ch === ':' && next === ':') {\n out.push('::');\n i += 2;\n continue;\n }\n\n if (ch === ':') {\n // Check for :update(...) syntax (case-insensitive)\n const updateMatch = /^:update\\s*\\(/i.exec(sql.slice(i));\n if (updateMatch) {\n if (isArrayArgs) {\n throw new Error(':update() syntax only works with named parameters');\n }\n \n // Parse the column list inside parentheses\n let j = i + updateMatch[0].length; // Skip ':update('\n const columnStart = j;\n let parenDepth = 1;\n let inString = false;\n let stringChar = '';\n \n // Find matching closing parenthesis\n while (j < len && parenDepth > 0) {\n const c = sql[j];\n const cNext = j + 1 < len ? sql[j + 1] : '';\n \n if (!inString) {\n if (c === \"'\" || c === '\"') {\n inString = true;\n stringChar = c;\n } else if (c === '(') {\n parenDepth++;\n } else if (c === ')') {\n parenDepth--;\n }\n } else {\n if (c === stringChar) {\n // Check for escaped quote\n if (cNext === stringChar) {\n j++; // Skip escaped quote\n } else {\n inString = false;\n }\n }\n }\n if (parenDepth > 0) j++;\n }\n \n if (parenDepth > 0) {\n throw new Error('Unclosed :update() parentheses');\n }\n \n // Extract column list (between the parentheses)\n const columnList = sql.slice(columnStart, j).trim();\n const updateEnd = j + 1; // Include closing ')'\n \n // Parse column names (split by comma, trim whitespace)\n const columns = columnList\n .split(',')\n .map(col => col.trim())\n .filter(col => col.length > 0);\n \n if (columns.length === 0) {\n throw new Error(':update() requires at least one column name');\n }\n \n // Build SET clause with only defined columns\n const obj = args as Record<string, unknown>;\n const setParts: string[] = [];\n const updateParams: unknown[] = [];\n \n for (const col of columns) {\n // Check if column exists in args and is not undefined\n if (Object.prototype.hasOwnProperty.call(obj, col) && obj[col] !== undefined) {\n setParts.push(`${col} = ${placeholder(pgIndex)}`);\n updateParams.push(obj[col]);\n }\n }\n \n if (setParts.length === 0) {\n throw new Error('All columns in :update() are undefined');\n }\n \n // Replace :update(...) with SET clause\n out.push('SET ', setParts.join(', '));\n params.push(...updateParams);\n \n i = updateEnd;\n continue;\n }\n \n // Attempt to parse a parameter token\n let j = i + 1;\n const start = j;\n while (j < len) {\n const c = sql[j];\n if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c === '_') {\n j++;\n } else {\n break;\n }\n }\n const name = sql.slice(start, j);\n if (!name) {\n // not a parameter — keep literal ':'\n out.push(':');\n i++;\n continue;\n }\n\n // Decide positional vs named\n const m = /^arg([1-9][0-9]*)$/.exec(name);\n const isPos = !!m;\n if (isPos) sawPositional = true; else sawNamed = true;\n if (sawNamed && sawPositional) {\n throw new Error('Cannot mix named and positional parameters in a single query');\n }\n\n let value: unknown;\n if (isPos) {\n if (!isArrayArgs) throw new Error('Positional placeholders require array arguments');\n const index = parseInt(m![1], 10) - 1; // 1-based in SQL\n const arr = args as unknown[];\n if (index < 0 || index >= arr.length) throw new Error(`Missing positional argument :${name}`);\n value = arr[index];\n } else {\n if (isArrayArgs) throw new Error('Named placeholders require a parameter object');\n const obj = args as Record<string, unknown>;\n if (!Object.prototype.hasOwnProperty.call(obj, name)) {\n throw new Error(`Missing named parameter :${name}`);\n }\n value = obj[name];\n }\n\n if (value === undefined) {\n throw new Error(`Parameter :${name} is undefined`);\n }\n\n // Expand placeholder(s)\n if (Array.isArray(value)) {\n if (value.length === 0) throw new Error(`Array parameter :${name} must not be empty`);\n const placeholders: string[] = [];\n for (const v of value) {\n if (v === undefined) throw new Error(`Array parameter :${name} contains undefined`);\n placeholders.push(placeholder(pgIndex));\n params.push(v === undefined ? null : v);\n }\n out.push(placeholders.join(', '));\n } else {\n out.push(placeholder(pgIndex));\n params.push(value === undefined ? null : value);\n }\n\n i = j;\n continue;\n }\n\n // default: copy char\n out.push(ch);\n i++;\n }\n\n return { sql: out.join(''), params };\n },\n };\n}\n\nexport const createMysqlBinder = () => createBinder('mysql');\nexport const createSqliteBinder = () => createBinder('sqlite');\nexport const createPostgresBinder = () => createBinder('postgres');\n\n// Re-export the shared helper for use in decorators\nexport { extractNamedParams };\n"]}
1
+ {"version":3,"file":"sqlBinder.js","sourceRoot":"","sources":["../../../src/binders/sqlBinder.ts"],"names":[],"mappings":"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","sourcesContent":["import { extractNamedParams } from '../core/sqlParams';\n\nexport type BindResult = {\n sql: string;\n params: unknown[];\n};\n\nexport interface SqlBinder {\n bind(sql: string, args: Record<string, unknown> | unknown[]): BindResult;\n}\n\ntype Dialect = 'mysql' | 'sqlite' | 'postgres';\n\nexport function createBinder(dialect: Dialect): SqlBinder {\n const placeholder = (indexRef: { i: number }) => {\n if (dialect === 'postgres') return `$${indexRef.i++}`;\n return '?'; // mysql + sqlite\n };\n\n return {\n bind(sql: string, args: Record<string, unknown> | unknown[]): BindResult {\n const isArrayArgs = Array.isArray(args);\n const params: unknown[] = [];\n const out: string[] = [];\n\n let i = 0;\n let inSQ = false; // single quote string\n let inDQ = false; // double quote identifier\n let inLC = false; // line comment -- ...\\n\n let inBC = false; // block comment /* ... */\n const pgIndex = { i: 1 };\n\n let sawNamed = false;\n let sawPositional = false;\n\n const len = sql.length;\n while (i < len) {\n const ch = sql[i];\n const next = i + 1 < len ? sql[i + 1] : '';\n\n // Handle exiting comments/strings first\n if (inLC) {\n out.push(ch);\n i++;\n if (ch === '\\n') inLC = false;\n continue;\n }\n if (inBC) {\n out.push(ch);\n i++;\n if (ch === '*' && next === '/') {\n out.push(next);\n i++;\n inBC = false;\n }\n continue;\n }\n if (inSQ) {\n out.push(ch);\n i++;\n // escape '' inside string\n if (ch === \"'\" && next === \"'\") {\n out.push(next);\n i++;\n } else if (ch === \"'\") {\n inSQ = false;\n }\n continue;\n }\n if (inDQ) {\n out.push(ch);\n i++;\n // escape \"\" inside identifier\n if (ch === '\"' && next === '\"') {\n out.push(next);\n i++;\n } else if (ch === '\"') {\n inDQ = false;\n }\n continue;\n }\n\n // Not inside string/comment\n if (ch === '-' && next === '-') {\n out.push(ch, next);\n i += 2;\n inLC = true;\n continue;\n }\n if (ch === '/' && next === '*') {\n out.push(ch, next);\n i += 2;\n inBC = true;\n continue;\n }\n if (ch === \"'\") {\n out.push(ch);\n i++;\n inSQ = true;\n continue;\n }\n if (ch === '\"') {\n out.push(ch);\n i++;\n inDQ = true;\n continue;\n }\n\n // Postgres cast :: — skip as literal\n if (ch === ':' && next === ':') {\n out.push('::');\n i += 2;\n continue;\n }\n\n if (ch === ':') {\n // Check for :update(...) syntax (case-insensitive)\n const updateMatch = /^:update\\s*\\(/i.exec(sql.slice(i));\n if (updateMatch) {\n if (isArrayArgs) {\n throw new Error(':update() syntax only works with named parameters');\n }\n \n // Parse the column list inside parentheses\n let j = i + updateMatch[0].length; // Skip ':update('\n const columnStart = j;\n let parenDepth = 1;\n let inString = false;\n let stringChar = '';\n \n // Find matching closing parenthesis\n while (j < len && parenDepth > 0) {\n const c = sql[j];\n const cNext = j + 1 < len ? sql[j + 1] : '';\n \n if (!inString) {\n if (c === \"'\" || c === '\"') {\n inString = true;\n stringChar = c;\n } else if (c === '(') {\n parenDepth++;\n } else if (c === ')') {\n parenDepth--;\n }\n } else {\n if (c === stringChar) {\n // Check for escaped quote\n if (cNext === stringChar) {\n j++; // Skip escaped quote\n } else {\n inString = false;\n }\n }\n }\n if (parenDepth > 0) j++;\n }\n \n if (parenDepth > 0) {\n throw new Error('Unclosed :update() parentheses');\n }\n \n // Extract column list (between the parentheses)\n const columnList = sql.slice(columnStart, j).trim();\n const updateEnd = j + 1; // Include closing ')'\n \n // Parse column list (split by comma, respecting quotes and parentheses)\n const items: string[] = [];\n let current = '';\n let inSQ = false; // single quote string\n let inDQ = false; // double quote identifier\n let itemParenDepth = 0;\n \n for (let k = 0; k < columnList.length; k++) {\n const ch = columnList[k];\n const next = k + 1 < columnList.length ? columnList[k + 1] : '';\n \n if (inSQ) {\n current += ch;\n if (ch === \"'\" && next === \"'\") {\n current += next;\n k++;\n } else if (ch === \"'\") {\n inSQ = false;\n }\n continue;\n }\n \n if (inDQ) {\n current += ch;\n if (ch === '\"' && next === '\"') {\n current += next;\n k++;\n } else if (ch === '\"') {\n inDQ = false;\n }\n continue;\n }\n \n if (ch === \"'\") {\n current += ch;\n inSQ = true;\n continue;\n }\n \n if (ch === '\"') {\n current += ch;\n inDQ = true;\n continue;\n }\n \n if (ch === '(') {\n current += ch;\n itemParenDepth++;\n continue;\n }\n \n if (ch === ')') {\n current += ch;\n itemParenDepth--;\n continue;\n }\n \n if (ch === ',' && itemParenDepth === 0) {\n const trimmed = current.trim();\n if (trimmed.length > 0) {\n items.push(trimmed);\n }\n current = '';\n continue;\n }\n \n current += ch;\n }\n \n // Add the last item\n const trimmed = current.trim();\n if (trimmed.length > 0) {\n items.push(trimmed);\n }\n \n if (items.length === 0) {\n throw new Error(':update() requires at least one column name');\n }\n \n // Build SET clause with literal expressions and parameterized columns\n const obj = args as Record<string, unknown>;\n const setParts: string[] = [];\n const updateParams: unknown[] = [];\n let hasParameterized = false;\n \n for (const item of items) {\n const trimmed = item.trim();\n \n // Check if this is a literal expression (contains = not inside quotes)\n let isLiteral = false;\n let eqIndex = -1;\n let inString = false;\n let stringChar = '';\n \n for (let k = 0; k < trimmed.length; k++) {\n const ch = trimmed[k];\n const next = k + 1 < trimmed.length ? trimmed[k + 1] : '';\n \n if (!inString && (ch === \"'\" || ch === '\"')) {\n inString = true;\n stringChar = ch;\n } else if (inString) {\n if (ch === stringChar) {\n if (next === stringChar) {\n k++; // Skip escaped quote\n } else {\n inString = false;\n }\n }\n } else if (ch === '=') {\n eqIndex = k;\n isLiteral = true;\n break;\n }\n }\n \n if (isLiteral && eqIndex >= 0) {\n // Literal SQL expression - include as-is\n setParts.push(trimmed);\n } else {\n // Parameterized column - check if defined in args\n hasParameterized = true;\n if (Object.prototype.hasOwnProperty.call(obj, trimmed) && obj[trimmed] !== undefined) {\n setParts.push(`${trimmed} = ${placeholder(pgIndex)}`);\n updateParams.push(obj[trimmed]);\n }\n }\n }\n \n // Only throw error if all parameterized columns are undefined (literals are always included)\n if (hasParameterized && setParts.length === 0) {\n throw new Error('All columns in :update() are undefined');\n }\n \n if (setParts.length === 0) {\n throw new Error(':update() requires at least one column name');\n }\n \n // Replace :update(...) with SET clause\n out.push('SET ', setParts.join(', '));\n params.push(...updateParams);\n \n i = updateEnd;\n continue;\n }\n \n // Attempt to parse a parameter token\n let j = i + 1;\n const start = j;\n while (j < len) {\n const c = sql[j];\n if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c === '_') {\n j++;\n } else {\n break;\n }\n }\n const name = sql.slice(start, j);\n if (!name) {\n // not a parameter — keep literal ':'\n out.push(':');\n i++;\n continue;\n }\n\n // Decide positional vs named\n const m = /^arg([1-9][0-9]*)$/.exec(name);\n const isPos = !!m;\n if (isPos) sawPositional = true; else sawNamed = true;\n if (sawNamed && sawPositional) {\n throw new Error('Cannot mix named and positional parameters in a single query');\n }\n\n let value: unknown;\n if (isPos) {\n if (!isArrayArgs) throw new Error('Positional placeholders require array arguments');\n const index = parseInt(m![1], 10) - 1; // 1-based in SQL\n const arr = args as unknown[];\n if (index < 0 || index >= arr.length) throw new Error(`Missing positional argument :${name}`);\n value = arr[index];\n } else {\n if (isArrayArgs) throw new Error('Named placeholders require a parameter object');\n const obj = args as Record<string, unknown>;\n if (!Object.prototype.hasOwnProperty.call(obj, name)) {\n throw new Error(`Missing named parameter :${name}`);\n }\n value = obj[name];\n }\n\n if (value === undefined) {\n throw new Error(`Parameter :${name} is undefined`);\n }\n\n // Expand placeholder(s)\n if (Array.isArray(value)) {\n if (value.length === 0) throw new Error(`Array parameter :${name} must not be empty`);\n const placeholders: string[] = [];\n for (const v of value) {\n if (v === undefined) throw new Error(`Array parameter :${name} contains undefined`);\n placeholders.push(placeholder(pgIndex));\n params.push(v === undefined ? null : v);\n }\n out.push(placeholders.join(', '));\n } else {\n out.push(placeholder(pgIndex));\n params.push(value === undefined ? null : value);\n }\n\n i = j;\n continue;\n }\n\n // default: copy char\n out.push(ch);\n i++;\n }\n\n return { sql: out.join(''), params };\n },\n };\n}\n\nexport const createMysqlBinder = () => createBinder('mysql');\nexport const createSqliteBinder = () => createBinder('sqlite');\nexport const createPostgresBinder = () => createBinder('postgres');\n\n// Re-export the shared helper for use in decorators\nexport { extractNamedParams };\n"]}
@@ -146,28 +146,130 @@ export function createBinder(dialect) {
146
146
  // Extract column list (between the parentheses)
147
147
  const columnList = sql.slice(columnStart, j).trim();
148
148
  const updateEnd = j + 1; // Include closing ')'
149
- // Parse column names (split by comma, trim whitespace)
150
- const columns = columnList
151
- .split(',')
152
- .map(col => col.trim())
153
- .filter(col => col.length > 0);
154
- if (columns.length === 0) {
149
+ // Parse column list (split by comma, respecting quotes and parentheses)
150
+ const items = [];
151
+ let current = '';
152
+ let inSQ = false; // single quote string
153
+ let inDQ = false; // double quote identifier
154
+ let itemParenDepth = 0;
155
+ for (let k = 0; k < columnList.length; k++) {
156
+ const ch = columnList[k];
157
+ const next = k + 1 < columnList.length ? columnList[k + 1] : '';
158
+ if (inSQ) {
159
+ current += ch;
160
+ if (ch === "'" && next === "'") {
161
+ current += next;
162
+ k++;
163
+ }
164
+ else if (ch === "'") {
165
+ inSQ = false;
166
+ }
167
+ continue;
168
+ }
169
+ if (inDQ) {
170
+ current += ch;
171
+ if (ch === '"' && next === '"') {
172
+ current += next;
173
+ k++;
174
+ }
175
+ else if (ch === '"') {
176
+ inDQ = false;
177
+ }
178
+ continue;
179
+ }
180
+ if (ch === "'") {
181
+ current += ch;
182
+ inSQ = true;
183
+ continue;
184
+ }
185
+ if (ch === '"') {
186
+ current += ch;
187
+ inDQ = true;
188
+ continue;
189
+ }
190
+ if (ch === '(') {
191
+ current += ch;
192
+ itemParenDepth++;
193
+ continue;
194
+ }
195
+ if (ch === ')') {
196
+ current += ch;
197
+ itemParenDepth--;
198
+ continue;
199
+ }
200
+ if (ch === ',' && itemParenDepth === 0) {
201
+ const trimmed = current.trim();
202
+ if (trimmed.length > 0) {
203
+ items.push(trimmed);
204
+ }
205
+ current = '';
206
+ continue;
207
+ }
208
+ current += ch;
209
+ }
210
+ // Add the last item
211
+ const trimmed = current.trim();
212
+ if (trimmed.length > 0) {
213
+ items.push(trimmed);
214
+ }
215
+ if (items.length === 0) {
155
216
  throw new Error(':update() requires at least one column name');
156
217
  }
157
- // Build SET clause with only defined columns
218
+ // Build SET clause with literal expressions and parameterized columns
158
219
  const obj = args;
159
220
  const setParts = [];
160
221
  const updateParams = [];
161
- for (const col of columns) {
162
- // Check if column exists in args and is not undefined
163
- if (Object.prototype.hasOwnProperty.call(obj, col) && obj[col] !== undefined) {
164
- setParts.push(`${col} = ${placeholder(pgIndex)}`);
165
- updateParams.push(obj[col]);
222
+ let hasParameterized = false;
223
+ for (const item of items) {
224
+ const trimmed = item.trim();
225
+ // Check if this is a literal expression (contains = not inside quotes)
226
+ let isLiteral = false;
227
+ let eqIndex = -1;
228
+ let inString = false;
229
+ let stringChar = '';
230
+ for (let k = 0; k < trimmed.length; k++) {
231
+ const ch = trimmed[k];
232
+ const next = k + 1 < trimmed.length ? trimmed[k + 1] : '';
233
+ if (!inString && (ch === "'" || ch === '"')) {
234
+ inString = true;
235
+ stringChar = ch;
236
+ }
237
+ else if (inString) {
238
+ if (ch === stringChar) {
239
+ if (next === stringChar) {
240
+ k++; // Skip escaped quote
241
+ }
242
+ else {
243
+ inString = false;
244
+ }
245
+ }
246
+ }
247
+ else if (ch === '=') {
248
+ eqIndex = k;
249
+ isLiteral = true;
250
+ break;
251
+ }
252
+ }
253
+ if (isLiteral && eqIndex >= 0) {
254
+ // Literal SQL expression - include as-is
255
+ setParts.push(trimmed);
256
+ }
257
+ else {
258
+ // Parameterized column - check if defined in args
259
+ hasParameterized = true;
260
+ if (Object.prototype.hasOwnProperty.call(obj, trimmed) && obj[trimmed] !== undefined) {
261
+ setParts.push(`${trimmed} = ${placeholder(pgIndex)}`);
262
+ updateParams.push(obj[trimmed]);
263
+ }
166
264
  }
167
265
  }
168
- if (setParts.length === 0) {
266
+ // Only throw error if all parameterized columns are undefined (literals are always included)
267
+ if (hasParameterized && setParts.length === 0) {
169
268
  throw new Error('All columns in :update() are undefined');
170
269
  }
270
+ if (setParts.length === 0) {
271
+ throw new Error(':update() requires at least one column name');
272
+ }
171
273
  // Replace :update(...) with SET clause
172
274
  out.push('SET ', setParts.join(', '));
173
275
  params.push(...updateParams);
@@ -1 +1 @@
1
- {"version":3,"file":"sqlBinder.js","sourceRoot":"","sources":["../../../src/binders/sqlBinder.ts"],"names":[],"mappings":"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","sourcesContent":["import { extractNamedParams } from '../core/sqlParams';\n\nexport type BindResult = {\n sql: string;\n params: unknown[];\n};\n\nexport interface SqlBinder {\n bind(sql: string, args: Record<string, unknown> | unknown[]): BindResult;\n}\n\ntype Dialect = 'mysql' | 'sqlite' | 'postgres';\n\nexport function createBinder(dialect: Dialect): SqlBinder {\n const placeholder = (indexRef: { i: number }) => {\n if (dialect === 'postgres') return `$${indexRef.i++}`;\n return '?'; // mysql + sqlite\n };\n\n return {\n bind(sql: string, args: Record<string, unknown> | unknown[]): BindResult {\n const isArrayArgs = Array.isArray(args);\n const params: unknown[] = [];\n const out: string[] = [];\n\n let i = 0;\n let inSQ = false; // single quote string\n let inDQ = false; // double quote identifier\n let inLC = false; // line comment -- ...\\n\n let inBC = false; // block comment /* ... */\n const pgIndex = { i: 1 };\n\n let sawNamed = false;\n let sawPositional = false;\n\n const len = sql.length;\n while (i < len) {\n const ch = sql[i];\n const next = i + 1 < len ? sql[i + 1] : '';\n\n // Handle exiting comments/strings first\n if (inLC) {\n out.push(ch);\n i++;\n if (ch === '\\n') inLC = false;\n continue;\n }\n if (inBC) {\n out.push(ch);\n i++;\n if (ch === '*' && next === '/') {\n out.push(next);\n i++;\n inBC = false;\n }\n continue;\n }\n if (inSQ) {\n out.push(ch);\n i++;\n // escape '' inside string\n if (ch === \"'\" && next === \"'\") {\n out.push(next);\n i++;\n } else if (ch === \"'\") {\n inSQ = false;\n }\n continue;\n }\n if (inDQ) {\n out.push(ch);\n i++;\n // escape \"\" inside identifier\n if (ch === '\"' && next === '\"') {\n out.push(next);\n i++;\n } else if (ch === '\"') {\n inDQ = false;\n }\n continue;\n }\n\n // Not inside string/comment\n if (ch === '-' && next === '-') {\n out.push(ch, next);\n i += 2;\n inLC = true;\n continue;\n }\n if (ch === '/' && next === '*') {\n out.push(ch, next);\n i += 2;\n inBC = true;\n continue;\n }\n if (ch === \"'\") {\n out.push(ch);\n i++;\n inSQ = true;\n continue;\n }\n if (ch === '\"') {\n out.push(ch);\n i++;\n inDQ = true;\n continue;\n }\n\n // Postgres cast :: — skip as literal\n if (ch === ':' && next === ':') {\n out.push('::');\n i += 2;\n continue;\n }\n\n if (ch === ':') {\n // Check for :update(...) syntax (case-insensitive)\n const updateMatch = /^:update\\s*\\(/i.exec(sql.slice(i));\n if (updateMatch) {\n if (isArrayArgs) {\n throw new Error(':update() syntax only works with named parameters');\n }\n \n // Parse the column list inside parentheses\n let j = i + updateMatch[0].length; // Skip ':update('\n const columnStart = j;\n let parenDepth = 1;\n let inString = false;\n let stringChar = '';\n \n // Find matching closing parenthesis\n while (j < len && parenDepth > 0) {\n const c = sql[j];\n const cNext = j + 1 < len ? sql[j + 1] : '';\n \n if (!inString) {\n if (c === \"'\" || c === '\"') {\n inString = true;\n stringChar = c;\n } else if (c === '(') {\n parenDepth++;\n } else if (c === ')') {\n parenDepth--;\n }\n } else {\n if (c === stringChar) {\n // Check for escaped quote\n if (cNext === stringChar) {\n j++; // Skip escaped quote\n } else {\n inString = false;\n }\n }\n }\n if (parenDepth > 0) j++;\n }\n \n if (parenDepth > 0) {\n throw new Error('Unclosed :update() parentheses');\n }\n \n // Extract column list (between the parentheses)\n const columnList = sql.slice(columnStart, j).trim();\n const updateEnd = j + 1; // Include closing ')'\n \n // Parse column names (split by comma, trim whitespace)\n const columns = columnList\n .split(',')\n .map(col => col.trim())\n .filter(col => col.length > 0);\n \n if (columns.length === 0) {\n throw new Error(':update() requires at least one column name');\n }\n \n // Build SET clause with only defined columns\n const obj = args as Record<string, unknown>;\n const setParts: string[] = [];\n const updateParams: unknown[] = [];\n \n for (const col of columns) {\n // Check if column exists in args and is not undefined\n if (Object.prototype.hasOwnProperty.call(obj, col) && obj[col] !== undefined) {\n setParts.push(`${col} = ${placeholder(pgIndex)}`);\n updateParams.push(obj[col]);\n }\n }\n \n if (setParts.length === 0) {\n throw new Error('All columns in :update() are undefined');\n }\n \n // Replace :update(...) with SET clause\n out.push('SET ', setParts.join(', '));\n params.push(...updateParams);\n \n i = updateEnd;\n continue;\n }\n \n // Attempt to parse a parameter token\n let j = i + 1;\n const start = j;\n while (j < len) {\n const c = sql[j];\n if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c === '_') {\n j++;\n } else {\n break;\n }\n }\n const name = sql.slice(start, j);\n if (!name) {\n // not a parameter — keep literal ':'\n out.push(':');\n i++;\n continue;\n }\n\n // Decide positional vs named\n const m = /^arg([1-9][0-9]*)$/.exec(name);\n const isPos = !!m;\n if (isPos) sawPositional = true; else sawNamed = true;\n if (sawNamed && sawPositional) {\n throw new Error('Cannot mix named and positional parameters in a single query');\n }\n\n let value: unknown;\n if (isPos) {\n if (!isArrayArgs) throw new Error('Positional placeholders require array arguments');\n const index = parseInt(m![1], 10) - 1; // 1-based in SQL\n const arr = args as unknown[];\n if (index < 0 || index >= arr.length) throw new Error(`Missing positional argument :${name}`);\n value = arr[index];\n } else {\n if (isArrayArgs) throw new Error('Named placeholders require a parameter object');\n const obj = args as Record<string, unknown>;\n if (!Object.prototype.hasOwnProperty.call(obj, name)) {\n throw new Error(`Missing named parameter :${name}`);\n }\n value = obj[name];\n }\n\n if (value === undefined) {\n throw new Error(`Parameter :${name} is undefined`);\n }\n\n // Expand placeholder(s)\n if (Array.isArray(value)) {\n if (value.length === 0) throw new Error(`Array parameter :${name} must not be empty`);\n const placeholders: string[] = [];\n for (const v of value) {\n if (v === undefined) throw new Error(`Array parameter :${name} contains undefined`);\n placeholders.push(placeholder(pgIndex));\n params.push(v === undefined ? null : v);\n }\n out.push(placeholders.join(', '));\n } else {\n out.push(placeholder(pgIndex));\n params.push(value === undefined ? null : value);\n }\n\n i = j;\n continue;\n }\n\n // default: copy char\n out.push(ch);\n i++;\n }\n\n return { sql: out.join(''), params };\n },\n };\n}\n\nexport const createMysqlBinder = () => createBinder('mysql');\nexport const createSqliteBinder = () => createBinder('sqlite');\nexport const createPostgresBinder = () => createBinder('postgres');\n\n// Re-export the shared helper for use in decorators\nexport { extractNamedParams };\n"]}
1
+ {"version":3,"file":"sqlBinder.js","sourceRoot":"","sources":["../../../src/binders/sqlBinder.ts"],"names":[],"mappings":"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","sourcesContent":["import { extractNamedParams } from '../core/sqlParams';\n\nexport type BindResult = {\n sql: string;\n params: unknown[];\n};\n\nexport interface SqlBinder {\n bind(sql: string, args: Record<string, unknown> | unknown[]): BindResult;\n}\n\ntype Dialect = 'mysql' | 'sqlite' | 'postgres';\n\nexport function createBinder(dialect: Dialect): SqlBinder {\n const placeholder = (indexRef: { i: number }) => {\n if (dialect === 'postgres') return `$${indexRef.i++}`;\n return '?'; // mysql + sqlite\n };\n\n return {\n bind(sql: string, args: Record<string, unknown> | unknown[]): BindResult {\n const isArrayArgs = Array.isArray(args);\n const params: unknown[] = [];\n const out: string[] = [];\n\n let i = 0;\n let inSQ = false; // single quote string\n let inDQ = false; // double quote identifier\n let inLC = false; // line comment -- ...\\n\n let inBC = false; // block comment /* ... */\n const pgIndex = { i: 1 };\n\n let sawNamed = false;\n let sawPositional = false;\n\n const len = sql.length;\n while (i < len) {\n const ch = sql[i];\n const next = i + 1 < len ? sql[i + 1] : '';\n\n // Handle exiting comments/strings first\n if (inLC) {\n out.push(ch);\n i++;\n if (ch === '\\n') inLC = false;\n continue;\n }\n if (inBC) {\n out.push(ch);\n i++;\n if (ch === '*' && next === '/') {\n out.push(next);\n i++;\n inBC = false;\n }\n continue;\n }\n if (inSQ) {\n out.push(ch);\n i++;\n // escape '' inside string\n if (ch === \"'\" && next === \"'\") {\n out.push(next);\n i++;\n } else if (ch === \"'\") {\n inSQ = false;\n }\n continue;\n }\n if (inDQ) {\n out.push(ch);\n i++;\n // escape \"\" inside identifier\n if (ch === '\"' && next === '\"') {\n out.push(next);\n i++;\n } else if (ch === '\"') {\n inDQ = false;\n }\n continue;\n }\n\n // Not inside string/comment\n if (ch === '-' && next === '-') {\n out.push(ch, next);\n i += 2;\n inLC = true;\n continue;\n }\n if (ch === '/' && next === '*') {\n out.push(ch, next);\n i += 2;\n inBC = true;\n continue;\n }\n if (ch === \"'\") {\n out.push(ch);\n i++;\n inSQ = true;\n continue;\n }\n if (ch === '\"') {\n out.push(ch);\n i++;\n inDQ = true;\n continue;\n }\n\n // Postgres cast :: — skip as literal\n if (ch === ':' && next === ':') {\n out.push('::');\n i += 2;\n continue;\n }\n\n if (ch === ':') {\n // Check for :update(...) syntax (case-insensitive)\n const updateMatch = /^:update\\s*\\(/i.exec(sql.slice(i));\n if (updateMatch) {\n if (isArrayArgs) {\n throw new Error(':update() syntax only works with named parameters');\n }\n \n // Parse the column list inside parentheses\n let j = i + updateMatch[0].length; // Skip ':update('\n const columnStart = j;\n let parenDepth = 1;\n let inString = false;\n let stringChar = '';\n \n // Find matching closing parenthesis\n while (j < len && parenDepth > 0) {\n const c = sql[j];\n const cNext = j + 1 < len ? sql[j + 1] : '';\n \n if (!inString) {\n if (c === \"'\" || c === '\"') {\n inString = true;\n stringChar = c;\n } else if (c === '(') {\n parenDepth++;\n } else if (c === ')') {\n parenDepth--;\n }\n } else {\n if (c === stringChar) {\n // Check for escaped quote\n if (cNext === stringChar) {\n j++; // Skip escaped quote\n } else {\n inString = false;\n }\n }\n }\n if (parenDepth > 0) j++;\n }\n \n if (parenDepth > 0) {\n throw new Error('Unclosed :update() parentheses');\n }\n \n // Extract column list (between the parentheses)\n const columnList = sql.slice(columnStart, j).trim();\n const updateEnd = j + 1; // Include closing ')'\n \n // Parse column list (split by comma, respecting quotes and parentheses)\n const items: string[] = [];\n let current = '';\n let inSQ = false; // single quote string\n let inDQ = false; // double quote identifier\n let itemParenDepth = 0;\n \n for (let k = 0; k < columnList.length; k++) {\n const ch = columnList[k];\n const next = k + 1 < columnList.length ? columnList[k + 1] : '';\n \n if (inSQ) {\n current += ch;\n if (ch === \"'\" && next === \"'\") {\n current += next;\n k++;\n } else if (ch === \"'\") {\n inSQ = false;\n }\n continue;\n }\n \n if (inDQ) {\n current += ch;\n if (ch === '\"' && next === '\"') {\n current += next;\n k++;\n } else if (ch === '\"') {\n inDQ = false;\n }\n continue;\n }\n \n if (ch === \"'\") {\n current += ch;\n inSQ = true;\n continue;\n }\n \n if (ch === '\"') {\n current += ch;\n inDQ = true;\n continue;\n }\n \n if (ch === '(') {\n current += ch;\n itemParenDepth++;\n continue;\n }\n \n if (ch === ')') {\n current += ch;\n itemParenDepth--;\n continue;\n }\n \n if (ch === ',' && itemParenDepth === 0) {\n const trimmed = current.trim();\n if (trimmed.length > 0) {\n items.push(trimmed);\n }\n current = '';\n continue;\n }\n \n current += ch;\n }\n \n // Add the last item\n const trimmed = current.trim();\n if (trimmed.length > 0) {\n items.push(trimmed);\n }\n \n if (items.length === 0) {\n throw new Error(':update() requires at least one column name');\n }\n \n // Build SET clause with literal expressions and parameterized columns\n const obj = args as Record<string, unknown>;\n const setParts: string[] = [];\n const updateParams: unknown[] = [];\n let hasParameterized = false;\n \n for (const item of items) {\n const trimmed = item.trim();\n \n // Check if this is a literal expression (contains = not inside quotes)\n let isLiteral = false;\n let eqIndex = -1;\n let inString = false;\n let stringChar = '';\n \n for (let k = 0; k < trimmed.length; k++) {\n const ch = trimmed[k];\n const next = k + 1 < trimmed.length ? trimmed[k + 1] : '';\n \n if (!inString && (ch === \"'\" || ch === '\"')) {\n inString = true;\n stringChar = ch;\n } else if (inString) {\n if (ch === stringChar) {\n if (next === stringChar) {\n k++; // Skip escaped quote\n } else {\n inString = false;\n }\n }\n } else if (ch === '=') {\n eqIndex = k;\n isLiteral = true;\n break;\n }\n }\n \n if (isLiteral && eqIndex >= 0) {\n // Literal SQL expression - include as-is\n setParts.push(trimmed);\n } else {\n // Parameterized column - check if defined in args\n hasParameterized = true;\n if (Object.prototype.hasOwnProperty.call(obj, trimmed) && obj[trimmed] !== undefined) {\n setParts.push(`${trimmed} = ${placeholder(pgIndex)}`);\n updateParams.push(obj[trimmed]);\n }\n }\n }\n \n // Only throw error if all parameterized columns are undefined (literals are always included)\n if (hasParameterized && setParts.length === 0) {\n throw new Error('All columns in :update() are undefined');\n }\n \n if (setParts.length === 0) {\n throw new Error(':update() requires at least one column name');\n }\n \n // Replace :update(...) with SET clause\n out.push('SET ', setParts.join(', '));\n params.push(...updateParams);\n \n i = updateEnd;\n continue;\n }\n \n // Attempt to parse a parameter token\n let j = i + 1;\n const start = j;\n while (j < len) {\n const c = sql[j];\n if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c === '_') {\n j++;\n } else {\n break;\n }\n }\n const name = sql.slice(start, j);\n if (!name) {\n // not a parameter — keep literal ':'\n out.push(':');\n i++;\n continue;\n }\n\n // Decide positional vs named\n const m = /^arg([1-9][0-9]*)$/.exec(name);\n const isPos = !!m;\n if (isPos) sawPositional = true; else sawNamed = true;\n if (sawNamed && sawPositional) {\n throw new Error('Cannot mix named and positional parameters in a single query');\n }\n\n let value: unknown;\n if (isPos) {\n if (!isArrayArgs) throw new Error('Positional placeholders require array arguments');\n const index = parseInt(m![1], 10) - 1; // 1-based in SQL\n const arr = args as unknown[];\n if (index < 0 || index >= arr.length) throw new Error(`Missing positional argument :${name}`);\n value = arr[index];\n } else {\n if (isArrayArgs) throw new Error('Named placeholders require a parameter object');\n const obj = args as Record<string, unknown>;\n if (!Object.prototype.hasOwnProperty.call(obj, name)) {\n throw new Error(`Missing named parameter :${name}`);\n }\n value = obj[name];\n }\n\n if (value === undefined) {\n throw new Error(`Parameter :${name} is undefined`);\n }\n\n // Expand placeholder(s)\n if (Array.isArray(value)) {\n if (value.length === 0) throw new Error(`Array parameter :${name} must not be empty`);\n const placeholders: string[] = [];\n for (const v of value) {\n if (v === undefined) throw new Error(`Array parameter :${name} contains undefined`);\n placeholders.push(placeholder(pgIndex));\n params.push(v === undefined ? null : v);\n }\n out.push(placeholders.join(', '));\n } else {\n out.push(placeholder(pgIndex));\n params.push(value === undefined ? null : value);\n }\n\n i = j;\n continue;\n }\n\n // default: copy char\n out.push(ch);\n i++;\n }\n\n return { sql: out.join(''), params };\n },\n };\n}\n\nexport const createMysqlBinder = () => createBinder('mysql');\nexport const createSqliteBinder = () => createBinder('sqlite');\nexport const createPostgresBinder = () => createBinder('postgres');\n\n// Re-export the shared helper for use in decorators\nexport { extractNamedParams };\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sqlstack",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "",