@devbro/neko-sql 0.1.16 → 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":"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","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,160 +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) {
133
- let sql = w.sql.replace(/\?/g, () => this.getVariablePlaceholder());
185
+ const tokenize = sqlTokenizer();
134
186
  return {
135
- sql,
187
+ sql: w.sql,
188
+ parts: tokenize(w.sql).filter((t) => t !== " "),
136
189
  bindings: w.bindings
137
190
  };
138
191
  }
139
192
  compileOrderBy(orderBy) {
140
193
  let rc = "";
194
+ let parts = [];
141
195
  if (orderBy.length) {
142
196
  rc = "order by " + orderBy.join(", ");
197
+ parts.push("order by");
198
+ parts = parts.concat(orderBy);
143
199
  }
144
- return { sql: rc, bindings: [] };
200
+ return { sql: rc, parts, bindings: [] };
145
201
  }
146
202
  compileLimit(limit) {
147
203
  let rc = "";
204
+ let parts = [];
148
205
  if (limit !== null) {
149
206
  rc = "limit " + limit;
207
+ parts.push("limit");
208
+ parts.push(limit);
150
209
  }
151
- return { sql: rc, bindings: [] };
210
+ return { sql: rc, parts, bindings: [] };
152
211
  }
153
212
  compileOffset(offset) {
154
213
  let rc = "";
214
+ let parts = [];
155
215
  if (offset !== null) {
156
216
  rc = "offset " + offset;
217
+ parts.push("offset");
218
+ parts.push(offset);
157
219
  }
158
- return { sql: rc, bindings: [] };
220
+ return { sql: rc, parts, bindings: [] };
159
221
  }
160
222
  compileWhereNull(w) {
161
223
  return {
162
224
  sql: `${w.column} is null`,
225
+ parts: [w.column, "is", "null"],
163
226
  bindings: []
164
227
  };
165
228
  }
166
229
  compileInsert(query, data) {
167
- let sql = "insert into " + query.parts.table + " (";
230
+ let parts = ["insert", "into", query.parts.table, "("];
168
231
  const columns = [];
169
232
  const bindings = [];
170
233
  const values = [];
171
234
  for (const [k, v] of Object.entries(data)) {
172
- 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("?");
173
242
  bindings.push(v);
174
- values.push(this.getVariablePlaceholder());
243
+ parts.push(",");
175
244
  }
176
- sql += columns.join(", ") + ") values (" + values + ")";
177
- return { sql, bindings };
245
+ parts.pop();
246
+ parts.push(")");
247
+ return { sql: parts.join(" "), parts, bindings };
178
248
  }
179
249
  compileUpdate(query, data) {
180
- let sql = "update " + query.parts.table + " set ";
181
250
  const bindings = [];
251
+ let parts = ["update", query.parts.table, "set"];
182
252
  const setParts = [];
183
253
  for (const [k, v] of Object.entries(data)) {
184
- setParts.push(`${k} = ${this.getVariablePlaceholder()}`);
254
+ parts = parts.concat([k, "=", "?", ","]);
255
+ setParts.push(`${k} = ?`);
185
256
  bindings.push(v);
186
257
  }
187
- sql += setParts.join(", ");
258
+ parts.pop();
188
259
  const where_csql = this.compileWhere(query.parts.where);
189
- sql += " " + where_csql.sql;
260
+ parts = parts.concat(where_csql.parts);
190
261
  bindings.push(...where_csql.bindings);
191
- return { sql, bindings };
262
+ return { sql: parts.join(" "), parts, bindings };
192
263
  }
193
264
  compileDelete(query) {
194
265
  let sql = "delete from " + query.parts.table;
266
+ let parts = ["delete", "from", query.parts.table];
195
267
  const where_csql = this.compileWhere(query.parts.where);
196
268
  sql += " " + where_csql.sql;
197
- return { sql, bindings: where_csql.bindings };
269
+ parts = parts.concat(where_csql.parts);
270
+ return { sql, parts, bindings: where_csql.bindings };
198
271
  }
199
272
  compileUpsert(query, data, conflictFields, updateFields) {
200
- let sql = "insert into " + query.parts.table + " (";
201
- const columns = [];
273
+ let parts = [];
202
274
  const bindings = [];
203
- const values = [];
204
- for (const [k, v] of Object.entries(data)) {
205
- columns.push(k);
206
- bindings.push(v);
207
- values.push(this.getVariablePlaceholder());
208
- }
209
- sql += columns.join(", ") + ") values (" + values + ")";
210
- 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"]);
211
279
  const setParts = [];
212
280
  for (const f of updateFields) {
213
281
  setParts.push(`${f} = excluded.${f}`);
282
+ setParts.push(`,`);
214
283
  }
215
- sql += setParts.join(", ");
284
+ setParts.pop();
285
+ parts = parts.concat(setParts);
216
286
  const where_csql = this.compileWhere(query.parts.where);
217
- sql += " " + where_csql.sql;
287
+ parts = parts.concat(where_csql.parts);
218
288
  bindings.push(...where_csql.bindings);
219
- return { sql, bindings };
289
+ return { sql: parts.join(" "), parts, bindings };
220
290
  }
221
291
  compileGroupBy(groupBy) {
222
292
  let rc = "";
293
+ let parts = [];
223
294
  if (groupBy.length) {
224
295
  rc = "group by " + groupBy.join(", ");
296
+ parts.push("group by");
297
+ parts = parts.concat(groupBy);
225
298
  }
226
- return { sql: rc, bindings: [] };
299
+ return { sql: rc, parts, bindings: [] };
227
300
  }
228
301
  compileHaving(having) {
229
302
  let sql = "";
230
303
  let bindings = [];
304
+ let parts = [];
231
305
  for (const w of having) {
232
306
  sql += " " + w.joinCondition + " ";
307
+ parts.push(w.joinCondition);
233
308
  if (w.negateCondition) {
234
309
  sql += "not ";
310
+ parts.push("not");
235
311
  }
236
312
  const funcName = "compileHaving" + toUpperFirst(w.type);
237
313
  const wh = this[funcName](w);
314
+ parts = parts.concat(wh.parts);
238
315
  sql += wh.sql;
239
316
  bindings = [...bindings, ...wh.bindings];
240
317
  }
241
- if (sql.startsWith(" and ")) {
242
- sql = "having " + sql.substring(" and ".length);
243
- } else if (sql.startsWith(" or ")) {
244
- sql = "having " + sql.substring(" or ".length);
318
+ if (parts.length > 0) {
319
+ parts[0] = "having";
245
320
  }
246
- return { sql, bindings };
321
+ return { sql: parts.join(" "), parts, bindings };
247
322
  }
248
323
  compileHavingOperation(w) {
249
324
  return {
250
- sql: `${w.column} ${w.operation} ${this.getVariablePlaceholder()}`,
325
+ sql: `${w.column} ${w.operation} ?`,
326
+ parts: [w.column, w.operation, "?"],
251
327
  bindings: [w.value]
252
328
  };
253
329
  }
254
330
  compileHavingRaw(w) {
255
331
  return {
256
332
  sql: w.sql,
333
+ parts: w.sql.split(" "),
257
334
  bindings: w.bindings
258
335
  };
259
336
  }