rado 1.2.1 → 1.3.0-preview.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/README.md +163 -257
- package/dist/compat.d.ts +3 -0
- package/dist/core/Builder.d.ts +16 -9
- package/dist/core/Builder.js +52 -4
- package/dist/core/Column.d.ts +25 -21
- package/dist/core/Column.js +39 -23
- package/dist/core/Constraint.d.ts +2 -1
- package/dist/core/Constraint.js +2 -1
- package/dist/core/Database.d.ts +5 -4
- package/dist/core/Database.js +14 -13
- package/dist/core/Emitter.d.ts +2 -2
- package/dist/core/Index.d.ts +1 -1
- package/dist/core/Internal.d.ts +19 -2
- package/dist/core/Internal.js +29 -11
- package/dist/core/Param.js +2 -0
- package/dist/core/Queries.d.ts +1 -0
- package/dist/core/Queries.js +11 -1
- package/dist/core/Resolver.js +2 -2
- package/dist/core/Schema.d.ts +1 -3
- package/dist/core/Selection.d.ts +9 -4
- package/dist/core/Selection.js +94 -5
- package/dist/core/Sql.d.ts +4 -3
- package/dist/core/Sql.js +8 -2
- package/dist/core/Table.d.ts +18 -11
- package/dist/core/Table.js +45 -25
- package/dist/core/View.d.ts +34 -0
- package/dist/core/View.js +153 -0
- package/dist/core/Virtual.d.ts +7 -2
- package/dist/core/Virtual.js +14 -10
- package/dist/core/expr/Conditions.d.ts +7 -7
- package/dist/core/expr/Include.d.ts +2 -2
- package/dist/core/expr/Include.js +1 -1
- package/dist/core/expr/Input.d.ts +1 -1
- package/dist/core/expr/Input.js +5 -1
- package/dist/core/query/CTE.d.ts +3 -5
- package/dist/core/query/CTE.js +1 -13
- package/dist/core/query/Delete.d.ts +10 -10
- package/dist/core/query/Delete.js +2 -2
- package/dist/core/query/Insert.d.ts +6 -5
- package/dist/core/query/Insert.js +22 -9
- package/dist/core/query/Query.d.ts +26 -11
- package/dist/core/query/Select.d.ts +41 -8
- package/dist/core/query/Select.js +235 -25
- package/dist/core/query/Shared.d.ts +2 -1
- package/dist/core/query/Shared.js +8 -5
- package/dist/core/query/Update.d.ts +9 -9
- package/dist/core/query/Update.js +24 -12
- package/dist/driver/better-sqlite3.js +4 -0
- package/dist/driver/bun-sqlite.js +3 -0
- package/dist/driver/d1.js +3 -0
- package/dist/driver/libsql.js +4 -0
- package/dist/driver/mysql2.js +5 -0
- package/dist/driver/pg.d.ts +17 -1
- package/dist/driver/pg.js +10 -1
- package/dist/driver/pglite.js +21 -6
- package/dist/driver/sql.js.js +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mysql/columns.d.ts +30 -30
- package/dist/mysql/columns.js +25 -24
- package/dist/mysql/dialect.js +6 -2
- package/dist/mysql/diff.js +1 -1
- package/dist/mysql.d.ts +1 -0
- package/dist/mysql.js +2 -0
- package/dist/postgres/columns.d.ts +103 -33
- package/dist/postgres/columns.js +317 -35
- package/dist/postgres/diff.js +3 -3
- package/dist/postgres/enum.d.ts +17 -0
- package/dist/postgres/enum.js +64 -0
- package/dist/postgres/schema.d.ts +19 -0
- package/dist/postgres/schema.js +47 -0
- package/dist/postgres.d.ts +3 -1
- package/dist/postgres.js +9 -2
- package/dist/sqlite/columns.d.ts +29 -14
- package/dist/sqlite/columns.js +41 -9
- package/dist/sqlite/dialect.js +3 -1
- package/dist/sqlite/diff.js +1 -1
- package/dist/sqlite/functions.d.ts +1 -1
- package/dist/sqlite/functions.js +1 -1
- package/dist/sqlite.d.ts +1 -0
- package/dist/sqlite.js +3 -6
- package/dist/universal/columns.d.ts +8 -8
- package/dist/universal/columns.js +10 -9
- package/dist/universal/functions.d.ts +1 -1
- package/dist/universal/functions.js +1 -1
- package/package.json +54 -37
package/dist/core/Selection.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
// src/core/Selection.ts
|
|
2
2
|
import {
|
|
3
3
|
getField,
|
|
4
|
+
getSelection,
|
|
4
5
|
getSql,
|
|
5
6
|
getTable,
|
|
6
7
|
hasField,
|
|
8
|
+
hasSelection,
|
|
7
9
|
hasTable,
|
|
8
10
|
internalSql
|
|
9
11
|
} from "./Internal.js";
|
|
10
12
|
import { sql } from "./Sql.js";
|
|
11
|
-
import {
|
|
13
|
+
import { virtualTarget } from "./Virtual.js";
|
|
12
14
|
var SqlColumn = class {
|
|
13
15
|
constructor(sql2, targetName) {
|
|
14
16
|
this.sql = sql2;
|
|
15
17
|
this.targetName = targetName;
|
|
16
18
|
}
|
|
19
|
+
sql;
|
|
20
|
+
targetName;
|
|
17
21
|
result(ctx) {
|
|
18
22
|
const value = ctx.values[ctx.index++];
|
|
19
23
|
if (!this.sql.mapFromDriverValue) return value;
|
|
@@ -25,6 +29,8 @@ var ObjectColumn = class {
|
|
|
25
29
|
this.nullable = nullable;
|
|
26
30
|
this.entries = entries;
|
|
27
31
|
}
|
|
32
|
+
nullable;
|
|
33
|
+
entries;
|
|
28
34
|
result(ctx) {
|
|
29
35
|
const result = {};
|
|
30
36
|
let isNullable = this.nullable.size > 0;
|
|
@@ -46,16 +52,27 @@ var ObjectColumn = class {
|
|
|
46
52
|
return result;
|
|
47
53
|
}
|
|
48
54
|
};
|
|
49
|
-
|
|
55
|
+
function firstTargetName(input) {
|
|
56
|
+
const expr = getSql(input);
|
|
57
|
+
if (expr) return hasField(input) ? getField(input).targetName : void 0;
|
|
58
|
+
if (!input || typeof input !== "object") return;
|
|
59
|
+
for (const value of Object.values(input)) {
|
|
60
|
+
const name = firstTargetName(value);
|
|
61
|
+
if (name) return name;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
var Selection = class _Selection {
|
|
50
65
|
constructor(input, nullable = /* @__PURE__ */ new Set()) {
|
|
51
66
|
this.input = input;
|
|
52
67
|
this.nullable = nullable;
|
|
53
68
|
const root = this.#defineColumn(nullable, input);
|
|
54
69
|
this.mapRow = root.result.bind(root);
|
|
55
70
|
}
|
|
71
|
+
input;
|
|
72
|
+
nullable;
|
|
56
73
|
mapRow;
|
|
57
74
|
makeVirtual(name) {
|
|
58
|
-
return
|
|
75
|
+
return virtualTarget(name, this.input);
|
|
59
76
|
}
|
|
60
77
|
#defineColumn(nullable, input) {
|
|
61
78
|
const expr = getSql(input);
|
|
@@ -71,6 +88,24 @@ var Selection = class {
|
|
|
71
88
|
fieldNames() {
|
|
72
89
|
return this.#fieldNames(this.input, /* @__PURE__ */ new Set());
|
|
73
90
|
}
|
|
91
|
+
aliasOf(input) {
|
|
92
|
+
return this.#aliasOf(this.input, /* @__PURE__ */ new Set(), getSql(input));
|
|
93
|
+
}
|
|
94
|
+
#aliasOf(input, names, target, name) {
|
|
95
|
+
const expr = getSql(input);
|
|
96
|
+
if (expr) {
|
|
97
|
+
let exprName = name ?? expr.alias;
|
|
98
|
+
if (!exprName) return;
|
|
99
|
+
while (names.has(exprName)) exprName = `${exprName}_`;
|
|
100
|
+
names.add(exprName);
|
|
101
|
+
if (expr === target) return exprName;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
for (const [name2, value] of Object.entries(input)) {
|
|
105
|
+
const alias = this.#aliasOf(value, names, target, name2);
|
|
106
|
+
if (alias) return alias;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
74
109
|
#fieldNames(input, names, name) {
|
|
75
110
|
const expr = getSql(input);
|
|
76
111
|
if (expr) {
|
|
@@ -105,8 +140,40 @@ var Selection = class {
|
|
|
105
140
|
get [internalSql]() {
|
|
106
141
|
return sql.join(this.#selectionToSql(this.input, /* @__PURE__ */ new Set()), sql`, `);
|
|
107
142
|
}
|
|
143
|
+
#collectTargetNames(input, names) {
|
|
144
|
+
const expr = getSql(input);
|
|
145
|
+
if (expr) {
|
|
146
|
+
if (hasField(input)) names.add(getField(input).targetName);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
for (const value of Object.values(input))
|
|
150
|
+
this.#collectTargetNames(value, names);
|
|
151
|
+
}
|
|
152
|
+
#targetNames() {
|
|
153
|
+
const names = /* @__PURE__ */ new Set();
|
|
154
|
+
this.#collectTargetNames(this.input, names);
|
|
155
|
+
return names;
|
|
156
|
+
}
|
|
108
157
|
join(right, operator) {
|
|
109
|
-
|
|
158
|
+
if (hasSelection(right)) {
|
|
159
|
+
const selected2 = getSelection(right);
|
|
160
|
+
const alias = firstTargetName(selected2.input);
|
|
161
|
+
if (!alias) return this;
|
|
162
|
+
const nullable2 = new Set(this.nullable);
|
|
163
|
+
if (operator === "leftJoin" || operator === "fullJoin")
|
|
164
|
+
nullable2.add(alias);
|
|
165
|
+
if (operator === "rightJoin" || operator === "fullJoin")
|
|
166
|
+
for (const name of this.#targetNames()) nullable2.add(name);
|
|
167
|
+
return new _Selection(this.input, nullable2);
|
|
168
|
+
}
|
|
169
|
+
if (!hasTable(right)) return this;
|
|
170
|
+
const rightTable = getTable(right);
|
|
171
|
+
const nullable = new Set(this.nullable);
|
|
172
|
+
if (operator === "leftJoin" || operator === "fullJoin")
|
|
173
|
+
nullable.add(rightTable.aliased);
|
|
174
|
+
if (operator === "rightJoin" || operator === "fullJoin")
|
|
175
|
+
for (const name of this.#targetNames()) nullable.add(name);
|
|
176
|
+
return new _Selection(this.input, nullable);
|
|
110
177
|
}
|
|
111
178
|
};
|
|
112
179
|
var TableSelection = class extends Selection {
|
|
@@ -114,8 +181,23 @@ var TableSelection = class extends Selection {
|
|
|
114
181
|
super(table, /* @__PURE__ */ new Set());
|
|
115
182
|
this.table = table;
|
|
116
183
|
}
|
|
184
|
+
table;
|
|
117
185
|
join(right, operator) {
|
|
118
186
|
const leftTable = getTable(this.table);
|
|
187
|
+
if (hasSelection(right)) {
|
|
188
|
+
const selected2 = getSelection(right);
|
|
189
|
+
const alias = firstTargetName(selected2.input);
|
|
190
|
+
if (!alias) return this;
|
|
191
|
+
const nullable2 = new Set(this.nullable);
|
|
192
|
+
if (operator === "rightJoin" || operator === "fullJoin")
|
|
193
|
+
nullable2.add(leftTable.aliased);
|
|
194
|
+
if (operator === "leftJoin" || operator === "fullJoin")
|
|
195
|
+
nullable2.add(alias);
|
|
196
|
+
return new Selection(
|
|
197
|
+
{ [leftTable.aliased]: this.table, [alias]: selected2.input },
|
|
198
|
+
nullable2
|
|
199
|
+
);
|
|
200
|
+
}
|
|
119
201
|
if (!hasTable(right)) return this;
|
|
120
202
|
const rightTable = getTable(right);
|
|
121
203
|
const nullable = new Set(this.nullable);
|
|
@@ -134,17 +216,23 @@ var JoinSelection = class _JoinSelection extends Selection {
|
|
|
134
216
|
);
|
|
135
217
|
this.tables = tables;
|
|
136
218
|
}
|
|
219
|
+
tables;
|
|
137
220
|
join(right, operator) {
|
|
138
221
|
if (!hasTable(right)) return this;
|
|
139
222
|
const rightTable = getTable(right);
|
|
140
223
|
const nullable = new Set(this.nullable);
|
|
141
224
|
if (operator === "rightJoin" || operator === "fullJoin")
|
|
142
|
-
this.tables.
|
|
225
|
+
for (const table of this.tables) nullable.add(getTable(table).aliased);
|
|
143
226
|
if (operator === "leftJoin" || operator === "fullJoin")
|
|
144
227
|
nullable.add(rightTable.aliased);
|
|
145
228
|
return new _JoinSelection([...this.tables, right], nullable);
|
|
146
229
|
}
|
|
147
230
|
};
|
|
231
|
+
var StarSelection = class extends Selection {
|
|
232
|
+
get [internalSql]() {
|
|
233
|
+
return sql`*`;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
148
236
|
var selected = /* @__PURE__ */ new WeakMap();
|
|
149
237
|
function selection(input) {
|
|
150
238
|
if (input instanceof Selection) return input;
|
|
@@ -156,6 +244,7 @@ function selection(input) {
|
|
|
156
244
|
export {
|
|
157
245
|
JoinSelection,
|
|
158
246
|
Selection,
|
|
247
|
+
StarSelection,
|
|
159
248
|
TableSelection,
|
|
160
249
|
selection
|
|
161
250
|
};
|
package/dist/core/Sql.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { DriverSpecs } from './Driver.js';
|
|
2
2
|
import type { Emitter } from './Emitter.js';
|
|
3
|
-
import { type HasSql, internalSql } from './Internal.js';
|
|
4
|
-
import type { Runtime } from './MetaData.js';
|
|
5
3
|
import type { FieldData } from './expr/Field.js';
|
|
6
4
|
import type { JsonPath } from './expr/Json.js';
|
|
5
|
+
import { type HasSql, internalSql } from './Internal.js';
|
|
6
|
+
import type { Runtime } from './MetaData.js';
|
|
7
7
|
export type Decoder<T = unknown> = ((value: unknown) => T) | {
|
|
8
8
|
mapFromDriverValue?(value: unknown, specs: DriverSpecs): T;
|
|
9
9
|
};
|
|
@@ -14,13 +14,14 @@ export declare class Sql<Value = unknown> implements HasSql<Value> {
|
|
|
14
14
|
alias?: string;
|
|
15
15
|
mapFromDriverValue?: (input: unknown, specs: DriverSpecs) => Value;
|
|
16
16
|
readonly [internalSql]: this;
|
|
17
|
-
constructor(emit
|
|
17
|
+
constructor(emit: (emitter: Emitter) => void);
|
|
18
18
|
as(name: string): Sql<Value>;
|
|
19
19
|
mapWith<T = Value>(decoder: Decoder<T>): Sql<T>;
|
|
20
20
|
inlineFields(withTableName: boolean): Sql<Value>;
|
|
21
21
|
inlineValues(): Sql<Value>;
|
|
22
22
|
nameSelf(name: string): Sql<Value>;
|
|
23
23
|
forSelection(): Sql<Value>;
|
|
24
|
+
if(condition: unknown): Sql<Value> | undefined;
|
|
24
25
|
}
|
|
25
26
|
export declare function sql<T>(strings: TemplateStringsArray, ...inner: Array<HasSql | unknown>): Sql<T>;
|
|
26
27
|
export declare namespace sql {
|
package/dist/core/Sql.js
CHANGED
|
@@ -9,9 +9,10 @@ import {
|
|
|
9
9
|
var noop = () => {
|
|
10
10
|
};
|
|
11
11
|
var Sql = class _Sql {
|
|
12
|
-
constructor(emit
|
|
12
|
+
constructor(emit) {
|
|
13
13
|
this.emit = emit;
|
|
14
14
|
}
|
|
15
|
+
emit;
|
|
15
16
|
static SELF_TARGET = "$$self";
|
|
16
17
|
alias;
|
|
17
18
|
mapFromDriverValue;
|
|
@@ -37,12 +38,16 @@ var Sql = class _Sql {
|
|
|
37
38
|
forSelection() {
|
|
38
39
|
return this;
|
|
39
40
|
}
|
|
41
|
+
if(condition) {
|
|
42
|
+
return condition ? this : void 0;
|
|
43
|
+
}
|
|
40
44
|
};
|
|
41
45
|
var JsonPathSql = class extends Sql {
|
|
42
46
|
constructor(path) {
|
|
43
47
|
super((emitter) => emitter.emitJsonPath(path));
|
|
44
48
|
this.path = path;
|
|
45
49
|
}
|
|
50
|
+
path;
|
|
46
51
|
forSelection() {
|
|
47
52
|
return sql.jsonPath({ ...this.path, asSql: false }).mapWith(this);
|
|
48
53
|
}
|
|
@@ -53,6 +58,7 @@ function sql(strings, ...inner) {
|
|
|
53
58
|
emitter.emitUnsafe(strings[i]);
|
|
54
59
|
if (i < inner.length) {
|
|
55
60
|
const insert = inner[i];
|
|
61
|
+
if (insert === void 0) continue;
|
|
56
62
|
const isObject = insert !== null && typeof insert === "object";
|
|
57
63
|
if (isObject && hasSql(insert)) getSql(insert).emit(emitter);
|
|
58
64
|
else if (isObject && hasTarget(insert)) getTarget(insert).emit(emitter);
|
|
@@ -63,7 +69,7 @@ function sql(strings, ...inner) {
|
|
|
63
69
|
}
|
|
64
70
|
((sql2) => {
|
|
65
71
|
function empty() {
|
|
66
|
-
return new Sql();
|
|
72
|
+
return new Sql(noop);
|
|
67
73
|
}
|
|
68
74
|
sql2.empty = empty;
|
|
69
75
|
function unsafe(directSql) {
|
package/dist/core/Table.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { type Column, type JsonColumn
|
|
1
|
+
import { type Column, type JsonColumn } from './Column.js';
|
|
2
2
|
import type { ForeignKeyConstraint, PrimaryKeyConstraint, UniqueConstraint } from './Constraint.js';
|
|
3
|
-
import { Index } from './Index.js';
|
|
4
|
-
import { type HasSelection, type HasSql, type HasTable } from './Internal.js';
|
|
5
|
-
import { type Sql } from './Sql.js';
|
|
6
3
|
import { Field } from './expr/Field.js';
|
|
7
4
|
import type { Input } from './expr/Input.js';
|
|
8
5
|
import { type JsonExpr } from './expr/Json.js';
|
|
6
|
+
import { Index } from './Index.js';
|
|
7
|
+
import { type HasCreate, type HasDrop, type HasSelection, type HasSql, type HasTable } from './Internal.js';
|
|
8
|
+
import { type Sql } from './Sql.js';
|
|
9
9
|
export type TableDefinition = {
|
|
10
10
|
[name: string]: Column;
|
|
11
11
|
};
|
|
@@ -24,30 +24,37 @@ export declare class TableApi<Definition extends TableDefinition = TableDefiniti
|
|
|
24
24
|
columnDefinition(name: string): Sql;
|
|
25
25
|
createDefinition(): Sql;
|
|
26
26
|
listColumns(): Sql;
|
|
27
|
-
fields(): Record<string, HasSql>;
|
|
28
27
|
createTable(altName?: string, ifNotExists?: boolean): Sql;
|
|
29
28
|
createIndexes(): Array<Sql>;
|
|
29
|
+
createEnums(): Array<Sql>;
|
|
30
30
|
create(): Array<Sql>;
|
|
31
|
-
drop(): Sql
|
|
31
|
+
drop(): Array<Sql>;
|
|
32
32
|
indexes(): Record<string, Index>;
|
|
33
33
|
}
|
|
34
|
-
export
|
|
34
|
+
export declare function tableFields(targetName: string, columns: TableDefinition): Record<string, HasSql>;
|
|
35
|
+
export type Table<Definition extends TableDefinition = Record<never, Column>, Name extends string = string> = TableFields<Definition, Name> & HasTable<Definition, Name> & HasSelection & HasCreate & HasDrop;
|
|
35
36
|
export type TableFields<Definition extends TableDefinition, TableName extends string = string> = {
|
|
36
|
-
[K in keyof Definition]: Definition[K] extends JsonColumn<infer T> ? JsonExpr<T> : Definition[K] extends Column<infer T
|
|
37
|
+
[K in keyof Definition]: Definition[K] extends JsonColumn<infer T> ? JsonExpr<T> : Definition[K] extends Column<infer T, [
|
|
38
|
+
infer Nullable extends boolean,
|
|
39
|
+
boolean
|
|
40
|
+
]> ? [Nullable] extends [false] ? Field<T, TableName> : Field<T | null, TableName> : never;
|
|
37
41
|
};
|
|
38
42
|
export type TableRow<Definition extends TableDefinition> = {
|
|
39
43
|
[K in keyof Definition]: Definition[K] extends Column<infer T> ? T : never;
|
|
40
44
|
} & {};
|
|
41
|
-
type IsReq<Col> = Col extends
|
|
45
|
+
type IsReq<Col> = Col extends Column<unknown, [boolean, infer Required extends boolean]> ? [Required] extends [true] ? true : false : false;
|
|
42
46
|
type RequiredInput<D> = {
|
|
43
47
|
readonly [K in keyof D as true extends IsReq<D[K]> ? K : never]: D[K] extends Column<infer V> ? Input<V> : never;
|
|
44
48
|
};
|
|
45
49
|
type OptionalInput<D> = {
|
|
46
|
-
readonly [K in keyof D as false extends IsReq<D[K]> ? K : never]?: D[K] extends Column<infer V> ? Input<V> : never;
|
|
50
|
+
readonly [K in keyof D as false extends IsReq<D[K]> ? K : never]?: D[K] extends Column<infer V> ? Input<V | null> : never;
|
|
47
51
|
};
|
|
48
52
|
export type TableInsert<Definition extends TableDefinition> = RequiredInput<Definition> & OptionalInput<Definition>;
|
|
49
53
|
export type TableUpdate<Definition extends TableDefinition> = {
|
|
50
|
-
readonly [K in keyof Definition]?: Definition[K] extends Column<infer T
|
|
54
|
+
readonly [K in keyof Definition]?: Definition[K] extends Column<infer T, [
|
|
55
|
+
infer Nullable extends boolean,
|
|
56
|
+
boolean
|
|
57
|
+
]> ? Nullable extends false ? Input<T> : Input<T | null> : never;
|
|
51
58
|
};
|
|
52
59
|
export type TableConfigSetting<Name extends string> = UniqueConstraint<Name> | PrimaryKeyConstraint<Name> | ForeignKeyConstraint<Name> | Index<Name>;
|
|
53
60
|
export interface TableConfig<Name extends string = string> extends Record<string, TableConfigSetting<Name>> {
|
package/dist/core/Table.js
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
// src/core/Table.ts
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
} from "./
|
|
2
|
+
import { collectEnumQuery } from "../postgres/enum.js";
|
|
3
|
+
import { formatColumn } from "./Column.js";
|
|
4
|
+
import { Field } from "./expr/Field.js";
|
|
5
|
+
import { jsonExpr } from "./expr/Json.js";
|
|
5
6
|
import { Index } from "./Index.js";
|
|
6
7
|
import {
|
|
7
8
|
getConstraint,
|
|
9
|
+
getCreate,
|
|
8
10
|
getData,
|
|
11
|
+
getDrop,
|
|
9
12
|
getTable,
|
|
10
13
|
hasConstraint,
|
|
14
|
+
internalCreate,
|
|
15
|
+
internalDrop,
|
|
11
16
|
internalSelection,
|
|
12
17
|
internalTable,
|
|
13
18
|
internalTarget
|
|
14
19
|
} from "./Internal.js";
|
|
15
20
|
import { selection } from "./Selection.js";
|
|
16
21
|
import { sql } from "./Sql.js";
|
|
17
|
-
import { Field } from "./expr/Field.js";
|
|
18
|
-
import { jsonExpr } from "./expr/Json.js";
|
|
19
22
|
var { assign, fromEntries, entries, keys } = Object;
|
|
20
23
|
var TableData = class {
|
|
21
24
|
name;
|
|
@@ -71,17 +74,6 @@ var TableApi = class extends TableData {
|
|
|
71
74
|
sql`, `
|
|
72
75
|
);
|
|
73
76
|
}
|
|
74
|
-
fields() {
|
|
75
|
-
return fromEntries(
|
|
76
|
-
entries(this.columns).map(([name, column]) => {
|
|
77
|
-
const columnApi = getData(column);
|
|
78
|
-
const { name: givenName } = columnApi;
|
|
79
|
-
const field = new Field(this.aliased, givenName ?? name, columnApi);
|
|
80
|
-
if (columnApi.json) return [name, jsonExpr(field)];
|
|
81
|
-
return [name, field];
|
|
82
|
-
})
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
77
|
createTable(altName, ifNotExists = false) {
|
|
86
78
|
return sql.join([
|
|
87
79
|
sql`create table`,
|
|
@@ -96,11 +88,14 @@ var TableApi = class extends TableData {
|
|
|
96
88
|
return indexApi.toSql(this.name, name, false);
|
|
97
89
|
});
|
|
98
90
|
}
|
|
91
|
+
createEnums() {
|
|
92
|
+
return collectEnumQuery(this);
|
|
93
|
+
}
|
|
99
94
|
create() {
|
|
100
|
-
return [this.createTable(), ...this.createIndexes()];
|
|
95
|
+
return [...this.createEnums(), this.createTable(), ...this.createIndexes()];
|
|
101
96
|
}
|
|
102
97
|
drop() {
|
|
103
|
-
return sql`drop table if exists ${this.
|
|
98
|
+
return [sql`drop table if exists ${this.identifier()}`];
|
|
104
99
|
}
|
|
105
100
|
indexes() {
|
|
106
101
|
return fromEntries(
|
|
@@ -108,17 +103,34 @@ var TableApi = class extends TableData {
|
|
|
108
103
|
);
|
|
109
104
|
}
|
|
110
105
|
};
|
|
106
|
+
function tableFields(targetName, columns) {
|
|
107
|
+
return fromEntries(
|
|
108
|
+
entries(columns).map(([name, column]) => {
|
|
109
|
+
const columnApi = getData(column);
|
|
110
|
+
const { name: givenName } = columnApi;
|
|
111
|
+
const field = new Field(targetName, givenName ?? name, columnApi);
|
|
112
|
+
if (columnApi.json) return [name, jsonExpr(field)];
|
|
113
|
+
return [name, field];
|
|
114
|
+
})
|
|
115
|
+
);
|
|
116
|
+
}
|
|
111
117
|
function table(name, columns, config, schemaName) {
|
|
112
118
|
const api = assign(new TableApi(), {
|
|
113
119
|
name,
|
|
114
120
|
schemaName,
|
|
115
121
|
columns
|
|
116
122
|
});
|
|
117
|
-
const fields = api.
|
|
123
|
+
const fields = tableFields(api.aliased, api.columns);
|
|
118
124
|
const table2 = {
|
|
119
125
|
[internalTable]: api,
|
|
120
|
-
[internalTarget]: api.
|
|
126
|
+
[internalTarget]: api.identifier(),
|
|
121
127
|
[internalSelection]: selection(fields),
|
|
128
|
+
get [internalCreate]() {
|
|
129
|
+
return api.create();
|
|
130
|
+
},
|
|
131
|
+
get [internalDrop]() {
|
|
132
|
+
return api.drop();
|
|
133
|
+
},
|
|
122
134
|
...fields
|
|
123
135
|
};
|
|
124
136
|
if (config) api.config = config(table2);
|
|
@@ -129,22 +141,30 @@ function alias(table2, alias2) {
|
|
|
129
141
|
...getTable(table2),
|
|
130
142
|
alias: alias2
|
|
131
143
|
});
|
|
132
|
-
const fields = api.
|
|
144
|
+
const fields = tableFields(api.aliased, api.columns);
|
|
133
145
|
return {
|
|
134
146
|
[internalTable]: api,
|
|
135
|
-
[internalTarget]: api.
|
|
147
|
+
[internalTarget]: api.identifier(),
|
|
136
148
|
[internalSelection]: selection(fields),
|
|
137
|
-
|
|
149
|
+
get [internalCreate]() {
|
|
150
|
+
return getCreate(table2);
|
|
151
|
+
},
|
|
152
|
+
get [internalDrop]() {
|
|
153
|
+
return getDrop(table2);
|
|
154
|
+
},
|
|
155
|
+
...fields
|
|
138
156
|
};
|
|
139
157
|
}
|
|
140
158
|
function tableCreator(nameTable) {
|
|
141
159
|
return (name, columns, config, schemaName) => {
|
|
142
|
-
|
|
160
|
+
const created = table(nameTable(name), columns, config, schemaName);
|
|
161
|
+
return alias(created, name);
|
|
143
162
|
};
|
|
144
163
|
}
|
|
145
164
|
export {
|
|
146
165
|
TableApi,
|
|
147
166
|
alias,
|
|
148
167
|
table,
|
|
149
|
-
tableCreator
|
|
168
|
+
tableCreator,
|
|
169
|
+
tableFields
|
|
150
170
|
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type HasCreate, type HasDrop, type HasSql, type HasTarget, internalData } from './Internal.js';
|
|
2
|
+
import type { QueryMeta } from './MetaData.js';
|
|
3
|
+
import type { UnionBase } from './query/Select.js';
|
|
4
|
+
import { type Sql } from './Sql.js';
|
|
5
|
+
import { type TableDefinition, type TableFields } from './Table.js';
|
|
6
|
+
import type { VirtualTarget } from './Virtual.js';
|
|
7
|
+
interface ViewData {
|
|
8
|
+
name: string;
|
|
9
|
+
columns?: TableDefinition;
|
|
10
|
+
columnNames?: Array<string>;
|
|
11
|
+
schemaName?: string;
|
|
12
|
+
materialized?: boolean;
|
|
13
|
+
query?: Sql;
|
|
14
|
+
}
|
|
15
|
+
export declare class ViewBase {
|
|
16
|
+
readonly [internalData]: ViewData;
|
|
17
|
+
constructor(data: ViewData);
|
|
18
|
+
}
|
|
19
|
+
export interface View extends HasTarget, HasCreate, HasDrop {
|
|
20
|
+
}
|
|
21
|
+
export declare function createView(data: ViewData, as: HasSql): Sql;
|
|
22
|
+
export declare function dropView(data: ViewData): Sql;
|
|
23
|
+
export declare class QueryView extends ViewBase {
|
|
24
|
+
as<Input, Meta extends QueryMeta>(query: UnionBase<Input, Meta>): View & Input;
|
|
25
|
+
}
|
|
26
|
+
export declare class DefinedView<Definition extends TableDefinition> extends ViewBase {
|
|
27
|
+
existing(): VirtualTarget<TableFields<Definition>>;
|
|
28
|
+
as(query: HasSql): View & TableFields<Definition>;
|
|
29
|
+
}
|
|
30
|
+
export declare function view(name: string): QueryView;
|
|
31
|
+
export declare function view<Definition extends TableDefinition>(name: string, columns: Definition, schemaName?: string): DefinedView<Definition>;
|
|
32
|
+
export declare function materializedView(name: string): QueryView;
|
|
33
|
+
export declare function materializedView<Definition extends TableDefinition>(name: string, columns: Definition, schemaName?: string): DefinedView<Definition>;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// src/core/View.ts
|
|
2
|
+
import { Field } from "./expr/Field.js";
|
|
3
|
+
import {
|
|
4
|
+
getData,
|
|
5
|
+
getField,
|
|
6
|
+
getQuery,
|
|
7
|
+
getSelection,
|
|
8
|
+
getSql,
|
|
9
|
+
hasField,
|
|
10
|
+
hasSql,
|
|
11
|
+
internalCreate,
|
|
12
|
+
internalData,
|
|
13
|
+
internalDrop,
|
|
14
|
+
internalQuery,
|
|
15
|
+
internalSelection,
|
|
16
|
+
internalTarget
|
|
17
|
+
} from "./Internal.js";
|
|
18
|
+
import { selection } from "./Selection.js";
|
|
19
|
+
import { sql } from "./Sql.js";
|
|
20
|
+
import { tableFields } from "./Table.js";
|
|
21
|
+
var ViewBase = class {
|
|
22
|
+
[internalData];
|
|
23
|
+
constructor(data) {
|
|
24
|
+
this[internalData] = data;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
function viewIdentifier({ name, schemaName }) {
|
|
28
|
+
return schemaName ? sql.join([sql.identifier(schemaName), sql.identifier(name)], sql`.`) : sql.identifier(name);
|
|
29
|
+
}
|
|
30
|
+
function createView(data, as) {
|
|
31
|
+
const createKeyword = data.materialized ? sql`create materialized view` : sql`create view`;
|
|
32
|
+
const { columns, columnNames } = data;
|
|
33
|
+
const columnList = columnNames ? sql.join(
|
|
34
|
+
columnNames.map((name) => sql.identifier(name)),
|
|
35
|
+
sql`, `
|
|
36
|
+
) : columns ? sql.join(
|
|
37
|
+
Object.entries(columns).map(([name, column]) => {
|
|
38
|
+
const columnData = getData(column);
|
|
39
|
+
return sql.identifier(columnData.name ?? name);
|
|
40
|
+
}),
|
|
41
|
+
sql`, `
|
|
42
|
+
) : void 0;
|
|
43
|
+
return sql.join([
|
|
44
|
+
createKeyword,
|
|
45
|
+
viewIdentifier(data),
|
|
46
|
+
columnList ? sql`(${columnList})` : void 0,
|
|
47
|
+
sql`as`,
|
|
48
|
+
as
|
|
49
|
+
]).inlineValues();
|
|
50
|
+
}
|
|
51
|
+
function viewColumnNames(input) {
|
|
52
|
+
const expr = getSql(input);
|
|
53
|
+
if (expr) {
|
|
54
|
+
if (hasField(input)) return [getField(input).fieldName];
|
|
55
|
+
if (expr.alias) return [expr.alias];
|
|
56
|
+
throw new Error("Missing field name");
|
|
57
|
+
}
|
|
58
|
+
return Object.entries(input).flatMap(([name, value]) => {
|
|
59
|
+
const expr2 = getSql(value);
|
|
60
|
+
if (expr2 && !hasField(value)) return [expr2.alias ?? name];
|
|
61
|
+
return viewColumnNames(value);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function viewFields(alias, source) {
|
|
65
|
+
return Object.fromEntries(
|
|
66
|
+
Object.entries(source).map(([key, value]) => {
|
|
67
|
+
if (value && typeof value === "object" && !hasSql(value))
|
|
68
|
+
return [key, viewFields(alias, value)];
|
|
69
|
+
const fieldName = hasField(value) ? getField(value).fieldName : key;
|
|
70
|
+
return [key, new Field(alias, fieldName, getSql(value))];
|
|
71
|
+
})
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
function dropView(data) {
|
|
75
|
+
const dropKeyword = data.materialized ? sql`drop materialized view` : sql`drop view`;
|
|
76
|
+
return sql.join([dropKeyword, sql`if exists`, viewIdentifier(data)]);
|
|
77
|
+
}
|
|
78
|
+
var QueryView = class extends ViewBase {
|
|
79
|
+
as(query) {
|
|
80
|
+
const data = getData(this);
|
|
81
|
+
const input = getSelection(query).input;
|
|
82
|
+
const target = {
|
|
83
|
+
[internalTarget]: viewIdentifier(data),
|
|
84
|
+
...viewFields(data.name, input)
|
|
85
|
+
};
|
|
86
|
+
const createData = {
|
|
87
|
+
...data,
|
|
88
|
+
columnNames: viewColumnNames(input)
|
|
89
|
+
};
|
|
90
|
+
return {
|
|
91
|
+
...target,
|
|
92
|
+
[internalSelection]: selection(target),
|
|
93
|
+
[internalQuery]: getQuery(query),
|
|
94
|
+
get [internalCreate]() {
|
|
95
|
+
const result = createView(createData, getQuery(query));
|
|
96
|
+
return [result];
|
|
97
|
+
},
|
|
98
|
+
get [internalDrop]() {
|
|
99
|
+
return [dropView(data)];
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
var DefinedView = class extends ViewBase {
|
|
105
|
+
existing() {
|
|
106
|
+
const data = getData(this);
|
|
107
|
+
const { name, columns } = data;
|
|
108
|
+
const fields = tableFields(name, columns);
|
|
109
|
+
return {
|
|
110
|
+
[internalTarget]: viewIdentifier(data),
|
|
111
|
+
...fields,
|
|
112
|
+
[internalSelection]: selection(fields)
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
as(query) {
|
|
116
|
+
const data = getData(this);
|
|
117
|
+
const fields = tableFields(
|
|
118
|
+
data.name,
|
|
119
|
+
data.columns
|
|
120
|
+
);
|
|
121
|
+
return {
|
|
122
|
+
[internalTarget]: viewIdentifier(data),
|
|
123
|
+
...fields,
|
|
124
|
+
[internalSelection]: selection(fields),
|
|
125
|
+
[internalQuery]: getSql(query),
|
|
126
|
+
get [internalCreate]() {
|
|
127
|
+
const result = createView(data, query);
|
|
128
|
+
return [result];
|
|
129
|
+
},
|
|
130
|
+
get [internalDrop]() {
|
|
131
|
+
return [dropView(data)];
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
function view(name, columns, schemaName) {
|
|
137
|
+
if (columns) return new DefinedView({ name, columns, schemaName });
|
|
138
|
+
return new QueryView({ name, columns, schemaName });
|
|
139
|
+
}
|
|
140
|
+
function materializedView(name, columns, schemaName) {
|
|
141
|
+
const data = { name, columns, schemaName, materialized: true };
|
|
142
|
+
if (columns) return new DefinedView(data);
|
|
143
|
+
return new QueryView(data);
|
|
144
|
+
}
|
|
145
|
+
export {
|
|
146
|
+
DefinedView,
|
|
147
|
+
QueryView,
|
|
148
|
+
ViewBase,
|
|
149
|
+
createView,
|
|
150
|
+
dropView,
|
|
151
|
+
materializedView,
|
|
152
|
+
view
|
|
153
|
+
};
|
package/dist/core/Virtual.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
|
|
1
|
+
import { type HasQuery, internalTarget } from './Internal.js';
|
|
2
|
+
import { type Sql } from './Sql.js';
|
|
3
|
+
export type VirtualQuery<Input> = VirtualTarget<Input> & HasQuery;
|
|
4
|
+
export type VirtualTarget<Input> = Input & {
|
|
5
|
+
readonly [internalTarget]: Sql;
|
|
6
|
+
};
|
|
7
|
+
export declare function virtualTarget<Input>(alias: string, source: Input): VirtualTarget<Input>;
|