@devbro/neko-sql 0.1.15 → 0.1.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.
package/dist/index.js CHANGED
@@ -76,7 +76,8 @@ var Query = class _Query {
76
76
  having: [],
77
77
  orderBy: [],
78
78
  limit: null,
79
- offset: null
79
+ offset: null,
80
+ alias: null
80
81
  };
81
82
  table(tableName) {
82
83
  this.parts.table = tableName;
@@ -166,7 +167,15 @@ var Query = class _Query {
166
167
  return this.grammar.toSql(this);
167
168
  }
168
169
  async get() {
169
- return await this.connection?.runQuery(this.toSql());
170
+ let sql = this.toSql();
171
+ return await this.connection?.runQuery(sql);
172
+ }
173
+ async first() {
174
+ let rc = await this.connection?.runQuery(this.toSql());
175
+ if (rc && Array.isArray(rc) && rc.length > 0) {
176
+ return rc[0];
177
+ }
178
+ return void 0;
170
179
  }
171
180
  async count() {
172
181
  const csql = this.grammar.compileCount(this);
@@ -232,9 +241,14 @@ var Query = class _Query {
232
241
  crossJoin(table, conditions) {
233
242
  return this.join(table, "cross", conditions);
234
243
  }
244
+ alias(alias) {
245
+ this.parts.alias = alias;
246
+ return this;
247
+ }
235
248
  };
236
249
 
237
250
  // src/QueryGrammar.mts
251
+ var import_sql_tokenizer = require("sql-tokenizer");
238
252
  function toUpperFirst(str) {
239
253
  return str.substring(0, 1).toUpperCase() + str.substring(1);
240
254
  }
@@ -255,79 +269,118 @@ var QueryGrammar = class {
255
269
  "offset"
256
270
  ];
257
271
  toSql(query) {
258
- let sql = "";
272
+ let rc = this.toSqlParts(query);
273
+ rc.sql = this.joinArray(rc.parts);
274
+ return rc;
275
+ }
276
+ toSqlParts(query) {
277
+ let parts = [];
259
278
  let bindings = [];
260
279
  for (const part of this.sqlParts) {
261
280
  const funcName = "compile" + toUpperFirst(part);
262
281
  const r = this[funcName](query.parts[part]);
263
- if (!sql) {
264
- sql = r.sql;
265
- } else if (r.sql) {
266
- sql += " " + r.sql;
267
- }
268
282
  bindings = [...bindings, ...r.bindings];
283
+ parts = [...parts, ...r.parts];
269
284
  }
270
- return { sql, bindings };
285
+ return {
286
+ sql: "",
287
+ bindings,
288
+ parts
289
+ };
271
290
  }
272
291
  compileCount(query) {
273
292
  let sql = "";
274
293
  let bindings = [];
294
+ let parts = [];
275
295
  for (const part of this.sqlParts) {
276
- let parts = query.parts[part];
296
+ let parts2 = query.parts[part];
277
297
  if (part === "select") {
278
- parts = ["count(*) as count"];
298
+ parts2 = ["count(*) as count"];
279
299
  }
280
300
  const funcName = "compile" + toUpperFirst(part);
281
- const r = this[funcName](parts);
282
- if (!sql) {
283
- sql = r.sql;
284
- } else if (r.sql) {
285
- sql += " " + r.sql;
286
- }
301
+ const r = this[funcName](parts2);
287
302
  bindings = [...bindings, ...r.bindings];
303
+ parts = [...parts, ...r.parts];
288
304
  }
289
- return { sql, bindings };
305
+ return { sql, parts, bindings };
290
306
  }
291
307
  compileSelect(selects) {
292
- const rc = selects.map((v) => {
293
- return v;
294
- }).join(", ");
295
- return { sql: "select " + rc, bindings: [] };
308
+ const parts = ["select"];
309
+ selects.map((v) => {
310
+ parts.push(v);
311
+ parts.push(",");
312
+ });
313
+ parts.pop();
314
+ return { sql: this.joinArray(parts), parts, bindings: [] };
296
315
  }
297
- compileTable(tableName) {
316
+ joinArray(arr) {
298
317
  let rc = "";
318
+ let last = "";
319
+ for (const a of arr) {
320
+ if (a === ",") {
321
+ rc += a;
322
+ } else if (last === "(" || last === " " || a === ")") {
323
+ rc += a;
324
+ } else if (a === "") {
325
+ rc += "";
326
+ } else {
327
+ rc += " " + a;
328
+ }
329
+ last = a;
330
+ }
331
+ return rc.trim();
332
+ }
333
+ compileTable(tableName) {
334
+ let parts = [];
299
335
  if (tableName.length) {
300
- rc = "from " + tableName;
336
+ parts.push("from");
337
+ parts.push(tableName);
301
338
  }
302
- return { sql: rc, bindings: [] };
339
+ return { sql: parts.join(" "), parts, bindings: [] };
303
340
  }
304
341
  compileJoin(joins) {
305
342
  let sql = "";
306
343
  let bindings = [];
344
+ let parts = [];
307
345
  for (const j of joins) {
308
- sql += " " + j.type + " join " + j.table + " on ";
309
- const where = this.compileWhere(j.conditions);
310
- if (where.sql.startsWith("where ")) {
311
- where.sql = where.sql.substring("where ".length);
346
+ let table = "";
347
+ let table_bindings = [];
348
+ parts.push(j.type);
349
+ parts.push("join");
350
+ if (typeof j.table === "string") {
351
+ parts.push(j.table);
352
+ } else {
353
+ const subQuery = j.table;
354
+ const { parts: parts2, bindings: bindings2 } = subQuery.toSql();
355
+ parts = [...parts, "(", ...parts2, ")", "as", subQuery.parts.alias || "subquery"];
356
+ table_bindings = bindings2;
312
357
  }
313
- sql += "(";
314
- sql += where.sql;
315
- sql += ")";
316
- bindings = [...bindings, ...where.bindings];
358
+ parts.push("on");
359
+ const where = this.compileWhere(j.conditions);
360
+ const where_parts = where.parts;
361
+ where_parts.shift();
362
+ parts.push("(");
363
+ parts = [...parts, ...where_parts];
364
+ parts.push(")");
365
+ bindings = [...bindings, ...table_bindings, ...where.bindings];
317
366
  }
318
- return { sql, bindings };
367
+ return { sql, parts, bindings };
319
368
  }
320
369
  compileWhere(wheres) {
321
370
  let sql = "";
322
371
  let bindings = [];
372
+ let parts = [];
323
373
  for (const w of wheres) {
324
374
  sql += " " + w.joinCondition + " ";
375
+ parts.push(w.joinCondition);
325
376
  if (w.negateCondition) {
326
377
  sql += "not ";
378
+ parts.push("not");
327
379
  }
328
380
  const funcName = "compileWhere" + toUpperFirst(w.type);
329
381
  const wh = this[funcName](w);
330
382
  sql += wh.sql;
383
+ parts = parts.concat(wh.parts);
331
384
  bindings = [...bindings, ...wh.bindings];
332
385
  }
333
386
  if (sql.startsWith(" and ")) {
@@ -335,159 +388,197 @@ var QueryGrammar = class {
335
388
  } else if (sql.startsWith(" or ")) {
336
389
  sql = "where " + sql.substring(" or ".length);
337
390
  }
338
- return { sql, bindings };
391
+ if (parts.length > 0) {
392
+ parts[0] = "where";
393
+ }
394
+ return { sql, parts, bindings };
339
395
  }
340
396
  compileWhereNested(w) {
341
397
  const subQuery = w.query;
342
- const { sql, bindings } = subQuery.grammar.compileWhere(subQuery.parts.where);
398
+ let parts = [];
399
+ const { sql, parts: parts2, bindings } = subQuery.grammar.compileWhere(subQuery.parts.where);
343
400
  let sql2 = sql.replace(/^where /, "");
401
+ parts2.shift();
402
+ parts.push("(");
403
+ parts = parts.concat(parts2);
404
+ parts.push(")");
344
405
  return {
345
406
  sql: `(${sql2})`,
407
+ parts,
346
408
  bindings
347
409
  };
348
410
  }
349
411
  compileWhereOperation(w) {
350
412
  if (w.operation.toLowerCase() === "in" && Array.isArray(w.value)) {
351
413
  return {
352
- sql: `${w.column} = ANY(${this.getVariablePlaceholder()})`,
414
+ sql: `${w.column} = ANY( ? )`,
415
+ parts: [w.column, " = ANY(", "?", ")"],
353
416
  bindings: [w.value]
354
417
  };
355
418
  }
356
419
  return {
357
- sql: `${w.column} ${w.operation} ${this.getVariablePlaceholder()}`,
420
+ sql: `${w.column} ${w.operation} ?`,
421
+ parts: [w.column, w.operation, "?"],
358
422
  bindings: [w.value]
359
423
  };
360
424
  }
361
425
  compileWhereOperationColumn(w) {
362
426
  return {
363
427
  sql: `${w.column1} ${w.operation} ${w.column2}`,
428
+ parts: [w.column1, w.operation, w.column2],
364
429
  bindings: []
365
430
  };
366
431
  }
367
432
  compileWhereRaw(w) {
433
+ const tokenize = (0, import_sql_tokenizer.sqlTokenizer)();
368
434
  return {
369
435
  sql: w.sql,
436
+ parts: tokenize(w.sql).filter((t) => t !== " "),
370
437
  bindings: w.bindings
371
438
  };
372
439
  }
373
440
  compileOrderBy(orderBy) {
374
441
  let rc = "";
442
+ let parts = [];
375
443
  if (orderBy.length) {
376
444
  rc = "order by " + orderBy.join(", ");
445
+ parts.push("order by");
446
+ parts = parts.concat(orderBy);
377
447
  }
378
- return { sql: rc, bindings: [] };
448
+ return { sql: rc, parts, bindings: [] };
379
449
  }
380
450
  compileLimit(limit) {
381
451
  let rc = "";
452
+ let parts = [];
382
453
  if (limit !== null) {
383
454
  rc = "limit " + limit;
455
+ parts.push("limit");
456
+ parts.push(limit);
384
457
  }
385
- return { sql: rc, bindings: [] };
458
+ return { sql: rc, parts, bindings: [] };
386
459
  }
387
460
  compileOffset(offset) {
388
461
  let rc = "";
462
+ let parts = [];
389
463
  if (offset !== null) {
390
464
  rc = "offset " + offset;
465
+ parts.push("offset");
466
+ parts.push(offset);
391
467
  }
392
- return { sql: rc, bindings: [] };
468
+ return { sql: rc, parts, bindings: [] };
393
469
  }
394
470
  compileWhereNull(w) {
395
471
  return {
396
472
  sql: `${w.column} is null`,
473
+ parts: [w.column, "is", "null"],
397
474
  bindings: []
398
475
  };
399
476
  }
400
477
  compileInsert(query, data) {
401
- let sql = "insert into " + query.parts.table + " (";
478
+ let parts = ["insert", "into", query.parts.table, "("];
402
479
  const columns = [];
403
480
  const bindings = [];
404
481
  const values = [];
405
482
  for (const [k, v] of Object.entries(data)) {
406
- columns.push(k);
483
+ parts.push(k);
484
+ parts.push(",");
485
+ }
486
+ parts.pop();
487
+ parts = parts.concat([")", "values", "("]);
488
+ for (const [k, v] of Object.entries(data)) {
489
+ parts.push("?");
407
490
  bindings.push(v);
408
- values.push(this.getVariablePlaceholder());
491
+ parts.push(",");
409
492
  }
410
- sql += columns.join(", ") + ") values (" + values + ")";
411
- return { sql, bindings };
493
+ parts.pop();
494
+ parts.push(")");
495
+ return { sql: parts.join(" "), parts, bindings };
412
496
  }
413
497
  compileUpdate(query, data) {
414
- let sql = "update " + query.parts.table + " set ";
415
498
  const bindings = [];
499
+ let parts = ["update", query.parts.table, "set"];
416
500
  const setParts = [];
417
501
  for (const [k, v] of Object.entries(data)) {
418
- setParts.push(`${k} = ${this.getVariablePlaceholder()}`);
502
+ parts = parts.concat([k, "=", "?", ","]);
503
+ setParts.push(`${k} = ?`);
419
504
  bindings.push(v);
420
505
  }
421
- sql += setParts.join(", ");
506
+ parts.pop();
422
507
  const where_csql = this.compileWhere(query.parts.where);
423
- sql += " " + where_csql.sql;
508
+ parts = parts.concat(where_csql.parts);
424
509
  bindings.push(...where_csql.bindings);
425
- return { sql, bindings };
510
+ return { sql: parts.join(" "), parts, bindings };
426
511
  }
427
512
  compileDelete(query) {
428
513
  let sql = "delete from " + query.parts.table;
514
+ let parts = ["delete", "from", query.parts.table];
429
515
  const where_csql = this.compileWhere(query.parts.where);
430
516
  sql += " " + where_csql.sql;
431
- return { sql, bindings: where_csql.bindings };
517
+ parts = parts.concat(where_csql.parts);
518
+ return { sql, parts, bindings: where_csql.bindings };
432
519
  }
433
520
  compileUpsert(query, data, conflictFields, updateFields) {
434
- let sql = "insert into " + query.parts.table + " (";
435
- const columns = [];
521
+ let parts = [];
436
522
  const bindings = [];
437
- const values = [];
438
- for (const [k, v] of Object.entries(data)) {
439
- columns.push(k);
440
- bindings.push(v);
441
- values.push(this.getVariablePlaceholder());
442
- }
443
- sql += columns.join(", ") + ") values (" + values + ")";
444
- sql += " on conflict (" + conflictFields.join(", ") + ") do update set ";
523
+ let isql = this.compileInsert(query, data);
524
+ parts = isql.parts;
525
+ bindings.push(...isql.bindings);
526
+ parts = parts.concat(["on", "conflict", "(", ...conflictFields, ")", "do", "update", "set"]);
445
527
  const setParts = [];
446
528
  for (const f of updateFields) {
447
529
  setParts.push(`${f} = excluded.${f}`);
530
+ setParts.push(`,`);
448
531
  }
449
- sql += setParts.join(", ");
532
+ setParts.pop();
533
+ parts = parts.concat(setParts);
450
534
  const where_csql = this.compileWhere(query.parts.where);
451
- sql += " " + where_csql.sql;
535
+ parts = parts.concat(where_csql.parts);
452
536
  bindings.push(...where_csql.bindings);
453
- return { sql, bindings };
537
+ return { sql: parts.join(" "), parts, bindings };
454
538
  }
455
539
  compileGroupBy(groupBy) {
456
540
  let rc = "";
541
+ let parts = [];
457
542
  if (groupBy.length) {
458
543
  rc = "group by " + groupBy.join(", ");
544
+ parts.push("group by");
545
+ parts = parts.concat(groupBy);
459
546
  }
460
- return { sql: rc, bindings: [] };
547
+ return { sql: rc, parts, bindings: [] };
461
548
  }
462
549
  compileHaving(having) {
463
550
  let sql = "";
464
551
  let bindings = [];
552
+ let parts = [];
465
553
  for (const w of having) {
466
554
  sql += " " + w.joinCondition + " ";
555
+ parts.push(w.joinCondition);
467
556
  if (w.negateCondition) {
468
557
  sql += "not ";
558
+ parts.push("not");
469
559
  }
470
560
  const funcName = "compileHaving" + toUpperFirst(w.type);
471
561
  const wh = this[funcName](w);
562
+ parts = parts.concat(wh.parts);
472
563
  sql += wh.sql;
473
564
  bindings = [...bindings, ...wh.bindings];
474
565
  }
475
- if (sql.startsWith(" and ")) {
476
- sql = "having " + sql.substring(" and ".length);
477
- } else if (sql.startsWith(" or ")) {
478
- sql = "having " + sql.substring(" or ".length);
566
+ if (parts.length > 0) {
567
+ parts[0] = "having";
479
568
  }
480
- return { sql, bindings };
569
+ return { sql: parts.join(" "), parts, bindings };
481
570
  }
482
571
  compileHavingOperation(w) {
483
572
  return {
484
- sql: `${w.column} ${w.operation} ${this.getVariablePlaceholder()}`,
573
+ sql: `${w.column} ${w.operation} ?`,
574
+ parts: [w.column, w.operation, "?"],
485
575
  bindings: [w.value]
486
576
  };
487
577
  }
488
578
  compileHavingRaw(w) {
489
579
  return {
490
580
  sql: w.sql,
581
+ parts: w.sql.split(" "),
491
582
  bindings: w.bindings
492
583
  };
493
584
  }
@@ -498,47 +589,36 @@ var PostgresqlQueryGrammar = class extends QueryGrammar {
498
589
  static {
499
590
  __name(this, "PostgresqlQueryGrammar");
500
591
  }
501
- parameterIndex;
502
592
  constructor() {
503
593
  super();
504
- this.parameterIndex = 1;
505
594
  }
506
595
  toSql(query) {
507
- this.parameterIndex = 1;
508
596
  return super.toSql(query);
509
597
  }
510
- getVariablePlaceholder() {
511
- return "$" + this.parameterIndex++;
512
- }
513
598
  compileInsert(query, data) {
514
- this.parameterIndex = 1;
515
599
  return super.compileInsert(query, data);
516
600
  }
517
601
  compileInsertGetId(query, data, options = { primaryKey: ["id"] }) {
518
- this.parameterIndex = 1;
519
602
  const rc = super.compileInsert(query, data);
520
603
  rc.sql += ` RETURNING ${options.primaryKey.join(", ")}`;
521
604
  return rc;
522
605
  }
523
606
  compileUpdate(query, data) {
524
- this.parameterIndex = 1;
525
607
  return super.compileUpdate(query, data);
526
608
  }
527
609
  compileDelete(query) {
528
- this.parameterIndex = 1;
529
610
  return super.compileDelete(query);
530
611
  }
531
612
  compileUpsert(query, data, conflictFields, updateFields) {
532
- this.parameterIndex = 1;
533
613
  return super.compileUpsert(query, data, conflictFields, updateFields);
534
614
  }
535
615
  compileCount(query) {
536
- this.parameterIndex = 1;
537
616
  return super.compileCount(query);
538
617
  }
539
618
  };
540
619
 
541
620
  // src/Expression.mts
621
+ var import_sql_tokenizer2 = require("sql-tokenizer");
542
622
  var Expression = class {
543
623
  constructor(sql = "", bindings = []) {
544
624
  this.sql = sql;
@@ -548,7 +628,8 @@ var Expression = class {
548
628
  __name(this, "Expression");
549
629
  }
550
630
  toCompiledSql() {
551
- return { sql: this.sql, bindings: this.bindings };
631
+ const tokenize = (0, import_sql_tokenizer2.sqlTokenizer)(this.sql);
632
+ return { sql: this.sql, bindings: this.bindings, parts: tokenize(this.sql) };
552
633
  }
553
634
  };
554
635
 
@@ -792,13 +873,14 @@ var SchemaGrammar = class {
792
873
  });
793
874
  }
794
875
  sql += [columns, primaryKeys, ...foreignKeys].join(",") + ")";
795
- const compiledSql = { sql, bindings: [] };
876
+ const compiledSql = { sql, parts: [], bindings: [] };
796
877
  if (blueprint.indexes.length > 0) {
797
878
  const indexSqls = blueprint.indexes.map((index) => {
798
879
  return this.compileIndex(blueprint.tableName, index);
799
880
  });
800
881
  return {
801
882
  sql: [compiledSql.sql, ...indexSqls.map((idx) => idx.sql)].join("; "),
883
+ parts: [],
802
884
  bindings: compiledSql.bindings
803
885
  };
804
886
  }
@@ -818,9 +900,9 @@ var SchemaGrammar = class {
818
900
  }
819
901
  let compiledSql;
820
902
  if (alterStatements.length > 0) {
821
- compiledSql = { sql: sql.join(" "), bindings: [] };
903
+ compiledSql = { sql: sql.join(" "), parts: [], bindings: [] };
822
904
  } else {
823
- compiledSql = { sql: sql.join(" ") + " ", bindings: [] };
905
+ compiledSql = { sql: sql.join(" ") + " ", parts: [], bindings: [] };
824
906
  }
825
907
  if (blueprint.indexes.length > 0) {
826
908
  const indexSqls = blueprint.indexes.map((index) => {
@@ -828,6 +910,7 @@ var SchemaGrammar = class {
828
910
  });
829
911
  return {
830
912
  sql: [compiledSql.sql, ...indexSqls.map((idx) => idx.sql)].join("; "),
913
+ parts: [],
831
914
  bindings: compiledSql.bindings
832
915
  };
833
916
  }
@@ -907,20 +990,26 @@ var SchemaGrammar = class {
907
990
  compileTables(schema = void 0) {
908
991
  return {
909
992
  sql: "select c.relname as name, n.nspname as schema, pg_total_relation_size(c.oid) as size, obj_description(c.oid, 'pg_class') as comment from pg_class c, pg_namespace n where c.relkind in ('r', 'p') and n.oid = c.relnamespace and " + this.compileSchemaWhereClause(schema, "n.nspname") + " order by n.nspname, c.relname",
993
+ parts: [],
910
994
  bindings: []
911
995
  };
912
996
  }
913
997
  compileTableExists(tableName, schema = "") {
914
998
  return {
915
999
  sql: "select exists (select 1 from pg_class c, pg_namespace n where n.nspname = " + (schema ? this.escape(schema) : "current_schema()") + " and c.relname = $1 and c.relkind in ('r', 'p') and n.oid = c.relnamespace)",
1000
+ parts: [],
916
1001
  bindings: [tableName]
917
1002
  };
918
1003
  }
919
1004
  compileDropTable(tableName) {
920
- return { sql: `drop table ${this.doubleQuoteString(tableName)}`, bindings: [] };
1005
+ return { sql: `drop table ${this.doubleQuoteString(tableName)}`, parts: [], bindings: [] };
921
1006
  }
922
1007
  compileDropTableIfExists(tableName) {
923
- return { sql: `drop table if exists ${this.doubleQuoteString(tableName)}`, bindings: [] };
1008
+ return {
1009
+ sql: `drop table if exists ${this.doubleQuoteString(tableName)}`,
1010
+ parts: [],
1011
+ bindings: []
1012
+ };
924
1013
  }
925
1014
  compileSchemaWhereClause(schema, column) {
926
1015
  if (Array.isArray(schema) && schema.length > 0) {
@@ -959,7 +1048,7 @@ var SchemaGrammar = class {
959
1048
  const uniqueKeyword = index.unique ? "unique " : "";
960
1049
  const indexType = index._type ? ` using ${index._type}` : "";
961
1050
  const sql = `create ${uniqueKeyword}index ${indexName} on ${tableName}${indexType} (${index.columns.join(", ")})`;
962
- return { sql, bindings: [] };
1051
+ return { sql, parts: [], bindings: [] };
963
1052
  }
964
1053
  };
965
1054
 
@@ -978,7 +1067,7 @@ var Schema = class {
978
1067
  structMethod(blueprint);
979
1068
  const grammar = new SchemaGrammar();
980
1069
  const sql = grammar.toSql(blueprint);
981
- await this.connection?.runQuery({ sql, bindings: [] });
1070
+ await this.connection?.runQuery({ sql, parts: [], bindings: [] });
982
1071
  }
983
1072
  async alterTable(tableName, structMethod) {
984
1073
  const blueprint = new Blueprint();
@@ -986,7 +1075,7 @@ var Schema = class {
986
1075
  structMethod(blueprint);
987
1076
  const grammar = new SchemaGrammar();
988
1077
  const sql = grammar.toSql(blueprint);
989
- await this.connection?.runQuery({ sql, bindings: [] });
1078
+ await this.connection?.runQuery({ sql, parts: [], bindings: [] });
990
1079
  }
991
1080
  async dropTable(tableName) {
992
1081
  const grammar = new SchemaGrammar();
@@ -1042,7 +1131,12 @@ var PostgresqlConnection = class _PostgresqlConnection extends Connection {
1042
1131
  return true;
1043
1132
  }
1044
1133
  async runQuery(sql) {
1045
- const result = await this.connection?.query(sql.sql, sql.bindings);
1134
+ let counter = 1;
1135
+ let sql2 = sql.sql;
1136
+ if (sql.parts && sql.parts.length > 0) {
1137
+ sql2 = sql.parts.map((v) => v === "?" ? "$" + counter++ : v).join(" ");
1138
+ }
1139
+ const result = await this.connection?.query(sql2, sql.bindings);
1046
1140
  return result?.rows;
1047
1141
  }
1048
1142
  async runCursor(sql) {