xcraft-core-pickaxe 0.1.29 → 0.1.30
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/lib/operator-to-sql.js +11 -0
- package/lib/operators.js +14 -0
- package/lib/picks.js +16 -0
- package/lib/query-builder.js +30 -9
- package/lib/query-to-sql.js +8 -3
- package/package.json +1 -1
package/lib/operator-to-sql.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const {isAnyPick, BasePick} = require('./picks.js');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
+
* @typedef {import("./query-builder.js").DbTable} DbTable
|
|
6
7
|
* @typedef {import("./operators.js").Expression} Expression
|
|
7
8
|
*/
|
|
8
9
|
|
|
@@ -103,6 +104,14 @@ const operators = {
|
|
|
103
104
|
return `LENGTH(${sql(value, context)})`;
|
|
104
105
|
},
|
|
105
106
|
|
|
107
|
+
lower({value}, context) {
|
|
108
|
+
return `LOWER(${sql(value, context)})`;
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
upper({value}, context) {
|
|
112
|
+
return `UPPER(${sql(value, context)})`;
|
|
113
|
+
},
|
|
114
|
+
|
|
106
115
|
substr({value, start, length}, context) {
|
|
107
116
|
const valueSql = sql(value, context);
|
|
108
117
|
const startSql = sql(start, context);
|
|
@@ -343,6 +352,7 @@ function getExpression(expressionOrPick) {
|
|
|
343
352
|
/**
|
|
344
353
|
* @typedef {{
|
|
345
354
|
* values: any[] | null,
|
|
355
|
+
* tablesUsed: DbTable[],
|
|
346
356
|
* scope?: any,
|
|
347
357
|
* useTableNames?: boolean,
|
|
348
358
|
* equalOperator: 'IS' | '=',
|
|
@@ -366,6 +376,7 @@ function sql(expressionOrPick, context) {
|
|
|
366
376
|
function expressionToSql(operator) {
|
|
367
377
|
const context = {
|
|
368
378
|
values: [],
|
|
379
|
+
tablesUsed: [],
|
|
369
380
|
};
|
|
370
381
|
return {
|
|
371
382
|
sql: sql(operator, context),
|
package/lib/operators.js
CHANGED
|
@@ -90,6 +90,20 @@ const operators = {
|
|
|
90
90
|
});
|
|
91
91
|
},
|
|
92
92
|
|
|
93
|
+
lower(value) {
|
|
94
|
+
return /** @type {const} */ ({
|
|
95
|
+
operator: 'lower',
|
|
96
|
+
value: op(value),
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
upper(value) {
|
|
101
|
+
return /** @type {const} */ ({
|
|
102
|
+
operator: 'upper',
|
|
103
|
+
value: op(value),
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
|
|
93
107
|
substr(value, start, length) {
|
|
94
108
|
value = op(value);
|
|
95
109
|
start = op(start);
|
package/lib/picks.js
CHANGED
|
@@ -86,6 +86,14 @@ class ValuePick extends BasePick {
|
|
|
86
86
|
super(type, expression);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* @template {AnyTypeOrShape} T
|
|
91
|
+
* @param {T} type
|
|
92
|
+
*/
|
|
93
|
+
as(type) {
|
|
94
|
+
return makePick(type, this.expression);
|
|
95
|
+
}
|
|
96
|
+
|
|
89
97
|
/**
|
|
90
98
|
* @template {AnyObjectShape} T
|
|
91
99
|
* @param {T} shape
|
|
@@ -179,6 +187,14 @@ class StringPick extends ValuePick {
|
|
|
179
187
|
return new NumberPick(number, $o.stringLength(this.expression));
|
|
180
188
|
}
|
|
181
189
|
|
|
190
|
+
lower() {
|
|
191
|
+
return new StringPick(this.type, $o.lower(this.expression));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
upper() {
|
|
195
|
+
return new StringPick(this.type, $o.upper(this.expression));
|
|
196
|
+
}
|
|
197
|
+
|
|
182
198
|
/**
|
|
183
199
|
* @param {number | BasePick<NumberType>} start
|
|
184
200
|
* @param {number | BasePick<NumberType>} [length]
|
package/lib/query-builder.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
+
const path = require('node:path');
|
|
3
4
|
const {
|
|
4
5
|
ObjectType,
|
|
5
6
|
ArrayType,
|
|
@@ -43,11 +44,15 @@ const partialObjectShape = require('./partial-object-shape.js');
|
|
|
43
44
|
*/
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
|
-
* @typedef {{db?: string,
|
|
47
|
+
* @typedef {{db?: string, dbId?: string, table: string, alias?: string}} DbTable
|
|
47
48
|
*/
|
|
48
49
|
|
|
49
50
|
/**
|
|
50
|
-
* @typedef {
|
|
51
|
+
* @typedef {{db?: undefined, dbId?: undefined, table: Subquery, alias?: string}} SubqueryAndAlias
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @typedef {string | Subquery | DbTable | SubqueryAndAlias} QueryTable
|
|
51
56
|
*/
|
|
52
57
|
|
|
53
58
|
/**
|
|
@@ -55,6 +60,7 @@ const partialObjectShape = require('./partial-object-shape.js');
|
|
|
55
60
|
* @template {AnyObjectShape} U
|
|
56
61
|
* @typedef {{
|
|
57
62
|
* db?: string,
|
|
63
|
+
* dbId?: string,
|
|
58
64
|
* table: string,
|
|
59
65
|
* alias?: string,
|
|
60
66
|
* shape?: T,
|
|
@@ -281,9 +287,15 @@ function getTableName(table) {
|
|
|
281
287
|
* @template {AnyObjectShape} T
|
|
282
288
|
* @param {AnyTableSchema} tableSchema
|
|
283
289
|
* @param {T} shape
|
|
284
|
-
* @returns {{pick: RowPick<GetShape<T>>, condition: BooleanPick | null}}
|
|
290
|
+
* @returns {{table: DbTable, pick: RowPick<GetShape<T>>, condition: BooleanPick | null}}
|
|
285
291
|
*/
|
|
286
292
|
function useTableSchema(tableSchema, shape) {
|
|
293
|
+
const table = {
|
|
294
|
+
db: tableSchema.db,
|
|
295
|
+
dbId: tableSchema.dbId,
|
|
296
|
+
table: tableSchema.table,
|
|
297
|
+
alias: tableSchema.alias,
|
|
298
|
+
};
|
|
287
299
|
const type = toObjectType(shape);
|
|
288
300
|
const tableName = getTableName(tableSchema);
|
|
289
301
|
let pick = rowPick(type, tableName);
|
|
@@ -295,7 +307,7 @@ function useTableSchema(tableSchema, shape) {
|
|
|
295
307
|
}
|
|
296
308
|
pick = tableSchema.scope(basePick).toRowPick();
|
|
297
309
|
}
|
|
298
|
-
return {pick, condition};
|
|
310
|
+
return {table, pick, condition};
|
|
299
311
|
}
|
|
300
312
|
|
|
301
313
|
/**
|
|
@@ -456,6 +468,15 @@ class FinalQuery {
|
|
|
456
468
|
return queryToSql(this.#queryParts, null).sql;
|
|
457
469
|
}
|
|
458
470
|
|
|
471
|
+
json() {
|
|
472
|
+
const {sql, values, tables} = queryToSql(this.#queryParts);
|
|
473
|
+
return {sql, values, tables};
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
getMapRow() {
|
|
477
|
+
return this.#getMapRow();
|
|
478
|
+
}
|
|
479
|
+
|
|
459
480
|
/**
|
|
460
481
|
* @returns {R | undefined}
|
|
461
482
|
*/
|
|
@@ -693,14 +714,14 @@ class FromQuery {
|
|
|
693
714
|
*/
|
|
694
715
|
_join(joinOperator, tableName, shape, joinFct, mergePicks) {
|
|
695
716
|
const tableSchema = this.#getTableSchema(tableName, shape);
|
|
696
|
-
const {pick, condition} = useTableSchema(tableSchema, shape);
|
|
717
|
+
const {table, pick, condition} = useTableSchema(tableSchema, shape);
|
|
697
718
|
|
|
698
719
|
const joinCondition = joinFct(...this.#picks, pick, pickOperators);
|
|
699
720
|
const queryParts = {
|
|
700
721
|
...this.#queryParts,
|
|
701
722
|
joins: mergeJoin(this.#queryParts.joins, {
|
|
702
723
|
operator: joinOperator,
|
|
703
|
-
table
|
|
724
|
+
table,
|
|
704
725
|
constraint: condition
|
|
705
726
|
? pickOperators.and(condition, joinCondition)
|
|
706
727
|
: joinCondition,
|
|
@@ -945,12 +966,11 @@ class QueryBuilder {
|
|
|
945
966
|
*/
|
|
946
967
|
from(tableName, shape) {
|
|
947
968
|
const tableSchema = this.#getTableSchema(tableName, shape);
|
|
948
|
-
const
|
|
969
|
+
const {table, pick, condition} = useTableSchema(tableSchema, shape);
|
|
949
970
|
const queryParts = {
|
|
950
|
-
from,
|
|
971
|
+
from: table,
|
|
951
972
|
withs: this.#withs,
|
|
952
973
|
};
|
|
953
|
-
const {pick, condition} = useTableSchema(tableSchema, shape);
|
|
954
974
|
if (condition) {
|
|
955
975
|
queryParts.where = condition;
|
|
956
976
|
}
|
|
@@ -966,4 +986,5 @@ class QueryBuilder {
|
|
|
966
986
|
module.exports = {
|
|
967
987
|
QueryBuilder,
|
|
968
988
|
FromQuery,
|
|
989
|
+
FinalQuery,
|
|
969
990
|
};
|
package/lib/query-to-sql.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
/**
|
|
3
|
+
* @typedef {import("./query-builder.js").DbTable} DbTable
|
|
3
4
|
* @typedef {import("./query-builder.js").QueryObj} QueryObj
|
|
4
5
|
* @typedef {import("./operator-to-sql.js").ExpressionToSqlContext} ExpressionToSqlContext
|
|
5
6
|
*/
|
|
@@ -21,7 +22,8 @@ function withSql(withs, context) {
|
|
|
21
22
|
.map(({name, query}) => {
|
|
22
23
|
let sql = '';
|
|
23
24
|
sql += `${name} AS (\n`;
|
|
24
|
-
sql += queryToSql(query, context.values)
|
|
25
|
+
sql += queryToSql(query, context.values, {tablesUsed: context.tablesUsed})
|
|
26
|
+
.sql;
|
|
25
27
|
sql += '\n)';
|
|
26
28
|
return sql;
|
|
27
29
|
})
|
|
@@ -37,6 +39,7 @@ function withSql(withs, context) {
|
|
|
37
39
|
function tableSql(table, context) {
|
|
38
40
|
// Note: table is not validated
|
|
39
41
|
if (typeof table === 'string') {
|
|
42
|
+
context.tablesUsed.push({table});
|
|
40
43
|
return table;
|
|
41
44
|
}
|
|
42
45
|
if (!('table' in table)) {
|
|
@@ -44,6 +47,7 @@ function tableSql(table, context) {
|
|
|
44
47
|
}
|
|
45
48
|
let resultSql = '';
|
|
46
49
|
if (typeof table.table === 'string') {
|
|
50
|
+
context.tablesUsed.push(table);
|
|
47
51
|
if (typeof table.db === 'string') {
|
|
48
52
|
resultSql += `${table.db}.`;
|
|
49
53
|
}
|
|
@@ -123,12 +127,13 @@ function groupByFields(groupBy, context) {
|
|
|
123
127
|
* @param {QueryObj} query
|
|
124
128
|
* @param {any[] | null} [values]
|
|
125
129
|
* @param {Partial<ExpressionToSqlContext>} [options]
|
|
126
|
-
* @returns {{sql: string, values: any[] | null}}
|
|
130
|
+
* @returns {{sql: string, values: any[] | null, tables: DbTable[]}}
|
|
127
131
|
*/
|
|
128
132
|
function queryToSql(query, values = [], options = {}) {
|
|
129
133
|
/** @type {ExpressionToSqlContext} */
|
|
130
134
|
const context = {
|
|
131
135
|
values,
|
|
136
|
+
tablesUsed: [],
|
|
132
137
|
scope: query.scope,
|
|
133
138
|
useTableNames: query.joins && query.joins.length > 0,
|
|
134
139
|
equalOperator: 'IS',
|
|
@@ -169,7 +174,7 @@ function queryToSql(query, values = [], options = {}) {
|
|
|
169
174
|
}
|
|
170
175
|
result += '\n' + `OFFSET ${query.offset}`;
|
|
171
176
|
}
|
|
172
|
-
return {sql: result, values};
|
|
177
|
+
return {sql: result, values, tables: context.tablesUsed};
|
|
173
178
|
}
|
|
174
179
|
|
|
175
180
|
module.exports = {
|