drizzle-databend 0.1.12 → 0.1.14

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.
@@ -11,7 +11,7 @@ export declare class DatabendDatabase {
11
11
  query: any;
12
12
  constructor(dialect: any, session: any, schema?: any);
13
13
  $with(alias: string): {
14
- as(qb: any): WithSubquery<string, Record<string, unknown>>;
14
+ as(qb: any): WithSubquery<string, any>;
15
15
  };
16
16
  $count(source: any, filters?: any): DatabendCountBuilder;
17
17
  with(...queries: any[]): {
@@ -7,7 +7,7 @@ export declare class QueryBuilder {
7
7
  dialectConfig: any;
8
8
  constructor(dialect?: any);
9
9
  $with(alias: string): {
10
- as(qb: any): WithSubquery<string, Record<string, unknown>>;
10
+ as(qb: any): WithSubquery<string, any>;
11
11
  };
12
12
  with(...queries: any[]): {
13
13
  select: (fields?: any) => DatabendSelectBuilder;
@@ -26,6 +26,7 @@ declare class DatabendSelectQueryBuilderBase extends TypedQueryBuilder<any, any>
26
26
  rightJoin: (table: any, on: any) => this;
27
27
  innerJoin: (table: any, on: any) => this;
28
28
  fullJoin: (table: any, on: any) => this;
29
+ crossJoin: (table: any) => this;
29
30
  private createSetOperator;
30
31
  union: (rightSelection: any) => this;
31
32
  unionAll: (rightSelection: any) => this;
@@ -44,7 +45,7 @@ declare class DatabendSelectQueryBuilderBase extends TypedQueryBuilder<any, any>
44
45
  /** @internal */
45
46
  getSQL(): any;
46
47
  toSQL(): any;
47
- as(alias: string): Subquery<string, Record<string, unknown>>;
48
+ as(alias: string): Subquery<string, any>;
48
49
  /** @internal */
49
50
  getSelectedFields(): any;
50
51
  $dynamic(): this;
package/dist/index.mjs CHANGED
@@ -1065,6 +1065,7 @@ var DatabendDialect = class {
1065
1065
  }
1066
1066
  const table = joinMeta.table;
1067
1067
  const lateralSql = joinMeta.lateral ? sql3` lateral` : void 0;
1068
+ const onClause = joinMeta.on ? sql3` on ${joinMeta.on}` : void 0;
1068
1069
  if (is(table, DatabendTable)) {
1069
1070
  const t = table;
1070
1071
  const tableName = t[DatabendTable.Symbol.Name];
@@ -1072,7 +1073,7 @@ var DatabendDialect = class {
1072
1073
  const origTableName = t[DatabendTable.Symbol.OriginalName];
1073
1074
  const alias2 = tableName === origTableName ? void 0 : joinMeta.alias;
1074
1075
  joinsArray.push(
1075
- sql3`${sql3.raw(joinMeta.joinType)} join${lateralSql} ${tableSchema ? sql3`${sql3.identifier(tableSchema)}.` : void 0}${sql3.identifier(origTableName)}${alias2 && sql3` ${sql3.identifier(alias2)}`} on ${joinMeta.on}`
1076
+ sql3`${sql3.raw(joinMeta.joinType)} join${lateralSql} ${tableSchema ? sql3`${sql3.identifier(tableSchema)}.` : void 0}${sql3.identifier(origTableName)}${alias2 && sql3` ${sql3.identifier(alias2)}`}${onClause}`
1076
1077
  );
1077
1078
  } else if (is(table, View2)) {
1078
1079
  const viewName = table[ViewBaseConfig].name;
@@ -1080,11 +1081,11 @@ var DatabendDialect = class {
1080
1081
  const origViewName = table[ViewBaseConfig].originalName;
1081
1082
  const alias2 = viewName === origViewName ? void 0 : joinMeta.alias;
1082
1083
  joinsArray.push(
1083
- sql3`${sql3.raw(joinMeta.joinType)} join${lateralSql} ${viewSchema ? sql3`${sql3.identifier(viewSchema)}.` : void 0}${sql3.identifier(origViewName)}${alias2 && sql3` ${sql3.identifier(alias2)}`} on ${joinMeta.on}`
1084
+ sql3`${sql3.raw(joinMeta.joinType)} join${lateralSql} ${viewSchema ? sql3`${sql3.identifier(viewSchema)}.` : void 0}${sql3.identifier(origViewName)}${alias2 && sql3` ${sql3.identifier(alias2)}`}${onClause}`
1084
1085
  );
1085
1086
  } else {
1086
1087
  joinsArray.push(
1087
- sql3`${sql3.raw(joinMeta.joinType)} join${lateralSql} ${table} on ${joinMeta.on}`
1088
+ sql3`${sql3.raw(joinMeta.joinType)} join${lateralSql} ${table}${onClause}`
1088
1089
  );
1089
1090
  }
1090
1091
  if (index2 < joins.length - 1) {
@@ -1807,6 +1808,32 @@ var DatabendSelectQueryBuilderBase = class extends TypedQueryBuilder {
1807
1808
  rightJoin = this.createJoin("right");
1808
1809
  innerJoin = this.createJoin("inner");
1809
1810
  fullJoin = this.createJoin("full");
1811
+ crossJoin = (table) => {
1812
+ const baseTableName = this.tableName;
1813
+ const tableName = getTableLikeName(table);
1814
+ if (typeof tableName === "string" && this.config.joins?.some((join) => join.alias === tableName)) {
1815
+ throw new Error(`Alias "${tableName}" is already used in this query`);
1816
+ }
1817
+ if (!this.isPartialSelect) {
1818
+ if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") {
1819
+ this.config.fields = {
1820
+ [baseTableName]: this.config.fields
1821
+ };
1822
+ }
1823
+ if (typeof tableName === "string" && !is5(table, SQL4)) {
1824
+ const selection = is5(table, Subquery2) ? table._.selectedFields : is5(table, View3) ? table[ViewBaseConfig2].selectedFields : table[Table4.Symbol.Columns];
1825
+ this.config.fields[tableName] = selection;
1826
+ }
1827
+ }
1828
+ if (!this.config.joins) {
1829
+ this.config.joins = [];
1830
+ }
1831
+ this.config.joins.push({ on: void 0, table, joinType: "cross", alias: tableName });
1832
+ if (typeof tableName === "string") {
1833
+ this.joinsNotNullableMap[tableName] = true;
1834
+ }
1835
+ return this;
1836
+ };
1810
1837
  createSetOperator(type, isAll) {
1811
1838
  return (rightSelection) => {
1812
1839
  const rightSelect = typeof rightSelection === "function" ? rightSelection(getDatabendSetOperators()) : rightSelection;
@@ -2925,6 +2952,12 @@ import {
2925
2952
  is as is10,
2926
2953
  SQL as SQL8
2927
2954
  } from "drizzle-orm";
2955
+ function getFieldSql(field) {
2956
+ const f = field;
2957
+ if (f.sql instanceof SQL8) return f.sql;
2958
+ if (f._?.sql instanceof SQL8) return f._.sql;
2959
+ throw new Error("Cannot extract SQL from field");
2960
+ }
2928
2961
  function toDecoderInput(decoder, value) {
2929
2962
  void decoder;
2930
2963
  return value;
@@ -2975,11 +3008,12 @@ function mapResultRow(columns, row, joinsNotNullableMap) {
2975
3008
  } else if (is10(field, SQL8)) {
2976
3009
  decoder = field.decoder;
2977
3010
  } else {
2978
- const col = field.sql.queryChunks.find((chunk) => is10(chunk, Column3));
3011
+ const fieldSql = getFieldSql(field);
3012
+ const col = fieldSql.queryChunks.find((chunk) => is10(chunk, Column3));
2979
3013
  if (is10(col, DatabendCustomColumn)) {
2980
3014
  decoder = col;
2981
3015
  } else {
2982
- decoder = field.sql.decoder;
3016
+ decoder = fieldSql.decoder;
2983
3017
  }
2984
3018
  }
2985
3019
  let node = acc;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "module": "./dist/index.mjs",
4
4
  "main": "./dist/index.mjs",
5
5
  "types": "./dist/index.d.ts",
6
- "version": "0.1.12",
6
+ "version": "0.1.14",
7
7
  "description": "A drizzle ORM driver for use with Databend. Based on drizzle's Postgres driver surface.",
8
8
  "type": "module",
9
9
  "scripts": {
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "peerDependencies": {
20
20
  "databend-driver": ">=0.33.0",
21
- "drizzle-orm": "^0.40.0"
21
+ "drizzle-orm": ">=0.40.0"
22
22
  },
23
23
  "peerDependenciesMeta": {
24
24
  "databend-driver": {
@@ -29,7 +29,7 @@
29
29
  "@biomejs/biome": "^2.4.7",
30
30
  "@types/node": "^25.5.0",
31
31
  "databend-driver": "^0.33.6",
32
- "drizzle-orm": "0.40.0",
32
+ "drizzle-orm": "0.45.0",
33
33
  "esbuild": "^0.25.0",
34
34
  "typescript": "^5.8.2",
35
35
  "vitest": "^1.6.0"
@@ -206,6 +206,7 @@ export class DatabendDialect {
206
206
  }
207
207
  const table = joinMeta.table;
208
208
  const lateralSql = joinMeta.lateral ? sql` lateral` : undefined;
209
+ const onClause = joinMeta.on ? sql` on ${joinMeta.on}` : undefined;
209
210
  if (is(table, DatabendTable)) {
210
211
  const t = table as any;
211
212
  const tableName = t[(DatabendTable as any).Symbol.Name];
@@ -213,7 +214,7 @@ export class DatabendDialect {
213
214
  const origTableName = t[(DatabendTable as any).Symbol.OriginalName];
214
215
  const alias = tableName === origTableName ? undefined : joinMeta.alias;
215
216
  joinsArray.push(
216
- sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${tableSchema ? sql`${sql.identifier(tableSchema)}.` : undefined}${sql.identifier(origTableName)}${alias && sql` ${sql.identifier(alias)}`} on ${joinMeta.on}`
217
+ sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${tableSchema ? sql`${sql.identifier(tableSchema)}.` : undefined}${sql.identifier(origTableName)}${alias && sql` ${sql.identifier(alias)}`}${onClause}`
217
218
  );
218
219
  } else if (is(table, View)) {
219
220
  const viewName = (table as any)[ViewBaseConfig].name;
@@ -221,11 +222,11 @@ export class DatabendDialect {
221
222
  const origViewName = (table as any)[ViewBaseConfig].originalName;
222
223
  const alias = viewName === origViewName ? undefined : joinMeta.alias;
223
224
  joinsArray.push(
224
- sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${viewSchema ? sql`${sql.identifier(viewSchema)}.` : undefined}${sql.identifier(origViewName)}${alias && sql` ${sql.identifier(alias)}`} on ${joinMeta.on}`
225
+ sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${viewSchema ? sql`${sql.identifier(viewSchema)}.` : undefined}${sql.identifier(origViewName)}${alias && sql` ${sql.identifier(alias)}`}${onClause}`
225
226
  );
226
227
  } else {
227
228
  joinsArray.push(
228
- sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${table} on ${joinMeta.on}`
229
+ sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${table}${onClause}`
229
230
  );
230
231
  }
231
232
  if (index < joins.length - 1) {
@@ -170,6 +170,41 @@ class DatabendSelectQueryBuilderBase extends TypedQueryBuilder<any, any> {
170
170
  innerJoin = this.createJoin('inner');
171
171
  fullJoin = this.createJoin('full');
172
172
 
173
+ crossJoin = (table: any) => {
174
+ const baseTableName = this.tableName;
175
+ const tableName = getTableLikeName(table);
176
+
177
+ if (typeof tableName === 'string' && this.config.joins?.some((join: any) => join.alias === tableName)) {
178
+ throw new Error(`Alias "${tableName}" is already used in this query`);
179
+ }
180
+
181
+ if (!this.isPartialSelect) {
182
+ if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === 'string') {
183
+ this.config.fields = {
184
+ [baseTableName]: this.config.fields,
185
+ };
186
+ }
187
+ if (typeof tableName === 'string' && !is(table, SQL)) {
188
+ const selection = is(table, Subquery)
189
+ ? table._.selectedFields
190
+ : is(table, View)
191
+ ? (table as any)[ViewBaseConfig].selectedFields
192
+ : table[(Table as any).Symbol.Columns];
193
+ this.config.fields[tableName] = selection;
194
+ }
195
+ }
196
+
197
+ if (!this.config.joins) {
198
+ this.config.joins = [];
199
+ }
200
+ this.config.joins.push({ on: undefined, table, joinType: 'cross', alias: tableName });
201
+
202
+ if (typeof tableName === 'string') {
203
+ this.joinsNotNullableMap[tableName] = true;
204
+ }
205
+ return this;
206
+ };
207
+
173
208
  private createSetOperator(type: string, isAll: boolean) {
174
209
  return (rightSelection: any) => {
175
210
  const rightSelect = typeof rightSelection === 'function'
@@ -6,6 +6,7 @@ import {
6
6
  is,
7
7
  type SelectedFieldsOrdered,
8
8
  SQL,
9
+ Subquery,
9
10
  } from 'drizzle-orm';
10
11
  import { DatabendCustomColumn } from '../databend-core/columns/custom.ts';
11
12
  import { DatabendDate } from '../databend-core/columns/date.ts';
@@ -15,6 +16,14 @@ type SQLInternal<T = unknown> = SQL<T> & {
15
16
  decoder: DriverValueDecoder<T, any>;
16
17
  };
17
18
 
19
+ /** Extract SQL from Aliased (has .sql) or Subquery (has _.sql) */
20
+ function getFieldSql(field: unknown): SQL {
21
+ const f = field as any;
22
+ if (f.sql instanceof SQL) return f.sql;
23
+ if (f._?.sql instanceof SQL) return f._.sql;
24
+ throw new Error('Cannot extract SQL from field');
25
+ }
26
+
18
27
  type DecoderInput<TDecoder extends DriverValueDecoder<unknown, unknown>> =
19
28
  Parameters<TDecoder['mapFromDriverValue']>[0];
20
29
 
@@ -113,12 +122,13 @@ export function mapResultRow<TResult>(
113
122
  } else if (is(field, SQL)) {
114
123
  decoder = (field as SQLInternal).decoder;
115
124
  } else {
116
- const col = field.sql.queryChunks.find((chunk) => is(chunk, Column));
125
+ const fieldSql = getFieldSql(field);
126
+ const col = fieldSql.queryChunks.find((chunk) => is(chunk, Column));
117
127
 
118
128
  if (is(col, DatabendCustomColumn)) {
119
129
  decoder = col;
120
130
  } else {
121
- decoder = (field.sql as SQLInternal).decoder;
131
+ decoder = (fieldSql as SQLInternal).decoder;
122
132
  }
123
133
  }
124
134
  let node = acc;