rado 1.0.14 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compat.d.ts +3 -3
- package/dist/compat.js +2 -0
- package/dist/core/Builder.d.ts +14 -9
- package/dist/core/Builder.js +24 -32
- package/dist/core/Column.d.ts +13 -4
- package/dist/core/Column.js +43 -8
- package/dist/core/Constraint.d.ts +16 -5
- package/dist/core/Constraint.js +17 -6
- package/dist/core/Database.d.ts +11 -4
- package/dist/core/Database.js +20 -4
- package/dist/core/Dialect.js +2 -2
- package/dist/core/Driver.d.ts +3 -3
- package/dist/core/Emitter.d.ts +7 -29
- package/dist/core/Emitter.js +31 -139
- package/dist/core/Index.d.ts +1 -1
- package/dist/core/Internal.d.ts +5 -4
- package/dist/core/Queries.d.ts +46 -0
- package/dist/core/{Query.js → Queries.js} +10 -8
- package/dist/core/Resolver.d.ts +2 -2
- package/dist/core/Selection.d.ts +7 -10
- package/dist/core/Selection.js +21 -22
- package/dist/core/Sql.d.ts +8 -29
- package/dist/core/Sql.js +67 -118
- package/dist/core/Table.d.ts +7 -3
- package/dist/core/Table.js +24 -8
- package/dist/core/Virtual.d.ts +1 -1
- package/dist/core/Virtual.js +15 -14
- package/dist/core/expr/Conditions.d.ts +4 -4
- package/dist/core/expr/Conditions.js +18 -8
- package/dist/core/expr/Field.d.ts +8 -6
- package/dist/core/expr/Field.js +3 -3
- package/dist/core/expr/Include.d.ts +10 -7
- package/dist/core/expr/Include.js +29 -12
- package/dist/core/expr/Input.d.ts +3 -1
- package/dist/core/expr/Input.js +24 -7
- package/dist/core/expr/Json.js +2 -2
- package/dist/core/query/CTE.d.ts +8 -0
- package/dist/core/query/CTE.js +33 -0
- package/dist/core/query/Delete.d.ts +14 -13
- package/dist/core/query/Delete.js +32 -6
- package/dist/core/query/Insert.d.ts +17 -36
- package/dist/core/query/Insert.js +121 -72
- package/dist/core/query/Query.d.ts +124 -0
- package/dist/core/query/Select.d.ts +74 -33
- package/dist/core/query/Select.js +255 -57
- package/dist/core/query/Shared.d.ts +3 -0
- package/dist/core/query/Shared.js +23 -0
- package/dist/core/query/Update.d.ts +13 -13
- package/dist/core/query/Update.js +51 -22
- package/dist/driver/d1.d.ts +2 -2
- package/dist/driver/libsql.d.ts +2 -2
- package/dist/driver/mysql2.d.ts +2 -2
- package/dist/driver/pg.d.ts +2 -2
- package/dist/driver/pglite.d.ts +2 -2
- package/dist/index.d.ts +7 -7
- package/dist/index.js +7 -7
- package/dist/mysql/columns.d.ts +37 -37
- package/dist/mysql/columns.js +32 -15
- package/dist/mysql/dialect.js +6 -7
- package/dist/mysql/diff.js +2 -1
- package/dist/mysql.d.ts +3 -2
- package/dist/mysql.js +11 -2
- package/dist/postgres/columns.d.ts +13 -13
- package/dist/postgres/columns.js +15 -6
- package/dist/postgres/dialect.js +6 -7
- package/dist/postgres/diff.js +2 -1
- package/dist/postgres.d.ts +3 -2
- package/dist/postgres.js +11 -2
- package/dist/sqlite/columns.d.ts +16 -1
- package/dist/sqlite/columns.js +36 -3
- package/dist/sqlite/dialect.js +6 -6
- package/dist/sqlite/diff.js +3 -5
- package/dist/sqlite.d.ts +3 -2
- package/dist/sqlite.js +11 -2
- package/dist/universal/functions.js +4 -1
- package/package.json +4 -4
- package/dist/core/Join.d.ts +0 -1
- package/dist/core/Query.d.ts +0 -46
- package/dist/core/query/Union.d.ts +0 -35
- package/dist/core/query/Union.js +0 -107
- /package/dist/core/{Join.js → query/Query.js} +0 -0
package/dist/core/Sql.js
CHANGED
|
@@ -1,122 +1,65 @@
|
|
|
1
1
|
// src/core/Sql.ts
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
import {
|
|
3
|
+
getSql,
|
|
4
|
+
getTarget,
|
|
5
|
+
hasSql,
|
|
6
|
+
hasTarget,
|
|
7
|
+
internalSql
|
|
8
|
+
} from "./Internal.js";
|
|
9
|
+
var noop = () => {
|
|
8
10
|
};
|
|
9
11
|
var Sql = class _Sql {
|
|
12
|
+
constructor(emit = noop) {
|
|
13
|
+
this.emit = emit;
|
|
14
|
+
}
|
|
10
15
|
static SELF_TARGET = "$$self";
|
|
11
16
|
alias;
|
|
12
17
|
mapFromDriverValue;
|
|
13
18
|
[internalSql] = this;
|
|
14
|
-
#chunks;
|
|
15
|
-
constructor(chunks = []) {
|
|
16
|
-
this.#chunks = chunks;
|
|
17
|
-
}
|
|
18
19
|
as(name) {
|
|
19
20
|
this.alias = name;
|
|
20
21
|
return this;
|
|
21
22
|
}
|
|
22
23
|
mapWith(decoder) {
|
|
23
24
|
const res = this;
|
|
24
|
-
res.mapFromDriverValue = typeof decoder === "function" ? decoder : decoder.mapFromDriverValue;
|
|
25
|
+
res.mapFromDriverValue = typeof decoder === "function" ? (input) => input === null ? null : decoder(input) : decoder.mapFromDriverValue;
|
|
25
26
|
return res;
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return this;
|
|
30
|
-
}
|
|
31
|
-
unsafe(sql2) {
|
|
32
|
-
if (sql2.length > 0) this.chunk("emitUnsafe", sql2);
|
|
33
|
-
return this;
|
|
34
|
-
}
|
|
35
|
-
field(field) {
|
|
36
|
-
return this.chunk("emitField", field);
|
|
37
|
-
}
|
|
38
|
-
add(sql2) {
|
|
39
|
-
const inner = getSql(sql2);
|
|
40
|
-
if (!(inner instanceof _Sql)) throw new Error("Invalid SQL");
|
|
41
|
-
this.#chunks.push(...inner.#chunks);
|
|
42
|
-
return this;
|
|
43
|
-
}
|
|
44
|
-
value(value) {
|
|
45
|
-
return this.chunk("emitValue", value);
|
|
46
|
-
}
|
|
47
|
-
getValue() {
|
|
48
|
-
if (this.#chunks.length !== 1) return;
|
|
49
|
-
const chunk = this.#chunks[0];
|
|
50
|
-
if (chunk?.type === "emitValue") return chunk.inner;
|
|
28
|
+
inlineFields(withTableName) {
|
|
29
|
+
return new _Sql((emitter) => emitter.inlineFields(this, withTableName));
|
|
51
30
|
}
|
|
52
|
-
|
|
53
|
-
return
|
|
31
|
+
inlineValues() {
|
|
32
|
+
return new _Sql((emitter) => emitter.inlineValues(this));
|
|
54
33
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (inner?.type !== "emitJsonPath") return this.chunk("emitJsonPath", path);
|
|
58
|
-
const innerPath = inner.inner;
|
|
59
|
-
return this.chunk("emitJsonPath", {
|
|
60
|
-
...innerPath,
|
|
61
|
-
segments: [...innerPath.segments, ...path.segments]
|
|
62
|
-
});
|
|
34
|
+
nameSelf(name) {
|
|
35
|
+
return new _Sql((emitter) => emitter.emitSelf(this, name));
|
|
63
36
|
}
|
|
64
37
|
forSelection() {
|
|
65
|
-
if (this.#chunks.length === 1) {
|
|
66
|
-
const first = this.#chunks[0];
|
|
67
|
-
if (first.type === "emitJsonPath")
|
|
68
|
-
return sql.jsonPath({ ...first.inner, asSql: false }).mapWith(this);
|
|
69
|
-
}
|
|
70
38
|
return this;
|
|
71
39
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
inlineValues() {
|
|
79
|
-
return new _Sql(
|
|
80
|
-
this.#chunks.map((chunk) => {
|
|
81
|
-
if (chunk.type !== "emitValue") return chunk;
|
|
82
|
-
return new Chunk("emitInline", chunk.inner);
|
|
83
|
-
})
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
inlineFields(withTableName) {
|
|
87
|
-
return new _Sql(
|
|
88
|
-
this.#chunks.flatMap((chunk) => {
|
|
89
|
-
if (chunk.type !== "emitField") return [chunk];
|
|
90
|
-
const data = chunk.inner;
|
|
91
|
-
if (withTableName)
|
|
92
|
-
return [
|
|
93
|
-
new Chunk("emitIdentifierOrSelf", data.targetName),
|
|
94
|
-
new Chunk("emitUnsafe", "."),
|
|
95
|
-
new Chunk("emitIdentifier", data.fieldName)
|
|
96
|
-
];
|
|
97
|
-
return [new Chunk("emitIdentifier", data.fieldName)];
|
|
98
|
-
})
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
nameSelf(name) {
|
|
102
|
-
return sql.chunk("emitSelf", { name, inner: this });
|
|
40
|
+
};
|
|
41
|
+
var JsonPathSql = class extends Sql {
|
|
42
|
+
constructor(path) {
|
|
43
|
+
super((emitter) => emitter.emitJsonPath(path));
|
|
44
|
+
this.path = path;
|
|
103
45
|
}
|
|
104
|
-
|
|
105
|
-
|
|
46
|
+
forSelection() {
|
|
47
|
+
return sql.jsonPath({ ...this.path, asSql: false }).mapWith(this);
|
|
106
48
|
}
|
|
107
49
|
};
|
|
108
50
|
function sql(strings, ...inner) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
51
|
+
return new Sql((emitter) => {
|
|
52
|
+
for (let i = 0; i < strings.length; i++) {
|
|
53
|
+
emitter.emitUnsafe(strings[i]);
|
|
54
|
+
if (i < inner.length) {
|
|
55
|
+
const insert = inner[i];
|
|
56
|
+
const isObject = insert !== null && typeof insert === "object";
|
|
57
|
+
if (isObject && hasSql(insert)) getSql(insert).emit(emitter);
|
|
58
|
+
else if (isObject && hasTarget(insert)) getTarget(insert).emit(emitter);
|
|
59
|
+
else emitter.emitValueOrInline(insert);
|
|
60
|
+
}
|
|
117
61
|
}
|
|
118
|
-
}
|
|
119
|
-
return sql2;
|
|
62
|
+
});
|
|
120
63
|
}
|
|
121
64
|
((sql2) => {
|
|
122
65
|
function empty() {
|
|
@@ -124,61 +67,67 @@ function sql(strings, ...inner) {
|
|
|
124
67
|
}
|
|
125
68
|
sql2.empty = empty;
|
|
126
69
|
function unsafe(directSql) {
|
|
127
|
-
return
|
|
70
|
+
return new Sql((emitter) => emitter.emitUnsafe(String(directSql)));
|
|
128
71
|
}
|
|
129
72
|
sql2.unsafe = unsafe;
|
|
130
73
|
function value(value2) {
|
|
131
|
-
return
|
|
74
|
+
return new Sql((emitter) => emitter.emitValueOrInline(value2));
|
|
132
75
|
}
|
|
133
76
|
sql2.value = value;
|
|
134
77
|
function inline(value2) {
|
|
135
|
-
return
|
|
78
|
+
return new Sql((emitter) => emitter.emitInline(value2));
|
|
136
79
|
}
|
|
137
80
|
sql2.inline = inline;
|
|
138
81
|
function placeholder(name) {
|
|
139
|
-
return
|
|
82
|
+
return new Sql((emitter) => emitter.emitPlaceholder(name));
|
|
140
83
|
}
|
|
141
84
|
sql2.placeholder = placeholder;
|
|
142
85
|
function identifier(identifier2) {
|
|
143
|
-
return
|
|
86
|
+
return new Sql((emitter) => emitter.emitIdentifierOrSelf(identifier2));
|
|
144
87
|
}
|
|
145
88
|
sql2.identifier = identifier;
|
|
146
89
|
function field(field2) {
|
|
147
|
-
return
|
|
90
|
+
return new Sql((emitter) => emitter.emitField(field2));
|
|
148
91
|
}
|
|
149
92
|
sql2.field = field;
|
|
150
93
|
function jsonPath(path) {
|
|
151
|
-
|
|
94
|
+
if (path.target instanceof JsonPathSql) {
|
|
95
|
+
const inner = path.target.path;
|
|
96
|
+
return new JsonPathSql({
|
|
97
|
+
...inner,
|
|
98
|
+
segments: [...inner.segments, ...path.segments]
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return new JsonPathSql(path);
|
|
152
102
|
}
|
|
153
103
|
sql2.jsonPath = jsonPath;
|
|
154
|
-
function chunk(type, inner) {
|
|
155
|
-
return empty().chunk(type, inner);
|
|
156
|
-
}
|
|
157
|
-
sql2.chunk = chunk;
|
|
158
104
|
function universal(runtimes) {
|
|
159
|
-
return
|
|
105
|
+
return new Sql((emitter) => emitter.emitUniversal(runtimes));
|
|
160
106
|
}
|
|
161
107
|
sql2.universal = universal;
|
|
162
|
-
function query(
|
|
108
|
+
function query(...chunks) {
|
|
163
109
|
return join(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
110
|
+
chunks.filter(Boolean).flatMap((chunk) => {
|
|
111
|
+
if (hasSql(chunk)) return chunk;
|
|
112
|
+
return Object.entries(chunk).map(([key, value2]) => {
|
|
113
|
+
const statement = key.replace(/([A-Z])/g, " $1").toLowerCase();
|
|
114
|
+
if (value2 === true) return sql2.unsafe(statement);
|
|
115
|
+
if (Array.isArray(value2)) value2 = join(value2);
|
|
116
|
+
if (!key) return value2;
|
|
117
|
+
return value2 && sql2`${sql2.unsafe(statement)} ${value2}`;
|
|
118
|
+
});
|
|
170
119
|
})
|
|
171
120
|
);
|
|
172
121
|
}
|
|
173
122
|
sql2.query = query;
|
|
174
123
|
function join(items, separator = sql2` `) {
|
|
175
124
|
const parts = items.filter(Boolean);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
125
|
+
return new Sql((emitter) => {
|
|
126
|
+
for (let i = 0; i < parts.length; i++) {
|
|
127
|
+
if (i > 0) separator.emit(emitter);
|
|
128
|
+
getSql(parts[i]).emit(emitter);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
182
131
|
}
|
|
183
132
|
sql2.join = join;
|
|
184
133
|
})(sql || (sql = {}));
|
package/dist/core/Table.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Column, type JsonColumn, type RequiredColumn } from './Column.js';
|
|
2
2
|
import type { ForeignKeyConstraint, PrimaryKeyConstraint, UniqueConstraint } from './Constraint.js';
|
|
3
3
|
import { Index } from './Index.js';
|
|
4
|
-
import { type
|
|
4
|
+
import { type HasSelection, type HasSql, type HasTable } from './Internal.js';
|
|
5
5
|
import { type Sql } from './Sql.js';
|
|
6
6
|
import { Field } from './expr/Field.js';
|
|
7
7
|
import type { Input } from './expr/Input.js';
|
|
@@ -31,7 +31,7 @@ export declare class TableApi<Definition extends TableDefinition = TableDefiniti
|
|
|
31
31
|
drop(): Sql;
|
|
32
32
|
indexes(): Record<string, Index>;
|
|
33
33
|
}
|
|
34
|
-
export type Table<Definition extends TableDefinition = Record<never, Column>, Name extends string = string> = TableFields<Definition, Name> & HasTable<Definition, Name> &
|
|
34
|
+
export type Table<Definition extends TableDefinition = Record<never, Column>, Name extends string = string> = TableFields<Definition, Name> & HasTable<Definition, Name> & HasSelection;
|
|
35
35
|
export type TableFields<Definition extends TableDefinition, TableName extends string = string> = {
|
|
36
36
|
[K in keyof Definition]: Definition[K] extends JsonColumn<infer T> ? JsonExpr<T> : Definition[K] extends Column<infer T> ? Field<T, TableName> : never;
|
|
37
37
|
};
|
|
@@ -54,4 +54,8 @@ export interface TableConfig<Name extends string = string> extends Record<string
|
|
|
54
54
|
}
|
|
55
55
|
export declare function table<Definition extends TableDefinition, Name extends string>(name: Name, columns: Definition, config?: (self: Table<Definition, Name>) => TableConfig<Name>, schemaName?: string): Table<Definition, Name>;
|
|
56
56
|
export declare function alias<Definition extends TableDefinition, Alias extends string>(table: Table<Definition>, alias: Alias): Table<Definition, Alias>;
|
|
57
|
+
export declare function tableCreator(nameTable: (name: string) => string): typeof table;
|
|
58
|
+
export type InsertRow<T> = T extends Table<infer Definition> ? TableInsert<Definition> : never;
|
|
59
|
+
export type SelectRow<T> = T extends Table<infer Definition> ? TableRow<Definition> : never;
|
|
60
|
+
export type UpdateRow<T> = T extends Table<infer Definition> ? TableUpdate<Definition> : never;
|
|
57
61
|
export {};
|
package/dist/core/Table.js
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
// src/core/Table.ts
|
|
2
|
+
import {
|
|
3
|
+
formatColumn
|
|
4
|
+
} from "./Column.js";
|
|
2
5
|
import { Index } from "./Index.js";
|
|
3
6
|
import {
|
|
4
7
|
getConstraint,
|
|
5
8
|
getData,
|
|
6
9
|
getTable,
|
|
7
10
|
hasConstraint,
|
|
11
|
+
internalSelection,
|
|
8
12
|
internalTable,
|
|
9
13
|
internalTarget
|
|
10
14
|
} from "./Internal.js";
|
|
15
|
+
import { selection } from "./Selection.js";
|
|
11
16
|
import { sql } from "./Sql.js";
|
|
12
17
|
import { Field } from "./expr/Field.js";
|
|
13
18
|
import { jsonExpr } from "./expr/Json.js";
|
|
@@ -42,17 +47,18 @@ var TableApi = class extends TableData {
|
|
|
42
47
|
const columnData = this.columns[name];
|
|
43
48
|
const column = getData(columnData);
|
|
44
49
|
const columnName = sql.identifier(column.name ?? name);
|
|
45
|
-
return sql`${columnName} ${
|
|
50
|
+
return sql`${columnName} ${formatColumn(column)}`;
|
|
46
51
|
}
|
|
47
52
|
createDefinition() {
|
|
48
53
|
const createColumns = keys(this.columns).map(
|
|
49
54
|
(name) => this.columnDefinition(name)
|
|
50
55
|
);
|
|
51
|
-
const createConstraints = entries(this.config ?? {}).filter(([, constraint]) => hasConstraint(constraint)).map(
|
|
52
|
-
|
|
56
|
+
const createConstraints = entries(this.config ?? {}).filter(([, constraint]) => hasConstraint(constraint)).map(([key, constraint]) => {
|
|
57
|
+
const { name } = getData(constraint);
|
|
58
|
+
return sql`constraint ${sql.identifier(name ?? key)} ${getConstraint(
|
|
53
59
|
constraint
|
|
54
|
-
)}
|
|
55
|
-
);
|
|
60
|
+
)}`;
|
|
61
|
+
});
|
|
56
62
|
return sql.join(createColumns.concat(createConstraints), sql`, `);
|
|
57
63
|
}
|
|
58
64
|
listColumns() {
|
|
@@ -94,7 +100,7 @@ var TableApi = class extends TableData {
|
|
|
94
100
|
return [this.createTable(), ...this.createIndexes()];
|
|
95
101
|
}
|
|
96
102
|
drop() {
|
|
97
|
-
return sql`drop table ${this.target()}`;
|
|
103
|
+
return sql`drop table if exists ${this.target()}`;
|
|
98
104
|
}
|
|
99
105
|
indexes() {
|
|
100
106
|
return fromEntries(
|
|
@@ -108,10 +114,12 @@ function table(name, columns, config, schemaName) {
|
|
|
108
114
|
schemaName,
|
|
109
115
|
columns
|
|
110
116
|
});
|
|
117
|
+
const fields = api.fields();
|
|
111
118
|
const table2 = {
|
|
112
119
|
[internalTable]: api,
|
|
113
120
|
[internalTarget]: api.target(),
|
|
114
|
-
|
|
121
|
+
[internalSelection]: selection(fields),
|
|
122
|
+
...fields
|
|
115
123
|
};
|
|
116
124
|
if (config) api.config = config(table2);
|
|
117
125
|
return table2;
|
|
@@ -121,14 +129,22 @@ function alias(table2, alias2) {
|
|
|
121
129
|
...getTable(table2),
|
|
122
130
|
alias: alias2
|
|
123
131
|
});
|
|
132
|
+
const fields = api.fields();
|
|
124
133
|
return {
|
|
125
134
|
[internalTable]: api,
|
|
126
135
|
[internalTarget]: api.target(),
|
|
136
|
+
[internalSelection]: selection(fields),
|
|
127
137
|
...api.fields()
|
|
128
138
|
};
|
|
129
139
|
}
|
|
140
|
+
function tableCreator(nameTable) {
|
|
141
|
+
return (name, columns, config, schemaName) => {
|
|
142
|
+
return table(nameTable(name), columns, config, schemaName);
|
|
143
|
+
};
|
|
144
|
+
}
|
|
130
145
|
export {
|
|
131
146
|
TableApi,
|
|
132
147
|
alias,
|
|
133
|
-
table
|
|
148
|
+
table,
|
|
149
|
+
tableCreator
|
|
134
150
|
};
|
package/dist/core/Virtual.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { type HasTarget } from './Internal.js';
|
|
2
|
-
export declare function virtual<Input>(alias: string, source
|
|
2
|
+
export declare function virtual<Input>(alias: string, source: Input): Input & HasTarget;
|
package/dist/core/Virtual.js
CHANGED
|
@@ -3,25 +3,26 @@ import { getSql, hasSql, internalTarget } from "./Internal.js";
|
|
|
3
3
|
import { sql } from "./Sql.js";
|
|
4
4
|
import { Field } from "./expr/Field.js";
|
|
5
5
|
function virtual(alias, source) {
|
|
6
|
-
const target = {
|
|
7
|
-
|
|
6
|
+
const target = {
|
|
7
|
+
[internalTarget]: sql.identifier(alias)
|
|
8
|
+
};
|
|
9
|
+
if (!source || typeof source !== "object")
|
|
10
|
+
throw new Error("Cannot alias a non-object");
|
|
11
|
+
if (hasSql(source)) {
|
|
8
12
|
const expr = getSql(source);
|
|
9
13
|
const name = expr.alias;
|
|
10
14
|
if (!name) throw new Error("Cannot alias a virtual field without a name");
|
|
11
15
|
return Object.assign(new Field(alias, name, expr), target);
|
|
12
16
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
});
|
|
17
|
+
const aliased = Object.fromEntries(
|
|
18
|
+
Object.entries(source).map(([key, value]) => {
|
|
19
|
+
return [key, new Field(alias, key, getSql(value))];
|
|
20
|
+
})
|
|
21
|
+
);
|
|
22
|
+
return {
|
|
23
|
+
[internalTarget]: sql.identifier(alias),
|
|
24
|
+
...aliased
|
|
25
|
+
};
|
|
25
26
|
}
|
|
26
27
|
export {
|
|
27
28
|
virtual
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type HasSql } from '../Internal.js';
|
|
2
2
|
import type { Either } from '../MetaData.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { SingleQuery } from '../Queries.js';
|
|
4
4
|
import { type Sql } from '../Sql.js';
|
|
5
5
|
import { type Input } from './Input.js';
|
|
6
6
|
export declare const eq: <T>(left: Input<T>, right: Input<T>) => Sql<boolean>;
|
|
@@ -19,8 +19,8 @@ export declare const arrayOverlaps: <T>(left: Input<Array<T>>, right: Input<Arra
|
|
|
19
19
|
export declare function and(...conditions: Array<undefined | Input<boolean>>): Sql<boolean>;
|
|
20
20
|
export declare function or(...conditions: Array<undefined | Input<boolean>>): Sql<boolean>;
|
|
21
21
|
export declare function not(condition: Input<boolean>): Sql<boolean>;
|
|
22
|
-
export declare function inArray<T>(left: Input<T>, right:
|
|
23
|
-
export declare function notInArray<T>(left: Input<T>, right:
|
|
22
|
+
export declare function inArray<T>(left: Input<T>, right: SingleQuery<Array<T>, any> | Input<Array<T>>): Sql<boolean>;
|
|
23
|
+
export declare function notInArray<T>(left: Input<T>, right: SingleQuery<T, any> | Input<Array<T>>): Sql<boolean>;
|
|
24
24
|
export declare function isNull(value: Input): Sql<boolean>;
|
|
25
25
|
export declare function isNotNull(value: Input): Sql<boolean>;
|
|
26
26
|
export declare function between<T>(value: Input<T>, left: Input<T>, right: Input<T>): Sql<boolean>;
|
|
@@ -30,4 +30,4 @@ export declare function desc<T>(input: HasSql<T>): Sql;
|
|
|
30
30
|
export declare function distinct<T>(input: HasSql<T>): Sql;
|
|
31
31
|
export declare function when<In, Out>(compare: Input<In>, ...cases: Array<[condition: Input<In>, result: Input<Out>] | Input<Out>>): Sql<Out>;
|
|
32
32
|
export declare function when<Out>(...cases: Array<[condition: Input<boolean>, result: Input<Out>] | Input<Out>>): Sql<Out>;
|
|
33
|
-
export declare function exists(query:
|
|
33
|
+
export declare function exists(query: SingleQuery<any, Either>): Sql<boolean>;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
// src/core/expr/Conditions.ts
|
|
2
|
-
import { getQuery,
|
|
2
|
+
import { getQuery, hasSql } from "../Internal.js";
|
|
3
3
|
import { sql } from "../Sql.js";
|
|
4
4
|
import { input } from "./Input.js";
|
|
5
5
|
function bool(impl) {
|
|
6
6
|
return impl.mapWith(Boolean);
|
|
7
7
|
}
|
|
8
8
|
function binop(operator) {
|
|
9
|
-
return (left, right) => bool(
|
|
9
|
+
return (left, right) => bool(
|
|
10
|
+
sql`${input(left, right)} ${sql.unsafe(operator)} ${input(right, left)}`
|
|
11
|
+
);
|
|
10
12
|
}
|
|
11
13
|
var eq = binop("=");
|
|
12
14
|
var ne = binop("<>");
|
|
@@ -22,13 +24,13 @@ var arrayContains = binop("@>");
|
|
|
22
24
|
var arrayContained = binop("<@");
|
|
23
25
|
var arrayOverlaps = binop("&&");
|
|
24
26
|
function and(...conditions) {
|
|
25
|
-
const inputs = conditions.filter((v) => v !== void 0).map(input);
|
|
27
|
+
const inputs = conditions.filter((v) => v !== void 0).map((i) => input(i));
|
|
26
28
|
if (inputs.length === 0) return bool(sql`true`);
|
|
27
29
|
if (inputs.length === 1) return bool(inputs[0]);
|
|
28
30
|
return bool(sql`(${sql.join(inputs, sql` and `)})`);
|
|
29
31
|
}
|
|
30
32
|
function or(...conditions) {
|
|
31
|
-
const inputs = conditions.filter((v) => v !== void 0).map(input);
|
|
33
|
+
const inputs = conditions.filter((v) => v !== void 0).map((i) => input(i));
|
|
32
34
|
if (inputs.length === 0) return bool(sql`true`);
|
|
33
35
|
if (inputs.length === 1) return bool(inputs[0]);
|
|
34
36
|
return bool(sql`(${sql.join(inputs, sql` or `)})`);
|
|
@@ -37,19 +39,27 @@ function not(condition) {
|
|
|
37
39
|
return bool(sql`not ${input(condition)}`);
|
|
38
40
|
}
|
|
39
41
|
function inArray(left, right) {
|
|
40
|
-
const value =
|
|
42
|
+
const value = hasSql(right) ? void 0 : right;
|
|
41
43
|
if (Array.isArray(value)) {
|
|
42
44
|
if (value.length === 0) return sql`false`;
|
|
43
|
-
return bool(
|
|
45
|
+
return bool(
|
|
46
|
+
sql`${input(left)} in (${sql.join(
|
|
47
|
+
value.map((i) => input(i)),
|
|
48
|
+
sql`, `
|
|
49
|
+
)})`
|
|
50
|
+
);
|
|
44
51
|
}
|
|
45
52
|
return bool(sql`${input(left)} in ${input(right)}`);
|
|
46
53
|
}
|
|
47
54
|
function notInArray(left, right) {
|
|
48
|
-
const value =
|
|
55
|
+
const value = hasSql(right) ? void 0 : right;
|
|
49
56
|
if (Array.isArray(value)) {
|
|
50
57
|
if (value.length === 0) return sql`true`;
|
|
51
58
|
return bool(
|
|
52
|
-
sql`${input(left)} not in (${sql.join(
|
|
59
|
+
sql`${input(left)} not in (${sql.join(
|
|
60
|
+
value.map((i) => input(i)),
|
|
61
|
+
sql`, `
|
|
62
|
+
)})`
|
|
53
63
|
);
|
|
54
64
|
}
|
|
55
65
|
return bool(sql`${input(left)} not in ${input(right)}`);
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import {
|
|
3
|
-
import { type Sql } from '../Sql.js';
|
|
1
|
+
import { type HasSql, internalField, internalSql } from '../Internal.js';
|
|
2
|
+
import type { SelectionRecord } from '../Selection.js';
|
|
3
|
+
import { type Decoder, type Sql } from '../Sql.js';
|
|
4
4
|
export interface FieldData {
|
|
5
5
|
targetName: string;
|
|
6
6
|
fieldName: string;
|
|
7
|
+
source: Decoder;
|
|
7
8
|
}
|
|
8
9
|
export declare class Field<Value = unknown, Table extends string = string> implements HasSql<Value> {
|
|
9
10
|
private brand;
|
|
10
11
|
readonly [internalField]: FieldData;
|
|
11
12
|
readonly [internalSql]: Sql<Value>;
|
|
12
|
-
constructor(targetName: string, fieldName: string,
|
|
13
|
-
mapFromDriverValue?(value: unknown, specs: DriverSpecs): Value;
|
|
14
|
-
});
|
|
13
|
+
constructor(targetName: string, fieldName: string, source?: Decoder<Value>);
|
|
15
14
|
}
|
|
15
|
+
export type StripFieldMeta<Input> = Input extends HasSql<infer Value> ? HasSql<Value> : Input extends SelectionRecord ? {
|
|
16
|
+
[Key in keyof Input]: StripFieldMeta<Input[Key]>;
|
|
17
|
+
} : Input;
|
package/dist/core/expr/Field.js
CHANGED
|
@@ -4,10 +4,10 @@ import { sql } from "../Sql.js";
|
|
|
4
4
|
var Field = class {
|
|
5
5
|
[internalField];
|
|
6
6
|
[internalSql];
|
|
7
|
-
constructor(targetName, fieldName,
|
|
8
|
-
const field = { targetName, fieldName };
|
|
7
|
+
constructor(targetName, fieldName, source = {}) {
|
|
8
|
+
const field = { targetName, fieldName, source };
|
|
9
9
|
this[internalField] = field;
|
|
10
|
-
const expr = sql.field(field).as(fieldName).mapWith(
|
|
10
|
+
const expr = sql.field(field).as(fieldName).mapWith(source);
|
|
11
11
|
this[internalSql] = expr;
|
|
12
12
|
}
|
|
13
13
|
};
|
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type HasSql, internalData, internalSql } from '../Internal.js';
|
|
2
2
|
import type { QueryMeta } from '../MetaData.js';
|
|
3
|
+
import type { QueryData } from '../Queries.js';
|
|
3
4
|
import type { RowOfRecord } from '../Selection.js';
|
|
4
5
|
import { type Sql } from '../Sql.js';
|
|
5
|
-
import type {
|
|
6
|
-
|
|
6
|
+
import type { SelectQuery } from '../query/Query.js';
|
|
7
|
+
import { type Select, type SelectBase } from '../query/Select.js';
|
|
8
|
+
export type IncludeQuery = SelectQuery & {
|
|
7
9
|
first: boolean;
|
|
8
|
-
}
|
|
9
|
-
export declare class Include<Result, Meta extends QueryMeta = QueryMeta> implements
|
|
10
|
+
};
|
|
11
|
+
export declare class Include<Result, Meta extends QueryMeta = QueryMeta> implements HasSql<Result> {
|
|
10
12
|
#private;
|
|
11
13
|
private brand;
|
|
12
|
-
readonly [internalData]:
|
|
13
|
-
constructor(data:
|
|
14
|
+
readonly [internalData]: QueryData<Meta> & IncludeQuery;
|
|
15
|
+
constructor(data: QueryData<Meta> & IncludeQuery);
|
|
14
16
|
get [internalSql](): Sql<Result>;
|
|
15
17
|
}
|
|
16
18
|
export declare function include<Input, Meta extends QueryMeta>(select: Select<Input, Meta>): Include<Array<RowOfRecord<Input>>, Meta>;
|
|
17
19
|
export declare namespace include {
|
|
18
20
|
function one<Input, Meta extends QueryMeta>(select: SelectBase<Input, Meta>): Include<RowOfRecord<Input> | null, Meta>;
|
|
19
21
|
}
|
|
22
|
+
export declare function includeQuery(query: IncludeQuery): Sql;
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
// src/core/expr/Include.ts
|
|
2
|
-
import {
|
|
3
|
-
getData,
|
|
4
|
-
internalData,
|
|
5
|
-
internalSql
|
|
6
|
-
} from "../Internal.js";
|
|
2
|
+
import { getData, internalData, internalSql } from "../Internal.js";
|
|
7
3
|
import { sql } from "../Sql.js";
|
|
4
|
+
import {
|
|
5
|
+
querySelection,
|
|
6
|
+
selectQuery
|
|
7
|
+
} from "../query/Select.js";
|
|
8
|
+
import { jsonAggregateArray, jsonArray } from "./Json.js";
|
|
8
9
|
var Include = class {
|
|
9
10
|
[internalData];
|
|
10
11
|
constructor(data) {
|
|
11
12
|
this[internalData] = data;
|
|
12
13
|
}
|
|
13
14
|
#mapFromDriverValue = (value, specs) => {
|
|
14
|
-
const
|
|
15
|
+
const query = getData(this);
|
|
15
16
|
const parsed = specs.parsesJson ? value : JSON.parse(value);
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
const selected = querySelection(query);
|
|
18
|
+
if (query.first) {
|
|
19
|
+
const result = parsed ? selected.mapRow({ values: parsed, index: 0, specs }) : null;
|
|
18
20
|
return result;
|
|
19
21
|
}
|
|
20
22
|
if (!parsed) return [];
|
|
@@ -27,12 +29,12 @@ var Include = class {
|
|
|
27
29
|
for (let i = 0; i < rows.length; i++) {
|
|
28
30
|
ctx.values = rows[i];
|
|
29
31
|
ctx.index = 0;
|
|
30
|
-
rows[i] =
|
|
32
|
+
rows[i] = selected.mapRow(ctx);
|
|
31
33
|
}
|
|
32
34
|
return rows ?? [];
|
|
33
35
|
};
|
|
34
36
|
get [internalSql]() {
|
|
35
|
-
return
|
|
37
|
+
return includeQuery(getData(this)).mapWith({
|
|
36
38
|
mapFromDriverValue: this.#mapFromDriverValue
|
|
37
39
|
});
|
|
38
40
|
}
|
|
@@ -42,11 +44,26 @@ function include(select) {
|
|
|
42
44
|
}
|
|
43
45
|
((include2) => {
|
|
44
46
|
function one(select) {
|
|
45
|
-
return new Include({
|
|
47
|
+
return new Include({
|
|
48
|
+
...getData(select),
|
|
49
|
+
first: true
|
|
50
|
+
});
|
|
46
51
|
}
|
|
47
52
|
include2.one = one;
|
|
48
53
|
})(include || (include = {}));
|
|
54
|
+
function includeQuery(query) {
|
|
55
|
+
const { first, limit, offset, orderBy } = query;
|
|
56
|
+
const wrapQuery = Boolean(limit || offset || orderBy);
|
|
57
|
+
const innerQuery = selectQuery(query);
|
|
58
|
+
const inner = wrapQuery ? sql`select * from (${innerQuery})` : innerQuery;
|
|
59
|
+
const fields = querySelection(query).fieldNames();
|
|
60
|
+
const subject = jsonArray(
|
|
61
|
+
...fields.map((name) => sql`_.${sql.identifier(name)}`)
|
|
62
|
+
);
|
|
63
|
+
return sql`(select ${first ? subject : jsonAggregateArray(subject)} from (${inner}) as _)`;
|
|
64
|
+
}
|
|
49
65
|
export {
|
|
50
66
|
Include,
|
|
51
|
-
include
|
|
67
|
+
include,
|
|
68
|
+
includeQuery
|
|
52
69
|
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { ColumnData } from '../Column.js';
|
|
1
2
|
import { type HasSql } from '../Internal.js';
|
|
2
3
|
import { type Sql } from '../Sql.js';
|
|
3
4
|
export type Input<T = unknown> = HasSql<T> | T;
|
|
4
|
-
export declare function input<T>(value: Input<T>): Sql<T>;
|
|
5
|
+
export declare function input<T>(value: Input<T>, maybeField?: Input<T>): Sql<T>;
|
|
6
|
+
export declare function mapToColumn<T>({ mapToDriverValue }: ColumnData, expr: Input<T>): Sql<T>;
|