@deterministic-code/datasources 0.1.14 → 0.1.15
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.
|
@@ -83,7 +83,7 @@ export class BatchCommandIBulkWriteStrategy {
|
|
|
83
83
|
return { result: null, rowsAffected };
|
|
84
84
|
};
|
|
85
85
|
mappedInsert = (item) => {
|
|
86
|
-
const record = this.reverse(item);
|
|
86
|
+
const record = this.repo.fillCreateZeros(this.reverse(item));
|
|
87
87
|
const statement = this.statements().insert(this.fields(record, (col) => listed(this.options.createProperties, col, !this.ids.includes(col) || assigned(record[col] ?? null))));
|
|
88
88
|
return { table: statement.table, fields: statement.fields };
|
|
89
89
|
};
|
package/dist/CRUDRepository.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export declare class CRUDRepository<T = Cells> extends ReadonlyRepository<T> imp
|
|
|
14
14
|
readonly ids: readonly string[];
|
|
15
15
|
private readonly createProperties?;
|
|
16
16
|
private readonly updateProperties?;
|
|
17
|
+
protected createZeros?: Cells;
|
|
17
18
|
private readonly crudStatements;
|
|
18
19
|
private readonly tree;
|
|
19
20
|
private readonly write;
|
|
@@ -36,6 +37,7 @@ export declare class CRUDRepository<T = Cells> extends ReadonlyRepository<T> imp
|
|
|
36
37
|
private save;
|
|
37
38
|
private remove;
|
|
38
39
|
private byId;
|
|
40
|
+
fillCreateZeros: (record: Cells) => Cells;
|
|
39
41
|
private reverseConvert;
|
|
40
42
|
private idWhere;
|
|
41
43
|
protected enrichmentInto: (name: string) => boolean;
|
package/dist/CRUDRepository.js
CHANGED
|
@@ -37,6 +37,7 @@ export class CRUDRepository extends ReadonlyRepository {
|
|
|
37
37
|
ids;
|
|
38
38
|
createProperties;
|
|
39
39
|
updateProperties;
|
|
40
|
+
createZeros;
|
|
40
41
|
crudStatements;
|
|
41
42
|
tree;
|
|
42
43
|
write;
|
|
@@ -118,7 +119,7 @@ export class CRUDRepository extends ReadonlyRepository {
|
|
|
118
119
|
readSingleById = async (id) => this.readSingle(this.byId(id));
|
|
119
120
|
insert = async (item) => {
|
|
120
121
|
const extras = lookupKeys(item);
|
|
121
|
-
const record = this.reverseConvert(item);
|
|
122
|
+
const record = this.fillCreateZeros(this.reverseConvert(item));
|
|
122
123
|
const fields = fieldsOf(record, (col) => extras.has(col) || listed(this.createProperties, col, !this.ids.includes(col) || assigned(record[col] ?? null)), extras, this.cell, this.enrichmentInto, this.crudStatements.readColumns, this.column);
|
|
123
124
|
const statement = this.crudStatements.insert(fields);
|
|
124
125
|
const response = await execute(this.command(), statement, statement.fields);
|
|
@@ -181,6 +182,7 @@ export class CRUDRepository extends ReadonlyRepository {
|
|
|
181
182
|
throw new DatasourceError("Composite id requires a row keyed by each Id column");
|
|
182
183
|
return this.idWhere({ [this.ids[0]]: id });
|
|
183
184
|
};
|
|
185
|
+
fillCreateZeros = (record) => this.createZeros === undefined ? record : { ...this.createZeros, ...record };
|
|
184
186
|
reverseConvert = (item) => {
|
|
185
187
|
const row = this.objectConverter.reverseConvert(item);
|
|
186
188
|
const converted = this.rowConverter ? this.rowConverter.reverseConvert(row) : row;
|
|
@@ -6,6 +6,8 @@ export class ConditionRenderer {
|
|
|
6
6
|
}
|
|
7
7
|
render = (condition) => condition.accept(this);
|
|
8
8
|
visit(where) {
|
|
9
|
-
return where instanceof Where
|
|
9
|
+
return where instanceof Where || where.constructor.name === "Where"
|
|
10
|
+
? this.expressions.render(where.condition)
|
|
11
|
+
: where.rawText;
|
|
10
12
|
}
|
|
11
13
|
}
|
|
@@ -4,69 +4,70 @@ import { Literal } from "./Literal.js";
|
|
|
4
4
|
import { Operator } from "./Operator.js";
|
|
5
5
|
import { Subquery } from "./Subquery.js";
|
|
6
6
|
import { Where } from "./Where.js";
|
|
7
|
+
const is = (value, type, name) => value instanceof type || value.constructor.name === name;
|
|
7
8
|
export class ExpressionRenderer {
|
|
8
9
|
text;
|
|
9
10
|
constructor(text) {
|
|
10
11
|
this.text = text;
|
|
11
12
|
}
|
|
12
13
|
render = (expression) => {
|
|
13
|
-
if (expression
|
|
14
|
+
if (is(expression, Where, "Where"))
|
|
14
15
|
return this.render(expression.condition);
|
|
15
|
-
if (expression
|
|
16
|
+
if (is(expression, Identifier, "Identifier"))
|
|
16
17
|
return expression.name;
|
|
17
|
-
if (expression
|
|
18
|
+
if (is(expression, Literal, "Literal"))
|
|
18
19
|
return inline(expression.value);
|
|
19
|
-
if (expression
|
|
20
|
+
if (is(expression, ArrayExpression, "ArrayExpression"))
|
|
20
21
|
return expression.elements.map((e) => this.render(e)).join(", ");
|
|
21
|
-
if (expression
|
|
22
|
+
if (is(expression, Operator.Not, "Not"))
|
|
22
23
|
return `NOT (${this.render(expression.argument)})`;
|
|
23
|
-
if (expression
|
|
24
|
+
if (is(expression, Operator.IsNull, "IsNull"))
|
|
24
25
|
return `${this.render(expression.argument)} IS NULL`;
|
|
25
|
-
if (expression
|
|
26
|
+
if (is(expression, Operator.IsNotNull, "IsNotNull"))
|
|
26
27
|
return `${this.render(expression.argument)} IS NOT NULL`;
|
|
27
|
-
if (expression
|
|
28
|
+
if (is(expression, Operator.Exists, "Exists"))
|
|
28
29
|
return `EXISTS ${this.render(expression.argument)}`;
|
|
29
|
-
if (expression
|
|
30
|
+
if (is(expression, Subquery, "Subquery"))
|
|
30
31
|
return `(${this.text.render(expression.query)})`;
|
|
31
|
-
if (expression
|
|
32
|
-
expression.left
|
|
33
|
-
expression.right
|
|
32
|
+
if (is(expression, Operator.In, "In") &&
|
|
33
|
+
is(expression.left, Identifier, "Identifier") &&
|
|
34
|
+
is(expression.right, ArrayExpression, "ArrayExpression"))
|
|
34
35
|
return expression.right.elements.length === 0
|
|
35
36
|
? "1 = 0"
|
|
36
37
|
: `${expression.left.name} IN (${slots(expression.left.name, expression.right.elements.length)})`;
|
|
37
|
-
if (expression
|
|
38
|
-
expression.left
|
|
39
|
-
expression.right
|
|
38
|
+
if (is(expression, Operator.In, "In") &&
|
|
39
|
+
is(expression.left, Identifier, "Identifier") &&
|
|
40
|
+
is(expression.right, Subquery, "Subquery"))
|
|
40
41
|
return `${expression.left.name} IN ${this.render(expression.right)}`;
|
|
41
|
-
if (expression
|
|
42
|
-
expression.left
|
|
43
|
-
expression.right
|
|
42
|
+
if (is(expression, Operator.NotIn, "NotIn") &&
|
|
43
|
+
is(expression.left, Identifier, "Identifier") &&
|
|
44
|
+
is(expression.right, ArrayExpression, "ArrayExpression"))
|
|
44
45
|
return expression.right.elements.length === 0
|
|
45
46
|
? "1 = 1"
|
|
46
47
|
: `${expression.left.name} NOT IN (${slots(expression.left.name, expression.right.elements.length)})`;
|
|
47
|
-
if (expression
|
|
48
|
-
expression.left
|
|
49
|
-
expression.right
|
|
48
|
+
if (is(expression, Operator.NotIn, "NotIn") &&
|
|
49
|
+
is(expression.left, Identifier, "Identifier") &&
|
|
50
|
+
is(expression.right, Subquery, "Subquery"))
|
|
50
51
|
return `${expression.left.name} NOT IN ${this.render(expression.right)}`;
|
|
51
|
-
if ((expression
|
|
52
|
-
expression.value
|
|
53
|
-
expression.low
|
|
54
|
-
expression.high
|
|
55
|
-
const word = expression
|
|
52
|
+
if ((is(expression, Operator.Between, "Between") || is(expression, Operator.NotBetween, "NotBetween")) &&
|
|
53
|
+
is(expression.value, Identifier, "Identifier") &&
|
|
54
|
+
is(expression.low, Literal, "Literal") &&
|
|
55
|
+
is(expression.high, Literal, "Literal")) {
|
|
56
|
+
const word = is(expression, Operator.NotBetween, "NotBetween") ? "NOT BETWEEN" : "BETWEEN";
|
|
56
57
|
return `${expression.value.name} ${word} $${parameterName(expression.value.name)}_0 AND $${parameterName(expression.value.name)}_1`;
|
|
57
58
|
}
|
|
58
|
-
if (expression
|
|
59
|
+
if (is(expression, Operator.Between, "Between"))
|
|
59
60
|
return `${this.render(expression.value)} BETWEEN ${this.render(expression.low)} AND ${this.render(expression.high)}`;
|
|
60
|
-
if (expression
|
|
61
|
+
if (is(expression, Operator.NotBetween, "NotBetween"))
|
|
61
62
|
return `${this.render(expression.value)} NOT BETWEEN ${this.render(expression.low)} AND ${this.render(expression.high)}`;
|
|
62
|
-
if (expression
|
|
63
|
+
if (is(expression, Operator.And, "And"))
|
|
63
64
|
return `${this.wrap(expression.left, true)} AND ${this.wrap(expression.right, true)}`;
|
|
64
|
-
if (expression
|
|
65
|
+
if (is(expression, Operator.Or, "Or"))
|
|
65
66
|
return `${this.wrap(expression.left, false)} OR ${this.wrap(expression.right, false)}`;
|
|
66
|
-
const operands =
|
|
67
|
-
if (operands && operands.left
|
|
67
|
+
const operands = pair(expression);
|
|
68
|
+
if (operands && is(operands.left, Identifier, "Identifier") && is(operands.right, Literal, "Literal"))
|
|
68
69
|
return `${operands.left.name} ${symbol(expression)} $${parameterName(operands.left.name)}`;
|
|
69
|
-
if (operands && operands.left
|
|
70
|
+
if (operands && is(operands.left, Literal, "Literal") && is(operands.right, Literal, "Literal"))
|
|
70
71
|
return `${inline(operands.left.value)} ${symbol(expression)} ${inline(operands.right.value)}`;
|
|
71
72
|
if (operands)
|
|
72
73
|
return `${this.render(operands.left)} ${symbol(expression)} ${this.render(operands.right)}`;
|
|
@@ -74,23 +75,34 @@ export class ExpressionRenderer {
|
|
|
74
75
|
};
|
|
75
76
|
wrap = (child, and) => needsParens(child, and) ? `(${this.render(child)})` : this.render(child);
|
|
76
77
|
}
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
78
|
+
const symbols = {
|
|
79
|
+
Equals: "=",
|
|
80
|
+
NotEquals: "<>",
|
|
81
|
+
GreaterThan: ">",
|
|
82
|
+
LessThan: "<",
|
|
83
|
+
GreaterThanOrEqual: ">=",
|
|
84
|
+
LessThanOrEqual: "<=",
|
|
85
|
+
Like: "LIKE",
|
|
86
|
+
NotLike: "NOT LIKE",
|
|
87
|
+
};
|
|
88
|
+
const symbol = (op) => symbols[op.constructor.name] ??
|
|
89
|
+
(is(op, Operator.Equals, "Equals")
|
|
90
|
+
? "="
|
|
91
|
+
: is(op, Operator.NotEquals, "NotEquals")
|
|
92
|
+
? "<>"
|
|
93
|
+
: is(op, Operator.GreaterThan, "GreaterThan")
|
|
94
|
+
? ">"
|
|
95
|
+
: is(op, Operator.LessThan, "LessThan")
|
|
96
|
+
? "<"
|
|
97
|
+
: is(op, Operator.GreaterThanOrEqual, "GreaterThanOrEqual")
|
|
98
|
+
? ">="
|
|
99
|
+
: is(op, Operator.LessThanOrEqual, "LessThanOrEqual")
|
|
100
|
+
? "<="
|
|
101
|
+
: is(op, Operator.Like, "Like")
|
|
102
|
+
? "LIKE"
|
|
103
|
+
: is(op, Operator.NotLike, "NotLike")
|
|
104
|
+
? "NOT LIKE"
|
|
105
|
+
: "IN");
|
|
94
106
|
const inline = (value) => value === null
|
|
95
107
|
? "null"
|
|
96
108
|
: typeof value === "boolean"
|
|
@@ -98,24 +110,24 @@ const inline = (value) => value === null
|
|
|
98
110
|
: typeof value === "string"
|
|
99
111
|
? `'${value.replace(/'/g, "''")}'`
|
|
100
112
|
: String(value);
|
|
101
|
-
const needsParens = (child, and) => child
|
|
113
|
+
const needsParens = (child, and) => is(child, Where, "Where")
|
|
102
114
|
? needsParens(child.condition, and)
|
|
103
|
-
: child
|
|
104
|
-
child
|
|
105
|
-
child
|
|
106
|
-
(child
|
|
107
|
-
(child
|
|
108
|
-
const pair = (expression) => expression
|
|
109
|
-
expression
|
|
110
|
-
expression
|
|
111
|
-
expression
|
|
112
|
-
expression
|
|
113
|
-
expression
|
|
114
|
-
expression
|
|
115
|
-
expression
|
|
116
|
-
expression
|
|
117
|
-
expression
|
|
118
|
-
expression
|
|
115
|
+
: is(child, Operator.Not, "Not") ||
|
|
116
|
+
is(child, Operator.In, "In") ||
|
|
117
|
+
is(child, Operator.NotIn, "NotIn") ||
|
|
118
|
+
(is(child, Operator.And, "And") && !and) ||
|
|
119
|
+
(is(child, Operator.Or, "Or") && and);
|
|
120
|
+
const pair = (expression) => is(expression, Operator.Equals, "Equals") ||
|
|
121
|
+
is(expression, Operator.NotEquals, "NotEquals") ||
|
|
122
|
+
is(expression, Operator.GreaterThan, "GreaterThan") ||
|
|
123
|
+
is(expression, Operator.LessThan, "LessThan") ||
|
|
124
|
+
is(expression, Operator.GreaterThanOrEqual, "GreaterThanOrEqual") ||
|
|
125
|
+
is(expression, Operator.LessThanOrEqual, "LessThanOrEqual") ||
|
|
126
|
+
is(expression, Operator.And, "And") ||
|
|
127
|
+
is(expression, Operator.Or, "Or") ||
|
|
128
|
+
is(expression, Operator.In, "In") ||
|
|
129
|
+
is(expression, Operator.Like, "Like") ||
|
|
130
|
+
is(expression, Operator.NotLike, "NotLike")
|
|
119
131
|
? expression
|
|
120
132
|
: undefined;
|
|
121
133
|
const parameterName = (name) => parts(name)
|