@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.
@@ -38,8 +38,10 @@ declare class Schema {
38
38
  declare abstract class QueryGrammar {
39
39
  sqlParts: string[];
40
40
  toSql(query: Query): CompiledSql;
41
+ toSqlParts(query: Query): CompiledSql;
41
42
  compileCount(query: Query): CompiledSql;
42
43
  compileSelect(selects: selectType[]): CompiledSql;
44
+ joinArray(arr: (string | number)[]): string;
43
45
  compileTable(tableName: string): CompiledSql;
44
46
  compileJoin(joins: joinType[]): CompiledSql;
45
47
  compileWhere(wheres: whereType[]): CompiledSql;
@@ -50,7 +52,6 @@ declare abstract class QueryGrammar {
50
52
  compileOrderBy(orderBy: string[]): CompiledSql;
51
53
  compileLimit(limit: number | null): CompiledSql;
52
54
  compileOffset(offset: number | null): CompiledSql;
53
- abstract getVariablePlaceholder(): string;
54
55
  compileWhereNull(w: whereNull): CompiledSql;
55
56
  compileInsert(query: Query, data: Record<string, Parameter>): CompiledSql;
56
57
  abstract compileInsertGetId(query: Query, data: Record<string, Parameter>, options: {
@@ -89,6 +90,7 @@ type QueryParts = {
89
90
  orderBy: string[];
90
91
  limit: number | null;
91
92
  offset: number | null;
93
+ alias: string | null;
92
94
  };
93
95
  declare class Query {
94
96
  readonly connection: Connection | null;
@@ -112,6 +114,7 @@ declare class Query {
112
114
  offset(offset: number): this;
113
115
  toSql(): CompiledSql;
114
116
  get(): Promise<any>;
117
+ first(): Promise<any>;
115
118
  count(): Promise<number>;
116
119
  getCursor(): Promise<any>;
117
120
  getConnection(): Connection | null;
@@ -122,30 +125,31 @@ declare class Query {
122
125
  update(data: Record<string, Parameter>): Promise<any>;
123
126
  upsert(data: Record<string, Parameter>, uniqueColumns: string[], updateColumns: string[]): Promise<any>;
124
127
  delete(): Promise<any>;
125
- join(table: string, type: joinType['type'], conditions: (whereType | {
128
+ join(table: string | Query, type: joinType['type'], conditions: (whereType | {
126
129
  column1: string;
127
130
  column2: string;
128
131
  })[]): this;
129
- innerJoin(table: string, conditions: (whereType | {
132
+ innerJoin(table: Parameters<typeof this.join>[0], conditions: (whereType | {
130
133
  column1: string;
131
134
  column2: string;
132
135
  })[]): this;
133
- leftJoin(table: string, conditions: (whereType | {
136
+ leftJoin(table: Parameters<typeof this.join>[0], conditions: (whereType | {
134
137
  column1: string;
135
138
  column2: string;
136
139
  })[]): this;
137
- rightJoin(table: string, conditions: (whereType | {
140
+ rightJoin(table: Parameters<typeof this.join>[0], conditions: (whereType | {
138
141
  column1: string;
139
142
  column2: string;
140
143
  })[]): this;
141
- fullJoin(table: string, conditions: (whereType | {
144
+ fullJoin(table: Parameters<typeof this.join>[0], conditions: (whereType | {
142
145
  column1: string;
143
146
  column2: string;
144
147
  })[]): this;
145
- crossJoin(table: string, conditions: (whereType | {
148
+ crossJoin(table: Parameters<typeof this.join>[0], conditions: (whereType | {
146
149
  column1: string;
147
150
  column2: string;
148
151
  })[]): this;
152
+ alias(alias: string): this;
149
153
  }
150
154
 
151
155
  type selectType = string;
@@ -183,12 +187,13 @@ type Parameter = string | number | Date | boolean | null | Expression | undefine
183
187
  type JoinCondition = 'and' | 'or';
184
188
  type CompiledSql = {
185
189
  sql: string;
190
+ parts: (string | number)[];
186
191
  bindings: Parameter[];
187
192
  };
188
193
  type havingType = whereBasic & (whereOp | whereRaw);
189
194
  type joinType = {
190
195
  type: 'inner' | 'left' | 'right' | 'full' | 'cross';
191
- table: string;
196
+ table: string | Query;
192
197
  conditions: whereType[];
193
198
  };
194
199
 
@@ -1 +1 @@
1
- export { B as Blueprint, a as Column, C as ColumnPropertiesType, F as ForeignKeyConstraint, I as IndexConstraint } from './Blueprint-mmlqFfF6.mjs';
1
+ export { B as Blueprint, a as Column, C as ColumnPropertiesType, F as ForeignKeyConstraint, I as IndexConstraint } from './Blueprint-DiSVtLdl.mjs';
@@ -1 +1 @@
1
- export { b as Connection } from './Blueprint-mmlqFfF6.mjs';
1
+ export { b as Connection } from './Blueprint-DiSVtLdl.mjs';
@@ -1 +1 @@
1
- export { E as Expression } from './Blueprint-mmlqFfF6.mjs';
1
+ export { E as Expression } from './Blueprint-DiSVtLdl.mjs';
@@ -1,5 +1,6 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+ import { sqlTokenizer } from "sql-tokenizer";
3
4
  class Expression {
4
5
  constructor(sql = "", bindings = []) {
5
6
  this.sql = sql;
@@ -9,7 +10,8 @@ class Expression {
9
10
  __name(this, "Expression");
10
11
  }
11
12
  toCompiledSql() {
12
- return { sql: this.sql, bindings: this.bindings };
13
+ const tokenize = sqlTokenizer(this.sql);
14
+ return { sql: this.sql, bindings: this.bindings, parts: tokenize(this.sql) };
13
15
  }
14
16
  }
15
17
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/Expression.mts"],"sourcesContent":["import { CompiledSql } from './types.mjs';\n\nexport class Expression {\n constructor(\n private sql = '',\n private bindings = []\n ) {}\n\n toCompiledSql(): CompiledSql {\n return { sql: this.sql, bindings: this.bindings };\n }\n}\n"],"mappings":";;AAEO,MAAM,WAAW;AAAA,EACtB,YACU,MAAM,IACN,WAAW,CAAC,GACpB;AAFQ;AACA;AAAA,EACP;AAAA,EANL,OAEwB;AAAA;AAAA;AAAA,EAMtB,gBAA6B;AAC3B,WAAO,EAAE,KAAK,KAAK,KAAK,UAAU,KAAK,SAAS;AAAA,EAClD;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/Expression.mts"],"sourcesContent":["import { CompiledSql } from './types.mjs';\n// @ts-ignore - no type definitions available for sql-tokenizer\nimport { sqlTokenizer } from 'sql-tokenizer';\n\nexport class Expression {\n constructor(\n private sql = '',\n private bindings = []\n ) {}\n\n toCompiledSql(): CompiledSql {\n const tokenize = sqlTokenizer(this.sql);\n return { sql: this.sql, bindings: this.bindings, parts: tokenize(this.sql) };\n }\n}\n"],"mappings":";;AAEA,SAAS,oBAAoB;AAEtB,MAAM,WAAW;AAAA,EACtB,YACU,MAAM,IACN,WAAW,CAAC,GACpB;AAFQ;AACA;AAAA,EACP;AAAA,EARL,OAIwB;AAAA;AAAA;AAAA,EAMtB,gBAA6B;AAC3B,UAAM,WAAW,aAAa,KAAK,GAAG;AACtC,WAAO,EAAE,KAAK,KAAK,KAAK,UAAU,KAAK,UAAU,OAAO,SAAS,KAAK,GAAG,EAAE;AAAA,EAC7E;AACF;","names":[]}
@@ -1,4 +1,4 @@
1
- import { S as Schema } from './Blueprint-mmlqFfF6.mjs';
1
+ import { S as Schema } from './Blueprint-DiSVtLdl.mjs';
2
2
 
3
3
  declare abstract class Migration {
4
4
  abstract up(schema: Schema): Promise<void>;
package/dist/Query.d.mts CHANGED
@@ -1 +1 @@
1
- export { c as Query, Q as QueryParts } from './Blueprint-mmlqFfF6.mjs';
1
+ export { c as Query, Q as QueryParts } from './Blueprint-DiSVtLdl.mjs';
package/dist/Query.mjs CHANGED
@@ -18,7 +18,8 @@ class Query {
18
18
  having: [],
19
19
  orderBy: [],
20
20
  limit: null,
21
- offset: null
21
+ offset: null,
22
+ alias: null
22
23
  };
23
24
  table(tableName) {
24
25
  this.parts.table = tableName;
@@ -108,7 +109,15 @@ class Query {
108
109
  return this.grammar.toSql(this);
109
110
  }
110
111
  async get() {
111
- return await this.connection?.runQuery(this.toSql());
112
+ let sql = this.toSql();
113
+ return await this.connection?.runQuery(sql);
114
+ }
115
+ async first() {
116
+ let rc = await this.connection?.runQuery(this.toSql());
117
+ if (rc && Array.isArray(rc) && rc.length > 0) {
118
+ return rc[0];
119
+ }
120
+ return void 0;
112
121
  }
113
122
  async count() {
114
123
  const csql = this.grammar.compileCount(this);
@@ -174,6 +183,10 @@ class Query {
174
183
  crossJoin(table, conditions) {
175
184
  return this.join(table, "cross", conditions);
176
185
  }
186
+ alias(alias) {
187
+ this.parts.alias = alias;
188
+ return this;
189
+ }
177
190
  }
178
191
  export {
179
192
  Query
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/Query.mts"],"sourcesContent":["import { Connection } from './Connection.mjs';\nimport { QueryGrammar } from './QueryGrammar.mjs';\nimport {\n CompiledSql,\n JoinCondition,\n Parameter,\n selectType,\n whereType,\n havingType,\n joinType,\n} from './types.mjs';\n\nexport type QueryParts = {\n select: selectType[];\n table: string;\n join: joinType[];\n where: whereType[];\n groupBy: string[];\n having: havingType[];\n orderBy: string[];\n limit: number | null;\n offset: number | null;\n};\n\nexport class Query {\n allowedOperations: string[] = ['=', '>', '<', '!=', 'like', 'ilike', 'in'];\n parts: QueryParts = {\n select: ['*'],\n table: '',\n join: [],\n where: [],\n groupBy: [],\n having: [],\n orderBy: [],\n limit: null,\n offset: null,\n };\n\n constructor(\n public readonly connection: Connection | null,\n public readonly grammar: QueryGrammar\n ) {}\n\n table(tableName: string): this {\n this.parts.table = tableName;\n return this;\n }\n\n whereNested(\n func: (q: Query) => void,\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ) {\n const subQuery = new Query(this.connection, this.grammar);\n func(subQuery);\n this.parts.where.push({\n type: 'nested',\n query: subQuery,\n joinCondition,\n negateCondition,\n });\n return this;\n }\n\n whereOp(\n column: string,\n operation: (typeof this.allowedOperations)[number],\n value: Parameter,\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ): this {\n this.parts.where.push({\n type: 'operation',\n column,\n operation,\n value,\n joinCondition,\n negateCondition,\n });\n return this;\n }\n\n whereRaw(\n sql: string,\n bindings: Parameter[],\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ): this {\n this.parts.where.push({ type: 'raw', sql, bindings, joinCondition, negateCondition });\n return this;\n }\n\n whereColumn(\n column1: string,\n operation: (typeof this.allowedOperations)[number],\n column2: string,\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ): this {\n this.parts.where.push({\n type: 'operationColumn',\n column1,\n operation,\n column2,\n joinCondition,\n negateCondition,\n });\n return this;\n }\n\n whereNull(\n column: string,\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ): this {\n this.parts.where.push({ type: 'null', column, joinCondition, negateCondition });\n return this;\n }\n\n clearWhere(): this {\n this.parts.where = [];\n return this;\n }\n\n select(selects: selectType[]): this {\n this.parts.select = [...selects];\n return this;\n }\n\n groupBy(columns: string[]): this {\n this.parts.groupBy = [...columns];\n return this;\n }\n\n havingOp(\n column: string,\n operation: (typeof this.allowedOperations)[number],\n value: Parameter,\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ): this {\n this.parts.having.push({\n type: 'operation',\n column,\n operation,\n value,\n joinCondition,\n negateCondition,\n });\n return this;\n }\n\n havingRaw(\n sql: string,\n bindings: Parameter[],\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ): this {\n this.parts.having.push({ type: 'raw', sql, bindings, joinCondition, negateCondition });\n return this;\n }\n\n orderBy(column: string, direction: 'asc' | 'desc' = 'asc'): this {\n this.parts.orderBy.push(`${column} ${direction}`);\n return this;\n }\n\n limit(limit: number): this {\n this.parts.limit = limit;\n return this;\n }\n\n offset(offset: number): this {\n this.parts.offset = offset;\n return this;\n }\n\n toSql(): CompiledSql {\n return this.grammar.toSql(this);\n }\n\n async get() {\n return await this.connection?.runQuery(this.toSql());\n }\n\n async count(): Promise<number> {\n const csql: CompiledSql = this.grammar.compileCount(this);\n const result = await this.connection?.runQuery(csql);\n if (result && Array.isArray(result) && result.length > 0) {\n return parseInt(result[0]['count'], 10);\n }\n return 0;\n }\n\n async getCursor() {\n return await this.connection?.runCursor(this.toSql());\n }\n\n getConnection(): Connection | null {\n return this.connection;\n }\n\n async insert(data: Record<string, Parameter>) {\n const csql: CompiledSql = this.grammar.compileInsert(this, data);\n return await this.connection?.runQuery(csql);\n }\n\n async insertGetId(\n data: Record<string, Parameter>,\n options: { primaryKey: string[] } = { primaryKey: ['id'] }\n ) {\n const csql: CompiledSql = this.grammar.compileInsertGetId(this, data, options);\n return await this.connection?.runQuery(csql);\n }\n\n async update(data: Record<string, Parameter>) {\n const csql: CompiledSql = this.grammar.compileUpdate(this, data);\n return await this.connection?.runQuery(csql);\n }\n\n async upsert(data: Record<string, Parameter>, uniqueColumns: string[], updateColumns: string[]) {\n const csql: CompiledSql = this.grammar.compileUpsert(this, data, uniqueColumns, updateColumns);\n return await this.connection?.runQuery(csql);\n }\n\n async delete() {\n const csql: CompiledSql = this.grammar.compileDelete(this);\n return await this.connection?.runQuery(csql);\n }\n\n join(\n table: string,\n type: joinType['type'],\n conditions: (whereType | { column1: string; column2: string })[]\n ): this {\n let conditions_corrected: whereType[] = [];\n for (const cond of conditions) {\n conditions_corrected.push({\n joinCondition: 'and',\n negateCondition: false,\n type: 'operationColumn',\n // @ts-ignore\n operation: '=',\n ...cond,\n });\n }\n this.parts.join.push({ type, table, conditions: conditions_corrected });\n return this;\n }\n\n innerJoin(table: string, conditions: (whereType | { column1: string; column2: string })[]): this {\n return this.join(table, 'inner', conditions);\n }\n\n leftJoin(table: string, conditions: (whereType | { column1: string; column2: string })[]): this {\n return this.join(table, 'left', conditions);\n }\n\n rightJoin(table: string, conditions: (whereType | { column1: string; column2: string })[]): this {\n return this.join(table, 'right', conditions);\n }\n\n fullJoin(table: string, conditions: (whereType | { column1: string; column2: string })[]): this {\n return this.join(table, 'full', conditions);\n }\n\n crossJoin(table: string, conditions: (whereType | { column1: string; column2: string })[]): this {\n return this.join(table, 'cross', conditions);\n }\n}\n"],"mappings":";;AAwBO,MAAM,MAAM;AAAA,EAcjB,YACkB,YACA,SAChB;AAFgB;AACA;AAAA,EACf;AAAA,EAzCL,OAwBmB;AAAA;AAAA;AAAA,EACjB,oBAA8B,CAAC,KAAK,KAAK,KAAK,MAAM,QAAQ,SAAS,IAAI;AAAA,EACzE,QAAoB;AAAA,IAClB,QAAQ,CAAC,GAAG;AAAA,IACZ,OAAO;AAAA,IACP,MAAM,CAAC;AAAA,IACP,OAAO,CAAC;AAAA,IACR,SAAS,CAAC;AAAA,IACV,QAAQ,CAAC;AAAA,IACT,SAAS,CAAC;AAAA,IACV,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAAA,EAOA,MAAM,WAAyB;AAC7B,SAAK,MAAM,QAAQ;AACnB,WAAO;AAAA,EACT;AAAA,EAEA,YACE,MACA,gBAA+B,OAC/B,kBAA2B,OAC3B;AACA,UAAM,WAAW,IAAI,MAAM,KAAK,YAAY,KAAK,OAAO;AACxD,SAAK,QAAQ;AACb,SAAK,MAAM,MAAM,KAAK;AAAA,MACpB,MAAM;AAAA,MACN,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,QACE,QACA,WACA,OACA,gBAA+B,OAC/B,kBAA2B,OACrB;AACN,SAAK,MAAM,MAAM,KAAK;AAAA,MACpB,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,SACE,KACA,UACA,gBAA+B,OAC/B,kBAA2B,OACrB;AACN,SAAK,MAAM,MAAM,KAAK,EAAE,MAAM,OAAO,KAAK,UAAU,eAAe,gBAAgB,CAAC;AACpF,WAAO;AAAA,EACT;AAAA,EAEA,YACE,SACA,WACA,SACA,gBAA+B,OAC/B,kBAA2B,OACrB;AACN,SAAK,MAAM,MAAM,KAAK;AAAA,MACpB,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,UACE,QACA,gBAA+B,OAC/B,kBAA2B,OACrB;AACN,SAAK,MAAM,MAAM,KAAK,EAAE,MAAM,QAAQ,QAAQ,eAAe,gBAAgB,CAAC;AAC9E,WAAO;AAAA,EACT;AAAA,EAEA,aAAmB;AACjB,SAAK,MAAM,QAAQ,CAAC;AACpB,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,SAA6B;AAClC,SAAK,MAAM,SAAS,CAAC,GAAG,OAAO;AAC/B,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,SAAyB;AAC/B,SAAK,MAAM,UAAU,CAAC,GAAG,OAAO;AAChC,WAAO;AAAA,EACT;AAAA,EAEA,SACE,QACA,WACA,OACA,gBAA+B,OAC/B,kBAA2B,OACrB;AACN,SAAK,MAAM,OAAO,KAAK;AAAA,MACrB,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,UACE,KACA,UACA,gBAA+B,OAC/B,kBAA2B,OACrB;AACN,SAAK,MAAM,OAAO,KAAK,EAAE,MAAM,OAAO,KAAK,UAAU,eAAe,gBAAgB,CAAC;AACrF,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,QAAgB,YAA4B,OAAa;AAC/D,SAAK,MAAM,QAAQ,KAAK,GAAG,MAAM,IAAI,SAAS,EAAE;AAChD,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OAAqB;AACzB,SAAK,MAAM,QAAQ;AACnB,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,QAAsB;AAC3B,SAAK,MAAM,SAAS;AACpB,WAAO;AAAA,EACT;AAAA,EAEA,QAAqB;AACnB,WAAO,KAAK,QAAQ,MAAM,IAAI;AAAA,EAChC;AAAA,EAEA,MAAM,MAAM;AACV,WAAO,MAAM,KAAK,YAAY,SAAS,KAAK,MAAM,CAAC;AAAA,EACrD;AAAA,EAEA,MAAM,QAAyB;AAC7B,UAAM,OAAoB,KAAK,QAAQ,aAAa,IAAI;AACxD,UAAM,SAAS,MAAM,KAAK,YAAY,SAAS,IAAI;AACnD,QAAI,UAAU,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,GAAG;AACxD,aAAO,SAAS,OAAO,CAAC,EAAE,OAAO,GAAG,EAAE;AAAA,IACxC;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,YAAY;AAChB,WAAO,MAAM,KAAK,YAAY,UAAU,KAAK,MAAM,CAAC;AAAA,EACtD;AAAA,EAEA,gBAAmC;AACjC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,OAAO,MAAiC;AAC5C,UAAM,OAAoB,KAAK,QAAQ,cAAc,MAAM,IAAI;AAC/D,WAAO,MAAM,KAAK,YAAY,SAAS,IAAI;AAAA,EAC7C;AAAA,EAEA,MAAM,YACJ,MACA,UAAoC,EAAE,YAAY,CAAC,IAAI,EAAE,GACzD;AACA,UAAM,OAAoB,KAAK,QAAQ,mBAAmB,MAAM,MAAM,OAAO;AAC7E,WAAO,MAAM,KAAK,YAAY,SAAS,IAAI;AAAA,EAC7C;AAAA,EAEA,MAAM,OAAO,MAAiC;AAC5C,UAAM,OAAoB,KAAK,QAAQ,cAAc,MAAM,IAAI;AAC/D,WAAO,MAAM,KAAK,YAAY,SAAS,IAAI;AAAA,EAC7C;AAAA,EAEA,MAAM,OAAO,MAAiC,eAAyB,eAAyB;AAC9F,UAAM,OAAoB,KAAK,QAAQ,cAAc,MAAM,MAAM,eAAe,aAAa;AAC7F,WAAO,MAAM,KAAK,YAAY,SAAS,IAAI;AAAA,EAC7C;AAAA,EAEA,MAAM,SAAS;AACb,UAAM,OAAoB,KAAK,QAAQ,cAAc,IAAI;AACzD,WAAO,MAAM,KAAK,YAAY,SAAS,IAAI;AAAA,EAC7C;AAAA,EAEA,KACE,OACA,MACA,YACM;AACN,QAAI,uBAAoC,CAAC;AACzC,eAAW,QAAQ,YAAY;AAC7B,2BAAqB,KAAK;AAAA,QACxB,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,MAAM;AAAA;AAAA,QAEN,WAAW;AAAA,QACX,GAAG;AAAA,MACL,CAAC;AAAA,IACH;AACA,SAAK,MAAM,KAAK,KAAK,EAAE,MAAM,OAAO,YAAY,qBAAqB,CAAC;AACtE,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,OAAe,YAAwE;AAC/F,WAAO,KAAK,KAAK,OAAO,SAAS,UAAU;AAAA,EAC7C;AAAA,EAEA,SAAS,OAAe,YAAwE;AAC9F,WAAO,KAAK,KAAK,OAAO,QAAQ,UAAU;AAAA,EAC5C;AAAA,EAEA,UAAU,OAAe,YAAwE;AAC/F,WAAO,KAAK,KAAK,OAAO,SAAS,UAAU;AAAA,EAC7C;AAAA,EAEA,SAAS,OAAe,YAAwE;AAC9F,WAAO,KAAK,KAAK,OAAO,QAAQ,UAAU;AAAA,EAC5C;AAAA,EAEA,UAAU,OAAe,YAAwE;AAC/F,WAAO,KAAK,KAAK,OAAO,SAAS,UAAU;AAAA,EAC7C;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/Query.mts"],"sourcesContent":["import { Connection } from './Connection.mjs';\nimport { QueryGrammar } from './QueryGrammar.mjs';\nimport {\n CompiledSql,\n JoinCondition,\n Parameter,\n selectType,\n whereType,\n havingType,\n joinType,\n} from './types.mjs';\n\nexport type QueryParts = {\n select: selectType[];\n table: string;\n join: joinType[];\n where: whereType[];\n groupBy: string[];\n having: havingType[];\n orderBy: string[];\n limit: number | null;\n offset: number | null;\n alias: string | null;\n};\n\nexport class Query {\n allowedOperations: string[] = ['=', '>', '<', '!=', 'like', 'ilike', 'in'];\n parts: QueryParts = {\n select: ['*'],\n table: '',\n join: [],\n where: [],\n groupBy: [],\n having: [],\n orderBy: [],\n limit: null,\n offset: null,\n alias: null,\n };\n\n constructor(\n public readonly connection: Connection | null,\n public readonly grammar: QueryGrammar\n ) {}\n\n table(tableName: string): this {\n this.parts.table = tableName;\n return this;\n }\n\n whereNested(\n func: (q: Query) => void,\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ) {\n const subQuery = new Query(this.connection, this.grammar);\n func(subQuery);\n this.parts.where.push({\n type: 'nested',\n query: subQuery,\n joinCondition,\n negateCondition,\n });\n return this;\n }\n\n whereOp(\n column: string,\n operation: (typeof this.allowedOperations)[number],\n value: Parameter,\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ): this {\n this.parts.where.push({\n type: 'operation',\n column,\n operation,\n value,\n joinCondition,\n negateCondition,\n });\n return this;\n }\n\n whereRaw(\n sql: string,\n bindings: Parameter[],\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ): this {\n this.parts.where.push({ type: 'raw', sql, bindings, joinCondition, negateCondition });\n return this;\n }\n\n whereColumn(\n column1: string,\n operation: (typeof this.allowedOperations)[number],\n column2: string,\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ): this {\n this.parts.where.push({\n type: 'operationColumn',\n column1,\n operation,\n column2,\n joinCondition,\n negateCondition,\n });\n return this;\n }\n\n whereNull(\n column: string,\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ): this {\n this.parts.where.push({ type: 'null', column, joinCondition, negateCondition });\n return this;\n }\n\n clearWhere(): this {\n this.parts.where = [];\n return this;\n }\n\n select(selects: selectType[]): this {\n this.parts.select = [...selects];\n return this;\n }\n\n groupBy(columns: string[]): this {\n this.parts.groupBy = [...columns];\n return this;\n }\n\n havingOp(\n column: string,\n operation: (typeof this.allowedOperations)[number],\n value: Parameter,\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ): this {\n this.parts.having.push({\n type: 'operation',\n column,\n operation,\n value,\n joinCondition,\n negateCondition,\n });\n return this;\n }\n\n havingRaw(\n sql: string,\n bindings: Parameter[],\n joinCondition: JoinCondition = 'and',\n negateCondition: boolean = false\n ): this {\n this.parts.having.push({ type: 'raw', sql, bindings, joinCondition, negateCondition });\n return this;\n }\n\n orderBy(column: string, direction: 'asc' | 'desc' = 'asc'): this {\n this.parts.orderBy.push(`${column} ${direction}`);\n return this;\n }\n\n limit(limit: number): this {\n this.parts.limit = limit;\n return this;\n }\n\n offset(offset: number): this {\n this.parts.offset = offset;\n return this;\n }\n\n toSql(): CompiledSql {\n return this.grammar.toSql(this);\n }\n\n async get() {\n let sql = this.toSql();\n return await this.connection?.runQuery(sql);\n }\n\n async first() {\n let rc = await this.connection?.runQuery(this.toSql());\n if (rc && Array.isArray(rc) && rc.length > 0) {\n return rc[0];\n }\n return undefined;\n }\n\n async count(): Promise<number> {\n const csql: CompiledSql = this.grammar.compileCount(this);\n const result = await this.connection?.runQuery(csql);\n if (result && Array.isArray(result) && result.length > 0) {\n return parseInt(result[0]['count'], 10);\n }\n return 0;\n }\n\n async getCursor() {\n return await this.connection?.runCursor(this.toSql());\n }\n\n getConnection(): Connection | null {\n return this.connection;\n }\n\n async insert(data: Record<string, Parameter>) {\n const csql: CompiledSql = this.grammar.compileInsert(this, data);\n return await this.connection?.runQuery(csql);\n }\n\n async insertGetId(\n data: Record<string, Parameter>,\n options: { primaryKey: string[] } = { primaryKey: ['id'] }\n ) {\n const csql: CompiledSql = this.grammar.compileInsertGetId(this, data, options);\n return await this.connection?.runQuery(csql);\n }\n\n async update(data: Record<string, Parameter>) {\n const csql: CompiledSql = this.grammar.compileUpdate(this, data);\n return await this.connection?.runQuery(csql);\n }\n\n async upsert(data: Record<string, Parameter>, uniqueColumns: string[], updateColumns: string[]) {\n const csql: CompiledSql = this.grammar.compileUpsert(this, data, uniqueColumns, updateColumns);\n return await this.connection?.runQuery(csql);\n }\n\n async delete() {\n const csql: CompiledSql = this.grammar.compileDelete(this);\n return await this.connection?.runQuery(csql);\n }\n\n join(\n table: string | Query,\n type: joinType['type'],\n conditions: (whereType | { column1: string; column2: string })[]\n ): this {\n let conditions_corrected: whereType[] = [];\n for (const cond of conditions) {\n conditions_corrected.push({\n joinCondition: 'and',\n negateCondition: false,\n type: 'operationColumn',\n // @ts-ignore\n operation: '=',\n ...cond,\n });\n }\n this.parts.join.push({ type, table, conditions: conditions_corrected });\n return this;\n }\n\n innerJoin(\n table: Parameters<typeof this.join>[0],\n conditions: (whereType | { column1: string; column2: string })[]\n ): this {\n return this.join(table, 'inner', conditions);\n }\n\n leftJoin(\n table: Parameters<typeof this.join>[0],\n conditions: (whereType | { column1: string; column2: string })[]\n ): this {\n return this.join(table, 'left', conditions);\n }\n\n rightJoin(\n table: Parameters<typeof this.join>[0],\n conditions: (whereType | { column1: string; column2: string })[]\n ): this {\n return this.join(table, 'right', conditions);\n }\n\n fullJoin(\n table: Parameters<typeof this.join>[0],\n conditions: (whereType | { column1: string; column2: string })[]\n ): this {\n return this.join(table, 'full', conditions);\n }\n\n crossJoin(\n table: Parameters<typeof this.join>[0],\n conditions: (whereType | { column1: string; column2: string })[]\n ): this {\n return this.join(table, 'cross', conditions);\n }\n\n alias(alias: string): this {\n this.parts.alias = alias;\n return this;\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- export { d as QueryGrammar } from './Blueprint-mmlqFfF6.mjs';
1
+ export { d as QueryGrammar } from './Blueprint-DiSVtLdl.mjs';
@@ -1,5 +1,6 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+ import { sqlTokenizer } from "sql-tokenizer";
3
4
  function toUpperFirst(str) {
4
5
  return str.substring(0, 1).toUpperCase() + str.substring(1);
5
6
  }
@@ -20,79 +21,118 @@ class QueryGrammar {
20
21
  "offset"
21
22
  ];
22
23
  toSql(query) {
23
- let sql = "";
24
+ let rc = this.toSqlParts(query);
25
+ rc.sql = this.joinArray(rc.parts);
26
+ return rc;
27
+ }
28
+ toSqlParts(query) {
29
+ let parts = [];
24
30
  let bindings = [];
25
31
  for (const part of this.sqlParts) {
26
32
  const funcName = "compile" + toUpperFirst(part);
27
33
  const r = this[funcName](query.parts[part]);
28
- if (!sql) {
29
- sql = r.sql;
30
- } else if (r.sql) {
31
- sql += " " + r.sql;
32
- }
33
34
  bindings = [...bindings, ...r.bindings];
35
+ parts = [...parts, ...r.parts];
34
36
  }
35
- return { sql, bindings };
37
+ return {
38
+ sql: "",
39
+ bindings,
40
+ parts
41
+ };
36
42
  }
37
43
  compileCount(query) {
38
44
  let sql = "";
39
45
  let bindings = [];
46
+ let parts = [];
40
47
  for (const part of this.sqlParts) {
41
- let parts = query.parts[part];
48
+ let parts2 = query.parts[part];
42
49
  if (part === "select") {
43
- parts = ["count(*) as count"];
50
+ parts2 = ["count(*) as count"];
44
51
  }
45
52
  const funcName = "compile" + toUpperFirst(part);
46
- const r = this[funcName](parts);
47
- if (!sql) {
48
- sql = r.sql;
49
- } else if (r.sql) {
50
- sql += " " + r.sql;
51
- }
53
+ const r = this[funcName](parts2);
52
54
  bindings = [...bindings, ...r.bindings];
55
+ parts = [...parts, ...r.parts];
53
56
  }
54
- return { sql, bindings };
57
+ return { sql, parts, bindings };
55
58
  }
56
59
  compileSelect(selects) {
57
- const rc = selects.map((v) => {
58
- return v;
59
- }).join(", ");
60
- return { sql: "select " + rc, bindings: [] };
60
+ const parts = ["select"];
61
+ selects.map((v) => {
62
+ parts.push(v);
63
+ parts.push(",");
64
+ });
65
+ parts.pop();
66
+ return { sql: this.joinArray(parts), parts, bindings: [] };
61
67
  }
62
- compileTable(tableName) {
68
+ joinArray(arr) {
63
69
  let rc = "";
70
+ let last = "";
71
+ for (const a of arr) {
72
+ if (a === ",") {
73
+ rc += a;
74
+ } else if (last === "(" || last === " " || a === ")") {
75
+ rc += a;
76
+ } else if (a === "") {
77
+ rc += "";
78
+ } else {
79
+ rc += " " + a;
80
+ }
81
+ last = a;
82
+ }
83
+ return rc.trim();
84
+ }
85
+ compileTable(tableName) {
86
+ let parts = [];
64
87
  if (tableName.length) {
65
- rc = "from " + tableName;
88
+ parts.push("from");
89
+ parts.push(tableName);
66
90
  }
67
- return { sql: rc, bindings: [] };
91
+ return { sql: parts.join(" "), parts, bindings: [] };
68
92
  }
69
93
  compileJoin(joins) {
70
94
  let sql = "";
71
95
  let bindings = [];
96
+ let parts = [];
72
97
  for (const j of joins) {
73
- sql += " " + j.type + " join " + j.table + " on ";
74
- const where = this.compileWhere(j.conditions);
75
- if (where.sql.startsWith("where ")) {
76
- where.sql = where.sql.substring("where ".length);
98
+ let table = "";
99
+ let table_bindings = [];
100
+ parts.push(j.type);
101
+ parts.push("join");
102
+ if (typeof j.table === "string") {
103
+ parts.push(j.table);
104
+ } else {
105
+ const subQuery = j.table;
106
+ const { parts: parts2, bindings: bindings2 } = subQuery.toSql();
107
+ parts = [...parts, "(", ...parts2, ")", "as", subQuery.parts.alias || "subquery"];
108
+ table_bindings = bindings2;
77
109
  }
78
- sql += "(";
79
- sql += where.sql;
80
- sql += ")";
81
- bindings = [...bindings, ...where.bindings];
110
+ parts.push("on");
111
+ const where = this.compileWhere(j.conditions);
112
+ const where_parts = where.parts;
113
+ where_parts.shift();
114
+ parts.push("(");
115
+ parts = [...parts, ...where_parts];
116
+ parts.push(")");
117
+ bindings = [...bindings, ...table_bindings, ...where.bindings];
82
118
  }
83
- return { sql, bindings };
119
+ return { sql, parts, bindings };
84
120
  }
85
121
  compileWhere(wheres) {
86
122
  let sql = "";
87
123
  let bindings = [];
124
+ let parts = [];
88
125
  for (const w of wheres) {
89
126
  sql += " " + w.joinCondition + " ";
127
+ parts.push(w.joinCondition);
90
128
  if (w.negateCondition) {
91
129
  sql += "not ";
130
+ parts.push("not");
92
131
  }
93
132
  const funcName = "compileWhere" + toUpperFirst(w.type);
94
133
  const wh = this[funcName](w);
95
134
  sql += wh.sql;
135
+ parts = parts.concat(wh.parts);
96
136
  bindings = [...bindings, ...wh.bindings];
97
137
  }
98
138
  if (sql.startsWith(" and ")) {
@@ -100,159 +140,197 @@ class QueryGrammar {
100
140
  } else if (sql.startsWith(" or ")) {
101
141
  sql = "where " + sql.substring(" or ".length);
102
142
  }
103
- return { sql, bindings };
143
+ if (parts.length > 0) {
144
+ parts[0] = "where";
145
+ }
146
+ return { sql, parts, bindings };
104
147
  }
105
148
  compileWhereNested(w) {
106
149
  const subQuery = w.query;
107
- const { sql, bindings } = subQuery.grammar.compileWhere(subQuery.parts.where);
150
+ let parts = [];
151
+ const { sql, parts: parts2, bindings } = subQuery.grammar.compileWhere(subQuery.parts.where);
108
152
  let sql2 = sql.replace(/^where /, "");
153
+ parts2.shift();
154
+ parts.push("(");
155
+ parts = parts.concat(parts2);
156
+ parts.push(")");
109
157
  return {
110
158
  sql: `(${sql2})`,
159
+ parts,
111
160
  bindings
112
161
  };
113
162
  }
114
163
  compileWhereOperation(w) {
115
164
  if (w.operation.toLowerCase() === "in" && Array.isArray(w.value)) {
116
165
  return {
117
- sql: `${w.column} = ANY(${this.getVariablePlaceholder()})`,
166
+ sql: `${w.column} = ANY( ? )`,
167
+ parts: [w.column, " = ANY(", "?", ")"],
118
168
  bindings: [w.value]
119
169
  };
120
170
  }
121
171
  return {
122
- sql: `${w.column} ${w.operation} ${this.getVariablePlaceholder()}`,
172
+ sql: `${w.column} ${w.operation} ?`,
173
+ parts: [w.column, w.operation, "?"],
123
174
  bindings: [w.value]
124
175
  };
125
176
  }
126
177
  compileWhereOperationColumn(w) {
127
178
  return {
128
179
  sql: `${w.column1} ${w.operation} ${w.column2}`,
180
+ parts: [w.column1, w.operation, w.column2],
129
181
  bindings: []
130
182
  };
131
183
  }
132
184
  compileWhereRaw(w) {
185
+ const tokenize = sqlTokenizer();
133
186
  return {
134
187
  sql: w.sql,
188
+ parts: tokenize(w.sql).filter((t) => t !== " "),
135
189
  bindings: w.bindings
136
190
  };
137
191
  }
138
192
  compileOrderBy(orderBy) {
139
193
  let rc = "";
194
+ let parts = [];
140
195
  if (orderBy.length) {
141
196
  rc = "order by " + orderBy.join(", ");
197
+ parts.push("order by");
198
+ parts = parts.concat(orderBy);
142
199
  }
143
- return { sql: rc, bindings: [] };
200
+ return { sql: rc, parts, bindings: [] };
144
201
  }
145
202
  compileLimit(limit) {
146
203
  let rc = "";
204
+ let parts = [];
147
205
  if (limit !== null) {
148
206
  rc = "limit " + limit;
207
+ parts.push("limit");
208
+ parts.push(limit);
149
209
  }
150
- return { sql: rc, bindings: [] };
210
+ return { sql: rc, parts, bindings: [] };
151
211
  }
152
212
  compileOffset(offset) {
153
213
  let rc = "";
214
+ let parts = [];
154
215
  if (offset !== null) {
155
216
  rc = "offset " + offset;
217
+ parts.push("offset");
218
+ parts.push(offset);
156
219
  }
157
- return { sql: rc, bindings: [] };
220
+ return { sql: rc, parts, bindings: [] };
158
221
  }
159
222
  compileWhereNull(w) {
160
223
  return {
161
224
  sql: `${w.column} is null`,
225
+ parts: [w.column, "is", "null"],
162
226
  bindings: []
163
227
  };
164
228
  }
165
229
  compileInsert(query, data) {
166
- let sql = "insert into " + query.parts.table + " (";
230
+ let parts = ["insert", "into", query.parts.table, "("];
167
231
  const columns = [];
168
232
  const bindings = [];
169
233
  const values = [];
170
234
  for (const [k, v] of Object.entries(data)) {
171
- columns.push(k);
235
+ parts.push(k);
236
+ parts.push(",");
237
+ }
238
+ parts.pop();
239
+ parts = parts.concat([")", "values", "("]);
240
+ for (const [k, v] of Object.entries(data)) {
241
+ parts.push("?");
172
242
  bindings.push(v);
173
- values.push(this.getVariablePlaceholder());
243
+ parts.push(",");
174
244
  }
175
- sql += columns.join(", ") + ") values (" + values + ")";
176
- return { sql, bindings };
245
+ parts.pop();
246
+ parts.push(")");
247
+ return { sql: parts.join(" "), parts, bindings };
177
248
  }
178
249
  compileUpdate(query, data) {
179
- let sql = "update " + query.parts.table + " set ";
180
250
  const bindings = [];
251
+ let parts = ["update", query.parts.table, "set"];
181
252
  const setParts = [];
182
253
  for (const [k, v] of Object.entries(data)) {
183
- setParts.push(`${k} = ${this.getVariablePlaceholder()}`);
254
+ parts = parts.concat([k, "=", "?", ","]);
255
+ setParts.push(`${k} = ?`);
184
256
  bindings.push(v);
185
257
  }
186
- sql += setParts.join(", ");
258
+ parts.pop();
187
259
  const where_csql = this.compileWhere(query.parts.where);
188
- sql += " " + where_csql.sql;
260
+ parts = parts.concat(where_csql.parts);
189
261
  bindings.push(...where_csql.bindings);
190
- return { sql, bindings };
262
+ return { sql: parts.join(" "), parts, bindings };
191
263
  }
192
264
  compileDelete(query) {
193
265
  let sql = "delete from " + query.parts.table;
266
+ let parts = ["delete", "from", query.parts.table];
194
267
  const where_csql = this.compileWhere(query.parts.where);
195
268
  sql += " " + where_csql.sql;
196
- return { sql, bindings: where_csql.bindings };
269
+ parts = parts.concat(where_csql.parts);
270
+ return { sql, parts, bindings: where_csql.bindings };
197
271
  }
198
272
  compileUpsert(query, data, conflictFields, updateFields) {
199
- let sql = "insert into " + query.parts.table + " (";
200
- const columns = [];
273
+ let parts = [];
201
274
  const bindings = [];
202
- const values = [];
203
- for (const [k, v] of Object.entries(data)) {
204
- columns.push(k);
205
- bindings.push(v);
206
- values.push(this.getVariablePlaceholder());
207
- }
208
- sql += columns.join(", ") + ") values (" + values + ")";
209
- sql += " on conflict (" + conflictFields.join(", ") + ") do update set ";
275
+ let isql = this.compileInsert(query, data);
276
+ parts = isql.parts;
277
+ bindings.push(...isql.bindings);
278
+ parts = parts.concat(["on", "conflict", "(", ...conflictFields, ")", "do", "update", "set"]);
210
279
  const setParts = [];
211
280
  for (const f of updateFields) {
212
281
  setParts.push(`${f} = excluded.${f}`);
282
+ setParts.push(`,`);
213
283
  }
214
- sql += setParts.join(", ");
284
+ setParts.pop();
285
+ parts = parts.concat(setParts);
215
286
  const where_csql = this.compileWhere(query.parts.where);
216
- sql += " " + where_csql.sql;
287
+ parts = parts.concat(where_csql.parts);
217
288
  bindings.push(...where_csql.bindings);
218
- return { sql, bindings };
289
+ return { sql: parts.join(" "), parts, bindings };
219
290
  }
220
291
  compileGroupBy(groupBy) {
221
292
  let rc = "";
293
+ let parts = [];
222
294
  if (groupBy.length) {
223
295
  rc = "group by " + groupBy.join(", ");
296
+ parts.push("group by");
297
+ parts = parts.concat(groupBy);
224
298
  }
225
- return { sql: rc, bindings: [] };
299
+ return { sql: rc, parts, bindings: [] };
226
300
  }
227
301
  compileHaving(having) {
228
302
  let sql = "";
229
303
  let bindings = [];
304
+ let parts = [];
230
305
  for (const w of having) {
231
306
  sql += " " + w.joinCondition + " ";
307
+ parts.push(w.joinCondition);
232
308
  if (w.negateCondition) {
233
309
  sql += "not ";
310
+ parts.push("not");
234
311
  }
235
312
  const funcName = "compileHaving" + toUpperFirst(w.type);
236
313
  const wh = this[funcName](w);
314
+ parts = parts.concat(wh.parts);
237
315
  sql += wh.sql;
238
316
  bindings = [...bindings, ...wh.bindings];
239
317
  }
240
- if (sql.startsWith(" and ")) {
241
- sql = "having " + sql.substring(" and ".length);
242
- } else if (sql.startsWith(" or ")) {
243
- sql = "having " + sql.substring(" or ".length);
318
+ if (parts.length > 0) {
319
+ parts[0] = "having";
244
320
  }
245
- return { sql, bindings };
321
+ return { sql: parts.join(" "), parts, bindings };
246
322
  }
247
323
  compileHavingOperation(w) {
248
324
  return {
249
- sql: `${w.column} ${w.operation} ${this.getVariablePlaceholder()}`,
325
+ sql: `${w.column} ${w.operation} ?`,
326
+ parts: [w.column, w.operation, "?"],
250
327
  bindings: [w.value]
251
328
  };
252
329
  }
253
330
  compileHavingRaw(w) {
254
331
  return {
255
332
  sql: w.sql,
333
+ parts: w.sql.split(" "),
256
334
  bindings: w.bindings
257
335
  };
258
336
  }