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.
Files changed (86) hide show
  1. package/README.md +163 -257
  2. package/dist/compat.d.ts +3 -0
  3. package/dist/core/Builder.d.ts +16 -9
  4. package/dist/core/Builder.js +52 -4
  5. package/dist/core/Column.d.ts +25 -21
  6. package/dist/core/Column.js +39 -23
  7. package/dist/core/Constraint.d.ts +2 -1
  8. package/dist/core/Constraint.js +2 -1
  9. package/dist/core/Database.d.ts +5 -4
  10. package/dist/core/Database.js +14 -13
  11. package/dist/core/Emitter.d.ts +2 -2
  12. package/dist/core/Index.d.ts +1 -1
  13. package/dist/core/Internal.d.ts +19 -2
  14. package/dist/core/Internal.js +29 -11
  15. package/dist/core/Param.js +2 -0
  16. package/dist/core/Queries.d.ts +1 -0
  17. package/dist/core/Queries.js +11 -1
  18. package/dist/core/Resolver.js +2 -2
  19. package/dist/core/Schema.d.ts +1 -3
  20. package/dist/core/Selection.d.ts +9 -4
  21. package/dist/core/Selection.js +94 -5
  22. package/dist/core/Sql.d.ts +4 -3
  23. package/dist/core/Sql.js +8 -2
  24. package/dist/core/Table.d.ts +18 -11
  25. package/dist/core/Table.js +45 -25
  26. package/dist/core/View.d.ts +34 -0
  27. package/dist/core/View.js +153 -0
  28. package/dist/core/Virtual.d.ts +7 -2
  29. package/dist/core/Virtual.js +14 -10
  30. package/dist/core/expr/Conditions.d.ts +7 -7
  31. package/dist/core/expr/Include.d.ts +2 -2
  32. package/dist/core/expr/Include.js +1 -1
  33. package/dist/core/expr/Input.d.ts +1 -1
  34. package/dist/core/expr/Input.js +5 -1
  35. package/dist/core/query/CTE.d.ts +3 -5
  36. package/dist/core/query/CTE.js +1 -13
  37. package/dist/core/query/Delete.d.ts +10 -10
  38. package/dist/core/query/Delete.js +2 -2
  39. package/dist/core/query/Insert.d.ts +6 -5
  40. package/dist/core/query/Insert.js +22 -9
  41. package/dist/core/query/Query.d.ts +26 -11
  42. package/dist/core/query/Select.d.ts +41 -8
  43. package/dist/core/query/Select.js +235 -25
  44. package/dist/core/query/Shared.d.ts +2 -1
  45. package/dist/core/query/Shared.js +8 -5
  46. package/dist/core/query/Update.d.ts +9 -9
  47. package/dist/core/query/Update.js +24 -12
  48. package/dist/driver/better-sqlite3.js +4 -0
  49. package/dist/driver/bun-sqlite.js +3 -0
  50. package/dist/driver/d1.js +3 -0
  51. package/dist/driver/libsql.js +4 -0
  52. package/dist/driver/mysql2.js +5 -0
  53. package/dist/driver/pg.d.ts +17 -1
  54. package/dist/driver/pg.js +10 -1
  55. package/dist/driver/pglite.js +21 -6
  56. package/dist/driver/sql.js.js +4 -0
  57. package/dist/index.d.ts +1 -0
  58. package/dist/index.js +1 -0
  59. package/dist/mysql/columns.d.ts +30 -30
  60. package/dist/mysql/columns.js +25 -24
  61. package/dist/mysql/dialect.js +6 -2
  62. package/dist/mysql/diff.js +1 -1
  63. package/dist/mysql.d.ts +1 -0
  64. package/dist/mysql.js +2 -0
  65. package/dist/postgres/columns.d.ts +103 -33
  66. package/dist/postgres/columns.js +317 -35
  67. package/dist/postgres/diff.js +3 -3
  68. package/dist/postgres/enum.d.ts +17 -0
  69. package/dist/postgres/enum.js +64 -0
  70. package/dist/postgres/schema.d.ts +19 -0
  71. package/dist/postgres/schema.js +47 -0
  72. package/dist/postgres.d.ts +3 -1
  73. package/dist/postgres.js +9 -2
  74. package/dist/sqlite/columns.d.ts +29 -14
  75. package/dist/sqlite/columns.js +41 -9
  76. package/dist/sqlite/dialect.js +3 -1
  77. package/dist/sqlite/diff.js +1 -1
  78. package/dist/sqlite/functions.d.ts +1 -1
  79. package/dist/sqlite/functions.js +1 -1
  80. package/dist/sqlite.d.ts +1 -0
  81. package/dist/sqlite.js +3 -6
  82. package/dist/universal/columns.d.ts +8 -8
  83. package/dist/universal/columns.js +10 -9
  84. package/dist/universal/functions.d.ts +1 -1
  85. package/dist/universal/functions.js +1 -1
  86. package/package.json +54 -37
@@ -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 { virtual } from "./Virtual.js";
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
- var Selection = class {
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 virtual(name, this.input);
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
- return this;
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.map((table) => getTable(table).aliased).forEach(nullable.add, nullable);
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
  };
@@ -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?: (emitter: Emitter) => void);
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 = noop) {
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) {
@@ -1,11 +1,11 @@
1
- import { type Column, type JsonColumn, type RequiredColumn } from './Column.js';
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 type Table<Definition extends TableDefinition = Record<never, Column>, Name extends string = string> = TableFields<Definition, Name> & HasTable<Definition, Name> & HasSelection;
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> ? Field<T, TableName> : never;
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 RequiredColumn<infer Value> ? null extends Value ? true : false : false;
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> ? Input<T> : never;
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>> {
@@ -1,21 +1,24 @@
1
1
  // src/core/Table.ts
2
- import {
3
- formatColumn
4
- } from "./Column.js";
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.target()}`;
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.fields();
123
+ const fields = tableFields(api.aliased, api.columns);
118
124
  const table2 = {
119
125
  [internalTable]: api,
120
- [internalTarget]: api.target(),
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.fields();
144
+ const fields = tableFields(api.aliased, api.columns);
133
145
  return {
134
146
  [internalTable]: api,
135
- [internalTarget]: api.target(),
147
+ [internalTarget]: api.identifier(),
136
148
  [internalSelection]: selection(fields),
137
- ...api.fields()
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
- return table(nameTable(name), columns, config, schemaName);
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
+ };
@@ -1,2 +1,7 @@
1
- import { type HasTarget } from './Internal.js';
2
- export declare function virtual<Input>(alias: string, source: Input): Input & HasTarget;
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>;