@hemia/db-connector 0.0.10 → 0.0.11
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/hemia-db-connector.esm.js +3126 -14
- package/dist/hemia-db-connector.js +3284 -59
- package/dist/types/index.d.ts +13 -2
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createClient } from '@clickhouse/client';
|
|
2
2
|
import { drizzle } from 'drizzle-orm/postgres-js';
|
|
3
3
|
export { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
|
|
4
|
-
import { isNull, inArray, gt, gte, lt, lte, like, ilike, ne, eq, and } from 'drizzle-orm';
|
|
5
|
-
export { and, eq, gt, gte, ilike, inArray, isNull, like, lt, lte, ne, not, or, sql } from 'drizzle-orm';
|
|
4
|
+
import { isNull as isNull$1, inArray as inArray$1, gt as gt$1, gte as gte$1, lt as lt$1, lte as lte$1, like as like$1, ilike as ilike$1, ne as ne$1, eq as eq$1, and as and$1 } from 'drizzle-orm';
|
|
5
|
+
export { and, arrayContained, arrayContains, arrayOverlaps, asc, avg, avgDistinct, between, count, countDistinct, desc, eq, exists, gt, gte, ilike, inArray, isNotNull, isNull, like, lt, lte, max, min, ne, not, notBetween, notExists, notIlike, notInArray, notLike, or, sql, sum, sumDistinct } from 'drizzle-orm';
|
|
6
6
|
import os from 'os';
|
|
7
7
|
import fs from 'fs';
|
|
8
8
|
import net from 'net';
|
|
@@ -3120,39 +3120,39 @@ class DrizzlePostgresConnector extends DrizzleSqlConnector {
|
|
|
3120
3120
|
if (!column)
|
|
3121
3121
|
return;
|
|
3122
3122
|
if (value === null) {
|
|
3123
|
-
conditions.push(isNull(column));
|
|
3123
|
+
conditions.push(isNull$1(column));
|
|
3124
3124
|
}
|
|
3125
3125
|
else if (Array.isArray(value)) {
|
|
3126
|
-
conditions.push(inArray(column, value));
|
|
3126
|
+
conditions.push(inArray$1(column, value));
|
|
3127
3127
|
}
|
|
3128
3128
|
else if (typeof value === 'object' && value !== null) {
|
|
3129
3129
|
if ('$gt' in value) {
|
|
3130
|
-
conditions.push(gt(column, value.$gt));
|
|
3130
|
+
conditions.push(gt$1(column, value.$gt));
|
|
3131
3131
|
}
|
|
3132
3132
|
if ('$gte' in value) {
|
|
3133
|
-
conditions.push(gte(column, value.$gte));
|
|
3133
|
+
conditions.push(gte$1(column, value.$gte));
|
|
3134
3134
|
}
|
|
3135
3135
|
if ('$lt' in value) {
|
|
3136
|
-
conditions.push(lt(column, value.$lt));
|
|
3136
|
+
conditions.push(lt$1(column, value.$lt));
|
|
3137
3137
|
}
|
|
3138
3138
|
if ('$lte' in value) {
|
|
3139
|
-
conditions.push(lte(column, value.$lte));
|
|
3139
|
+
conditions.push(lte$1(column, value.$lte));
|
|
3140
3140
|
}
|
|
3141
3141
|
if ('$like' in value) {
|
|
3142
|
-
conditions.push(like(column, value.$like));
|
|
3142
|
+
conditions.push(like$1(column, value.$like));
|
|
3143
3143
|
}
|
|
3144
3144
|
if ('$ilike' in value) {
|
|
3145
|
-
conditions.push(ilike(column, value.$ilike));
|
|
3145
|
+
conditions.push(ilike$1(column, value.$ilike));
|
|
3146
3146
|
}
|
|
3147
3147
|
if ('$ne' in value) {
|
|
3148
|
-
conditions.push(ne(column, value.$ne));
|
|
3148
|
+
conditions.push(ne$1(column, value.$ne));
|
|
3149
3149
|
}
|
|
3150
3150
|
}
|
|
3151
3151
|
else {
|
|
3152
|
-
conditions.push(eq(column, value));
|
|
3152
|
+
conditions.push(eq$1(column, value));
|
|
3153
3153
|
}
|
|
3154
3154
|
});
|
|
3155
|
-
return conditions.length > 0 ? and(...conditions) : undefined;
|
|
3155
|
+
return conditions.length > 0 ? and$1(...conditions) : undefined;
|
|
3156
3156
|
}
|
|
3157
3157
|
buildRawWhereClause(where, params, offset = 0) {
|
|
3158
3158
|
if (!where || Object.keys(where).length === 0)
|
|
@@ -4118,14 +4118,73 @@ class ForeignKey {
|
|
|
4118
4118
|
return name ?? `${chunks.join("_")}_fk`;
|
|
4119
4119
|
}
|
|
4120
4120
|
}
|
|
4121
|
+
function foreignKey(config) {
|
|
4122
|
+
function mappedConfig() {
|
|
4123
|
+
const { name, columns, foreignColumns } = config;
|
|
4124
|
+
return {
|
|
4125
|
+
name,
|
|
4126
|
+
columns,
|
|
4127
|
+
foreignColumns
|
|
4128
|
+
};
|
|
4129
|
+
}
|
|
4130
|
+
return new ForeignKeyBuilder(mappedConfig);
|
|
4131
|
+
}
|
|
4121
4132
|
|
|
4122
4133
|
function iife(fn, ...args) {
|
|
4123
4134
|
return fn(...args);
|
|
4124
4135
|
}
|
|
4125
4136
|
|
|
4137
|
+
function unique(name) {
|
|
4138
|
+
return new UniqueOnConstraintBuilder(name);
|
|
4139
|
+
}
|
|
4126
4140
|
function uniqueKeyName(table, columns) {
|
|
4127
4141
|
return `${table[TableName]}_${columns.join("_")}_unique`;
|
|
4128
4142
|
}
|
|
4143
|
+
class UniqueConstraintBuilder {
|
|
4144
|
+
constructor(columns, name) {
|
|
4145
|
+
this.name = name;
|
|
4146
|
+
this.columns = columns;
|
|
4147
|
+
}
|
|
4148
|
+
static [entityKind] = "PgUniqueConstraintBuilder";
|
|
4149
|
+
/** @internal */
|
|
4150
|
+
columns;
|
|
4151
|
+
/** @internal */
|
|
4152
|
+
nullsNotDistinctConfig = false;
|
|
4153
|
+
nullsNotDistinct() {
|
|
4154
|
+
this.nullsNotDistinctConfig = true;
|
|
4155
|
+
return this;
|
|
4156
|
+
}
|
|
4157
|
+
/** @internal */
|
|
4158
|
+
build(table) {
|
|
4159
|
+
return new UniqueConstraint(table, this.columns, this.nullsNotDistinctConfig, this.name);
|
|
4160
|
+
}
|
|
4161
|
+
}
|
|
4162
|
+
class UniqueOnConstraintBuilder {
|
|
4163
|
+
static [entityKind] = "PgUniqueOnConstraintBuilder";
|
|
4164
|
+
/** @internal */
|
|
4165
|
+
name;
|
|
4166
|
+
constructor(name) {
|
|
4167
|
+
this.name = name;
|
|
4168
|
+
}
|
|
4169
|
+
on(...columns) {
|
|
4170
|
+
return new UniqueConstraintBuilder(columns, this.name);
|
|
4171
|
+
}
|
|
4172
|
+
}
|
|
4173
|
+
class UniqueConstraint {
|
|
4174
|
+
constructor(table, columns, nullsNotDistinct, name) {
|
|
4175
|
+
this.table = table;
|
|
4176
|
+
this.columns = columns;
|
|
4177
|
+
this.name = name ?? uniqueKeyName(this.table, this.columns.map((column) => column.name));
|
|
4178
|
+
this.nullsNotDistinct = nullsNotDistinct;
|
|
4179
|
+
}
|
|
4180
|
+
static [entityKind] = "PgUniqueConstraint";
|
|
4181
|
+
columns;
|
|
4182
|
+
name;
|
|
4183
|
+
nullsNotDistinct = false;
|
|
4184
|
+
getName() {
|
|
4185
|
+
return this.name;
|
|
4186
|
+
}
|
|
4187
|
+
}
|
|
4129
4188
|
|
|
4130
4189
|
function parsePgArrayValue(arrayString, startFrom, inQuotes) {
|
|
4131
4190
|
for (let i = startFrom; i < arrayString.length; i++) {
|
|
@@ -4328,6 +4387,19 @@ class ExtraConfigColumn extends PgColumn {
|
|
|
4328
4387
|
return this;
|
|
4329
4388
|
}
|
|
4330
4389
|
}
|
|
4390
|
+
class IndexedColumn {
|
|
4391
|
+
static [entityKind] = "IndexedColumn";
|
|
4392
|
+
constructor(name, keyAsName, type, indexConfig) {
|
|
4393
|
+
this.name = name;
|
|
4394
|
+
this.keyAsName = keyAsName;
|
|
4395
|
+
this.type = type;
|
|
4396
|
+
this.indexConfig = indexConfig;
|
|
4397
|
+
}
|
|
4398
|
+
name;
|
|
4399
|
+
keyAsName;
|
|
4400
|
+
type;
|
|
4401
|
+
indexConfig;
|
|
4402
|
+
}
|
|
4331
4403
|
class PgArrayBuilder extends PgColumnBuilder {
|
|
4332
4404
|
static [entityKind] = "PgArrayBuilder";
|
|
4333
4405
|
constructor(name, baseBuilder, size) {
|
|
@@ -4472,6 +4544,9 @@ class Subquery {
|
|
|
4472
4544
|
// return new SQL([this]);
|
|
4473
4545
|
// }
|
|
4474
4546
|
}
|
|
4547
|
+
class WithSubquery extends Subquery {
|
|
4548
|
+
static [entityKind] = "WithSubquery";
|
|
4549
|
+
}
|
|
4475
4550
|
|
|
4476
4551
|
const tracer = {
|
|
4477
4552
|
startActiveSpan(name, fn) {
|
|
@@ -4537,6 +4612,12 @@ class Table {
|
|
|
4537
4612
|
this[BaseName] = baseName;
|
|
4538
4613
|
}
|
|
4539
4614
|
}
|
|
4615
|
+
function getTableName(table) {
|
|
4616
|
+
return table[TableName];
|
|
4617
|
+
}
|
|
4618
|
+
function getTableUniqueName(table) {
|
|
4619
|
+
return `${table[Schema] ?? "public"}.${table[TableName]}`;
|
|
4620
|
+
}
|
|
4540
4621
|
|
|
4541
4622
|
function isSQLWrapper(value) {
|
|
4542
4623
|
return value !== null && value !== void 0 && typeof value.getSQL === "function";
|
|
@@ -4776,6 +4857,9 @@ class Name {
|
|
|
4776
4857
|
return new SQL([this]);
|
|
4777
4858
|
}
|
|
4778
4859
|
}
|
|
4860
|
+
function isDriverValueEncoder(value) {
|
|
4861
|
+
return typeof value === "object" && value !== null && "mapToDriverValue" in value && typeof value.mapToDriverValue === "function";
|
|
4862
|
+
}
|
|
4779
4863
|
const noopDecoder = {
|
|
4780
4864
|
mapFromDriverValue: (value) => value
|
|
4781
4865
|
};
|
|
@@ -4908,6 +4992,162 @@ Subquery.prototype.getSQL = function() {
|
|
|
4908
4992
|
return new SQL([this]);
|
|
4909
4993
|
};
|
|
4910
4994
|
|
|
4995
|
+
class ColumnAliasProxyHandler {
|
|
4996
|
+
constructor(table) {
|
|
4997
|
+
this.table = table;
|
|
4998
|
+
}
|
|
4999
|
+
static [entityKind] = "ColumnAliasProxyHandler";
|
|
5000
|
+
get(columnObj, prop) {
|
|
5001
|
+
if (prop === "table") {
|
|
5002
|
+
return this.table;
|
|
5003
|
+
}
|
|
5004
|
+
return columnObj[prop];
|
|
5005
|
+
}
|
|
5006
|
+
}
|
|
5007
|
+
class TableAliasProxyHandler {
|
|
5008
|
+
constructor(alias, replaceOriginalName) {
|
|
5009
|
+
this.alias = alias;
|
|
5010
|
+
this.replaceOriginalName = replaceOriginalName;
|
|
5011
|
+
}
|
|
5012
|
+
static [entityKind] = "TableAliasProxyHandler";
|
|
5013
|
+
get(target, prop) {
|
|
5014
|
+
if (prop === Table.Symbol.IsAlias) {
|
|
5015
|
+
return true;
|
|
5016
|
+
}
|
|
5017
|
+
if (prop === Table.Symbol.Name) {
|
|
5018
|
+
return this.alias;
|
|
5019
|
+
}
|
|
5020
|
+
if (this.replaceOriginalName && prop === Table.Symbol.OriginalName) {
|
|
5021
|
+
return this.alias;
|
|
5022
|
+
}
|
|
5023
|
+
if (prop === ViewBaseConfig) {
|
|
5024
|
+
return {
|
|
5025
|
+
...target[ViewBaseConfig],
|
|
5026
|
+
name: this.alias,
|
|
5027
|
+
isAlias: true
|
|
5028
|
+
};
|
|
5029
|
+
}
|
|
5030
|
+
if (prop === Table.Symbol.Columns) {
|
|
5031
|
+
const columns = target[Table.Symbol.Columns];
|
|
5032
|
+
if (!columns) {
|
|
5033
|
+
return columns;
|
|
5034
|
+
}
|
|
5035
|
+
const proxiedColumns = {};
|
|
5036
|
+
Object.keys(columns).map((key) => {
|
|
5037
|
+
proxiedColumns[key] = new Proxy(
|
|
5038
|
+
columns[key],
|
|
5039
|
+
new ColumnAliasProxyHandler(new Proxy(target, this))
|
|
5040
|
+
);
|
|
5041
|
+
});
|
|
5042
|
+
return proxiedColumns;
|
|
5043
|
+
}
|
|
5044
|
+
const value = target[prop];
|
|
5045
|
+
if (is(value, Column)) {
|
|
5046
|
+
return new Proxy(value, new ColumnAliasProxyHandler(new Proxy(target, this)));
|
|
5047
|
+
}
|
|
5048
|
+
return value;
|
|
5049
|
+
}
|
|
5050
|
+
}
|
|
5051
|
+
function aliasedTable(table, tableAlias) {
|
|
5052
|
+
return new Proxy(table, new TableAliasProxyHandler(tableAlias, false));
|
|
5053
|
+
}
|
|
5054
|
+
function aliasedTableColumn(column, tableAlias) {
|
|
5055
|
+
return new Proxy(
|
|
5056
|
+
column,
|
|
5057
|
+
new ColumnAliasProxyHandler(new Proxy(column.table, new TableAliasProxyHandler(tableAlias, false)))
|
|
5058
|
+
);
|
|
5059
|
+
}
|
|
5060
|
+
function mapColumnsInAliasedSQLToAlias(query, alias) {
|
|
5061
|
+
return new SQL.Aliased(mapColumnsInSQLToAlias(query.sql, alias), query.fieldAlias);
|
|
5062
|
+
}
|
|
5063
|
+
function mapColumnsInSQLToAlias(query, alias) {
|
|
5064
|
+
return sql.join(query.queryChunks.map((c) => {
|
|
5065
|
+
if (is(c, Column)) {
|
|
5066
|
+
return aliasedTableColumn(c, alias);
|
|
5067
|
+
}
|
|
5068
|
+
if (is(c, SQL)) {
|
|
5069
|
+
return mapColumnsInSQLToAlias(c, alias);
|
|
5070
|
+
}
|
|
5071
|
+
if (is(c, SQL.Aliased)) {
|
|
5072
|
+
return mapColumnsInAliasedSQLToAlias(c, alias);
|
|
5073
|
+
}
|
|
5074
|
+
return c;
|
|
5075
|
+
}));
|
|
5076
|
+
}
|
|
5077
|
+
|
|
5078
|
+
class CheckBuilder {
|
|
5079
|
+
constructor(name, value) {
|
|
5080
|
+
this.name = name;
|
|
5081
|
+
this.value = value;
|
|
5082
|
+
}
|
|
5083
|
+
static [entityKind] = "PgCheckBuilder";
|
|
5084
|
+
brand;
|
|
5085
|
+
/** @internal */
|
|
5086
|
+
build(table) {
|
|
5087
|
+
return new Check(table, this);
|
|
5088
|
+
}
|
|
5089
|
+
}
|
|
5090
|
+
class Check {
|
|
5091
|
+
constructor(table, builder) {
|
|
5092
|
+
this.table = table;
|
|
5093
|
+
this.name = builder.name;
|
|
5094
|
+
this.value = builder.value;
|
|
5095
|
+
}
|
|
5096
|
+
static [entityKind] = "PgCheck";
|
|
5097
|
+
name;
|
|
5098
|
+
value;
|
|
5099
|
+
}
|
|
5100
|
+
function check(name, value) {
|
|
5101
|
+
return new CheckBuilder(name, value);
|
|
5102
|
+
}
|
|
5103
|
+
|
|
5104
|
+
function orderSelectedFields(fields, pathPrefix) {
|
|
5105
|
+
return Object.entries(fields).reduce((result, [name, field]) => {
|
|
5106
|
+
if (typeof name !== "string") {
|
|
5107
|
+
return result;
|
|
5108
|
+
}
|
|
5109
|
+
const newPath = pathPrefix ? [...pathPrefix, name] : [name];
|
|
5110
|
+
if (is(field, Column) || is(field, SQL) || is(field, SQL.Aliased) || is(field, Subquery)) {
|
|
5111
|
+
result.push({ path: newPath, field });
|
|
5112
|
+
} else if (is(field, Table)) {
|
|
5113
|
+
result.push(...orderSelectedFields(field[Table.Symbol.Columns], newPath));
|
|
5114
|
+
} else {
|
|
5115
|
+
result.push(...orderSelectedFields(field, newPath));
|
|
5116
|
+
}
|
|
5117
|
+
return result;
|
|
5118
|
+
}, []);
|
|
5119
|
+
}
|
|
5120
|
+
function haveSameKeys(left, right) {
|
|
5121
|
+
const leftKeys = Object.keys(left);
|
|
5122
|
+
const rightKeys = Object.keys(right);
|
|
5123
|
+
if (leftKeys.length !== rightKeys.length) {
|
|
5124
|
+
return false;
|
|
5125
|
+
}
|
|
5126
|
+
for (const [index, key] of leftKeys.entries()) {
|
|
5127
|
+
if (key !== rightKeys[index]) {
|
|
5128
|
+
return false;
|
|
5129
|
+
}
|
|
5130
|
+
}
|
|
5131
|
+
return true;
|
|
5132
|
+
}
|
|
5133
|
+
function applyMixins(baseClass, extendedClasses) {
|
|
5134
|
+
for (const extendedClass of extendedClasses) {
|
|
5135
|
+
for (const name of Object.getOwnPropertyNames(extendedClass.prototype)) {
|
|
5136
|
+
if (name === "constructor") continue;
|
|
5137
|
+
Object.defineProperty(
|
|
5138
|
+
baseClass.prototype,
|
|
5139
|
+
name,
|
|
5140
|
+
Object.getOwnPropertyDescriptor(extendedClass.prototype, name) || /* @__PURE__ */ Object.create(null)
|
|
5141
|
+
);
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
5144
|
+
}
|
|
5145
|
+
function getTableColumns(table) {
|
|
5146
|
+
return table[Table.Symbol.Columns];
|
|
5147
|
+
}
|
|
5148
|
+
function getTableLikeName(table) {
|
|
5149
|
+
return is(table, Subquery) ? table._.alias : is(table, View) ? table[ViewBaseConfig].name : is(table, SQL) ? void 0 : table[Table.Symbol.IsAlias] ? table[Table.Symbol.Name] : table[Table.Symbol.BaseName];
|
|
5150
|
+
}
|
|
4911
5151
|
function getColumnNameAndConfig(a, b) {
|
|
4912
5152
|
return {
|
|
4913
5153
|
name: typeof a === "string" && a.length > 0 ? a : "",
|
|
@@ -5626,6 +5866,7 @@ function numeric(a, b) {
|
|
|
5626
5866
|
const mode = config?.mode;
|
|
5627
5867
|
return mode === "number" ? new PgNumericNumberBuilder(name, config?.precision, config?.scale) : mode === "bigint" ? new PgNumericBigIntBuilder(name, config?.precision, config?.scale) : new PgNumericBuilder(name, config?.precision, config?.scale);
|
|
5628
5868
|
}
|
|
5869
|
+
const decimal = numeric;
|
|
5629
5870
|
|
|
5630
5871
|
class PgPointTupleBuilder extends PgColumnBuilder {
|
|
5631
5872
|
static [entityKind] = "PgPointTupleBuilder";
|
|
@@ -6198,6 +6439,96 @@ function vector(a, b) {
|
|
|
6198
6439
|
return new PgVectorBuilder(name, config);
|
|
6199
6440
|
}
|
|
6200
6441
|
|
|
6442
|
+
class QueryPromise {
|
|
6443
|
+
static [entityKind] = "QueryPromise";
|
|
6444
|
+
[Symbol.toStringTag] = "QueryPromise";
|
|
6445
|
+
catch(onRejected) {
|
|
6446
|
+
return this.then(void 0, onRejected);
|
|
6447
|
+
}
|
|
6448
|
+
finally(onFinally) {
|
|
6449
|
+
return this.then(
|
|
6450
|
+
(value) => {
|
|
6451
|
+
onFinally?.();
|
|
6452
|
+
return value;
|
|
6453
|
+
},
|
|
6454
|
+
(reason) => {
|
|
6455
|
+
onFinally?.();
|
|
6456
|
+
throw reason;
|
|
6457
|
+
}
|
|
6458
|
+
);
|
|
6459
|
+
}
|
|
6460
|
+
then(onFulfilled, onRejected) {
|
|
6461
|
+
return this.execute().then(onFulfilled, onRejected);
|
|
6462
|
+
}
|
|
6463
|
+
}
|
|
6464
|
+
|
|
6465
|
+
class SelectionProxyHandler {
|
|
6466
|
+
static [entityKind] = "SelectionProxyHandler";
|
|
6467
|
+
config;
|
|
6468
|
+
constructor(config) {
|
|
6469
|
+
this.config = { ...config };
|
|
6470
|
+
}
|
|
6471
|
+
get(subquery, prop) {
|
|
6472
|
+
if (prop === "_") {
|
|
6473
|
+
return {
|
|
6474
|
+
...subquery["_"],
|
|
6475
|
+
selectedFields: new Proxy(
|
|
6476
|
+
subquery._.selectedFields,
|
|
6477
|
+
this
|
|
6478
|
+
)
|
|
6479
|
+
};
|
|
6480
|
+
}
|
|
6481
|
+
if (prop === ViewBaseConfig) {
|
|
6482
|
+
return {
|
|
6483
|
+
...subquery[ViewBaseConfig],
|
|
6484
|
+
selectedFields: new Proxy(
|
|
6485
|
+
subquery[ViewBaseConfig].selectedFields,
|
|
6486
|
+
this
|
|
6487
|
+
)
|
|
6488
|
+
};
|
|
6489
|
+
}
|
|
6490
|
+
if (typeof prop === "symbol") {
|
|
6491
|
+
return subquery[prop];
|
|
6492
|
+
}
|
|
6493
|
+
const columns = is(subquery, Subquery) ? subquery._.selectedFields : is(subquery, View) ? subquery[ViewBaseConfig].selectedFields : subquery;
|
|
6494
|
+
const value = columns[prop];
|
|
6495
|
+
if (is(value, SQL.Aliased)) {
|
|
6496
|
+
if (this.config.sqlAliasedBehavior === "sql" && !value.isSelectionField) {
|
|
6497
|
+
return value.sql;
|
|
6498
|
+
}
|
|
6499
|
+
const newValue = value.clone();
|
|
6500
|
+
newValue.isSelectionField = true;
|
|
6501
|
+
return newValue;
|
|
6502
|
+
}
|
|
6503
|
+
if (is(value, SQL)) {
|
|
6504
|
+
if (this.config.sqlBehavior === "sql") {
|
|
6505
|
+
return value;
|
|
6506
|
+
}
|
|
6507
|
+
throw new Error(
|
|
6508
|
+
`You tried to reference "${prop}" field from a subquery, which is a raw SQL field, but it doesn't have an alias declared. Please add an alias to the field using ".as('alias')" method.`
|
|
6509
|
+
);
|
|
6510
|
+
}
|
|
6511
|
+
if (is(value, Column)) {
|
|
6512
|
+
if (this.config.alias) {
|
|
6513
|
+
return new Proxy(
|
|
6514
|
+
value,
|
|
6515
|
+
new ColumnAliasProxyHandler(
|
|
6516
|
+
new Proxy(
|
|
6517
|
+
value.table,
|
|
6518
|
+
new TableAliasProxyHandler(this.config.alias, this.config.replaceOriginalName ?? false)
|
|
6519
|
+
)
|
|
6520
|
+
)
|
|
6521
|
+
);
|
|
6522
|
+
}
|
|
6523
|
+
return value;
|
|
6524
|
+
}
|
|
6525
|
+
if (typeof value !== "object" || value === null) {
|
|
6526
|
+
return value;
|
|
6527
|
+
}
|
|
6528
|
+
return new Proxy(value, new SelectionProxyHandler(this.config));
|
|
6529
|
+
}
|
|
6530
|
+
}
|
|
6531
|
+
|
|
6201
6532
|
function getPgColumnBuilders() {
|
|
6202
6533
|
return {
|
|
6203
6534
|
bigint,
|
|
@@ -6290,4 +6621,2785 @@ const pgTable = (name, columns, extraConfig) => {
|
|
|
6290
6621
|
return pgTableWithSchema(name, columns, extraConfig, void 0);
|
|
6291
6622
|
};
|
|
6292
6623
|
|
|
6293
|
-
|
|
6624
|
+
class IndexBuilderOn {
|
|
6625
|
+
constructor(unique, name) {
|
|
6626
|
+
this.unique = unique;
|
|
6627
|
+
this.name = name;
|
|
6628
|
+
}
|
|
6629
|
+
static [entityKind] = "PgIndexBuilderOn";
|
|
6630
|
+
on(...columns) {
|
|
6631
|
+
return new IndexBuilder(
|
|
6632
|
+
columns.map((it) => {
|
|
6633
|
+
if (is(it, SQL)) {
|
|
6634
|
+
return it;
|
|
6635
|
+
}
|
|
6636
|
+
it = it;
|
|
6637
|
+
const clonedIndexedColumn = new IndexedColumn(it.name, !!it.keyAsName, it.columnType, it.indexConfig);
|
|
6638
|
+
it.indexConfig = JSON.parse(JSON.stringify(it.defaultConfig));
|
|
6639
|
+
return clonedIndexedColumn;
|
|
6640
|
+
}),
|
|
6641
|
+
this.unique,
|
|
6642
|
+
false,
|
|
6643
|
+
this.name
|
|
6644
|
+
);
|
|
6645
|
+
}
|
|
6646
|
+
onOnly(...columns) {
|
|
6647
|
+
return new IndexBuilder(
|
|
6648
|
+
columns.map((it) => {
|
|
6649
|
+
if (is(it, SQL)) {
|
|
6650
|
+
return it;
|
|
6651
|
+
}
|
|
6652
|
+
it = it;
|
|
6653
|
+
const clonedIndexedColumn = new IndexedColumn(it.name, !!it.keyAsName, it.columnType, it.indexConfig);
|
|
6654
|
+
it.indexConfig = it.defaultConfig;
|
|
6655
|
+
return clonedIndexedColumn;
|
|
6656
|
+
}),
|
|
6657
|
+
this.unique,
|
|
6658
|
+
true,
|
|
6659
|
+
this.name
|
|
6660
|
+
);
|
|
6661
|
+
}
|
|
6662
|
+
/**
|
|
6663
|
+
* Specify what index method to use. Choices are `btree`, `hash`, `gist`, `spgist`, `gin`, `brin`, or user-installed access methods like `bloom`. The default method is `btree.
|
|
6664
|
+
*
|
|
6665
|
+
* If you have the `pg_vector` extension installed in your database, you can use the `hnsw` and `ivfflat` options, which are predefined types.
|
|
6666
|
+
*
|
|
6667
|
+
* **You can always specify any string you want in the method, in case Drizzle doesn't have it natively in its types**
|
|
6668
|
+
*
|
|
6669
|
+
* @param method The name of the index method to be used
|
|
6670
|
+
* @param columns
|
|
6671
|
+
* @returns
|
|
6672
|
+
*/
|
|
6673
|
+
using(method, ...columns) {
|
|
6674
|
+
return new IndexBuilder(
|
|
6675
|
+
columns.map((it) => {
|
|
6676
|
+
if (is(it, SQL)) {
|
|
6677
|
+
return it;
|
|
6678
|
+
}
|
|
6679
|
+
it = it;
|
|
6680
|
+
const clonedIndexedColumn = new IndexedColumn(it.name, !!it.keyAsName, it.columnType, it.indexConfig);
|
|
6681
|
+
it.indexConfig = JSON.parse(JSON.stringify(it.defaultConfig));
|
|
6682
|
+
return clonedIndexedColumn;
|
|
6683
|
+
}),
|
|
6684
|
+
this.unique,
|
|
6685
|
+
true,
|
|
6686
|
+
this.name,
|
|
6687
|
+
method
|
|
6688
|
+
);
|
|
6689
|
+
}
|
|
6690
|
+
}
|
|
6691
|
+
class IndexBuilder {
|
|
6692
|
+
static [entityKind] = "PgIndexBuilder";
|
|
6693
|
+
/** @internal */
|
|
6694
|
+
config;
|
|
6695
|
+
constructor(columns, unique, only, name, method = "btree") {
|
|
6696
|
+
this.config = {
|
|
6697
|
+
name,
|
|
6698
|
+
columns,
|
|
6699
|
+
unique,
|
|
6700
|
+
only,
|
|
6701
|
+
method
|
|
6702
|
+
};
|
|
6703
|
+
}
|
|
6704
|
+
concurrently() {
|
|
6705
|
+
this.config.concurrently = true;
|
|
6706
|
+
return this;
|
|
6707
|
+
}
|
|
6708
|
+
with(obj) {
|
|
6709
|
+
this.config.with = obj;
|
|
6710
|
+
return this;
|
|
6711
|
+
}
|
|
6712
|
+
where(condition) {
|
|
6713
|
+
this.config.where = condition;
|
|
6714
|
+
return this;
|
|
6715
|
+
}
|
|
6716
|
+
/** @internal */
|
|
6717
|
+
build(table) {
|
|
6718
|
+
return new Index(this.config, table);
|
|
6719
|
+
}
|
|
6720
|
+
}
|
|
6721
|
+
class Index {
|
|
6722
|
+
static [entityKind] = "PgIndex";
|
|
6723
|
+
config;
|
|
6724
|
+
constructor(config, table) {
|
|
6725
|
+
this.config = { ...config, table };
|
|
6726
|
+
}
|
|
6727
|
+
}
|
|
6728
|
+
function index(name) {
|
|
6729
|
+
return new IndexBuilderOn(false, name);
|
|
6730
|
+
}
|
|
6731
|
+
function uniqueIndex(name) {
|
|
6732
|
+
return new IndexBuilderOn(true, name);
|
|
6733
|
+
}
|
|
6734
|
+
|
|
6735
|
+
function primaryKey(...config) {
|
|
6736
|
+
if (config[0].columns) {
|
|
6737
|
+
return new PrimaryKeyBuilder(config[0].columns, config[0].name);
|
|
6738
|
+
}
|
|
6739
|
+
return new PrimaryKeyBuilder(config);
|
|
6740
|
+
}
|
|
6741
|
+
class PrimaryKeyBuilder {
|
|
6742
|
+
static [entityKind] = "PgPrimaryKeyBuilder";
|
|
6743
|
+
/** @internal */
|
|
6744
|
+
columns;
|
|
6745
|
+
/** @internal */
|
|
6746
|
+
name;
|
|
6747
|
+
constructor(columns, name) {
|
|
6748
|
+
this.columns = columns;
|
|
6749
|
+
this.name = name;
|
|
6750
|
+
}
|
|
6751
|
+
/** @internal */
|
|
6752
|
+
build(table) {
|
|
6753
|
+
return new PrimaryKey(table, this.columns, this.name);
|
|
6754
|
+
}
|
|
6755
|
+
}
|
|
6756
|
+
class PrimaryKey {
|
|
6757
|
+
constructor(table, columns, name) {
|
|
6758
|
+
this.table = table;
|
|
6759
|
+
this.columns = columns;
|
|
6760
|
+
this.name = name;
|
|
6761
|
+
}
|
|
6762
|
+
static [entityKind] = "PgPrimaryKey";
|
|
6763
|
+
columns;
|
|
6764
|
+
name;
|
|
6765
|
+
getName() {
|
|
6766
|
+
return this.name ?? `${this.table[PgTable.Symbol.Name]}_${this.columns.map((column) => column.name).join("_")}_pk`;
|
|
6767
|
+
}
|
|
6768
|
+
}
|
|
6769
|
+
|
|
6770
|
+
const PgViewConfig = Symbol.for("drizzle:PgViewConfig");
|
|
6771
|
+
|
|
6772
|
+
function toSnakeCase(input) {
|
|
6773
|
+
const words = input.replace(/['\u2019]/g, "").match(/[\da-z]+|[A-Z]+(?![a-z])|[A-Z][\da-z]+/g) ?? [];
|
|
6774
|
+
return words.map((word) => word.toLowerCase()).join("_");
|
|
6775
|
+
}
|
|
6776
|
+
function toCamelCase(input) {
|
|
6777
|
+
const words = input.replace(/['\u2019]/g, "").match(/[\da-z]+|[A-Z]+(?![a-z])|[A-Z][\da-z]+/g) ?? [];
|
|
6778
|
+
return words.reduce((acc, word, i) => {
|
|
6779
|
+
const formattedWord = i === 0 ? word.toLowerCase() : `${word[0].toUpperCase()}${word.slice(1)}`;
|
|
6780
|
+
return acc + formattedWord;
|
|
6781
|
+
}, "");
|
|
6782
|
+
}
|
|
6783
|
+
function noopCase(input) {
|
|
6784
|
+
return input;
|
|
6785
|
+
}
|
|
6786
|
+
class CasingCache {
|
|
6787
|
+
static [entityKind] = "CasingCache";
|
|
6788
|
+
/** @internal */
|
|
6789
|
+
cache = {};
|
|
6790
|
+
cachedTables = {};
|
|
6791
|
+
convert;
|
|
6792
|
+
constructor(casing) {
|
|
6793
|
+
this.convert = casing === "snake_case" ? toSnakeCase : casing === "camelCase" ? toCamelCase : noopCase;
|
|
6794
|
+
}
|
|
6795
|
+
getColumnCasing(column) {
|
|
6796
|
+
if (!column.keyAsName) return column.name;
|
|
6797
|
+
const schema = column.table[Table.Symbol.Schema] ?? "public";
|
|
6798
|
+
const tableName = column.table[Table.Symbol.OriginalName];
|
|
6799
|
+
const key = `${schema}.${tableName}.${column.name}`;
|
|
6800
|
+
if (!this.cache[key]) {
|
|
6801
|
+
this.cacheTable(column.table);
|
|
6802
|
+
}
|
|
6803
|
+
return this.cache[key];
|
|
6804
|
+
}
|
|
6805
|
+
cacheTable(table) {
|
|
6806
|
+
const schema = table[Table.Symbol.Schema] ?? "public";
|
|
6807
|
+
const tableName = table[Table.Symbol.OriginalName];
|
|
6808
|
+
const tableKey = `${schema}.${tableName}`;
|
|
6809
|
+
if (!this.cachedTables[tableKey]) {
|
|
6810
|
+
for (const column of Object.values(table[Table.Symbol.Columns])) {
|
|
6811
|
+
const columnKey = `${tableKey}.${column.name}`;
|
|
6812
|
+
this.cache[columnKey] = this.convert(column.name);
|
|
6813
|
+
}
|
|
6814
|
+
this.cachedTables[tableKey] = true;
|
|
6815
|
+
}
|
|
6816
|
+
}
|
|
6817
|
+
clearCache() {
|
|
6818
|
+
this.cache = {};
|
|
6819
|
+
this.cachedTables = {};
|
|
6820
|
+
}
|
|
6821
|
+
}
|
|
6822
|
+
|
|
6823
|
+
class DrizzleError extends Error {
|
|
6824
|
+
static [entityKind] = "DrizzleError";
|
|
6825
|
+
constructor({ message, cause }) {
|
|
6826
|
+
super(message);
|
|
6827
|
+
this.name = "DrizzleError";
|
|
6828
|
+
this.cause = cause;
|
|
6829
|
+
}
|
|
6830
|
+
}
|
|
6831
|
+
|
|
6832
|
+
function bindIfParam(value, column) {
|
|
6833
|
+
if (isDriverValueEncoder(column) && !isSQLWrapper(value) && !is(value, Param) && !is(value, Placeholder) && !is(value, Column) && !is(value, Table) && !is(value, View)) {
|
|
6834
|
+
return new Param(value, column);
|
|
6835
|
+
}
|
|
6836
|
+
return value;
|
|
6837
|
+
}
|
|
6838
|
+
const eq = (left, right) => {
|
|
6839
|
+
return sql`${left} = ${bindIfParam(right, left)}`;
|
|
6840
|
+
};
|
|
6841
|
+
const ne = (left, right) => {
|
|
6842
|
+
return sql`${left} <> ${bindIfParam(right, left)}`;
|
|
6843
|
+
};
|
|
6844
|
+
function and(...unfilteredConditions) {
|
|
6845
|
+
const conditions = unfilteredConditions.filter(
|
|
6846
|
+
(c) => c !== void 0
|
|
6847
|
+
);
|
|
6848
|
+
if (conditions.length === 0) {
|
|
6849
|
+
return void 0;
|
|
6850
|
+
}
|
|
6851
|
+
if (conditions.length === 1) {
|
|
6852
|
+
return new SQL(conditions);
|
|
6853
|
+
}
|
|
6854
|
+
return new SQL([
|
|
6855
|
+
new StringChunk("("),
|
|
6856
|
+
sql.join(conditions, new StringChunk(" and ")),
|
|
6857
|
+
new StringChunk(")")
|
|
6858
|
+
]);
|
|
6859
|
+
}
|
|
6860
|
+
function or(...unfilteredConditions) {
|
|
6861
|
+
const conditions = unfilteredConditions.filter(
|
|
6862
|
+
(c) => c !== void 0
|
|
6863
|
+
);
|
|
6864
|
+
if (conditions.length === 0) {
|
|
6865
|
+
return void 0;
|
|
6866
|
+
}
|
|
6867
|
+
if (conditions.length === 1) {
|
|
6868
|
+
return new SQL(conditions);
|
|
6869
|
+
}
|
|
6870
|
+
return new SQL([
|
|
6871
|
+
new StringChunk("("),
|
|
6872
|
+
sql.join(conditions, new StringChunk(" or ")),
|
|
6873
|
+
new StringChunk(")")
|
|
6874
|
+
]);
|
|
6875
|
+
}
|
|
6876
|
+
function not(condition) {
|
|
6877
|
+
return sql`not ${condition}`;
|
|
6878
|
+
}
|
|
6879
|
+
const gt = (left, right) => {
|
|
6880
|
+
return sql`${left} > ${bindIfParam(right, left)}`;
|
|
6881
|
+
};
|
|
6882
|
+
const gte = (left, right) => {
|
|
6883
|
+
return sql`${left} >= ${bindIfParam(right, left)}`;
|
|
6884
|
+
};
|
|
6885
|
+
const lt = (left, right) => {
|
|
6886
|
+
return sql`${left} < ${bindIfParam(right, left)}`;
|
|
6887
|
+
};
|
|
6888
|
+
const lte = (left, right) => {
|
|
6889
|
+
return sql`${left} <= ${bindIfParam(right, left)}`;
|
|
6890
|
+
};
|
|
6891
|
+
function inArray(column, values) {
|
|
6892
|
+
if (Array.isArray(values)) {
|
|
6893
|
+
if (values.length === 0) {
|
|
6894
|
+
return sql`false`;
|
|
6895
|
+
}
|
|
6896
|
+
return sql`${column} in ${values.map((v) => bindIfParam(v, column))}`;
|
|
6897
|
+
}
|
|
6898
|
+
return sql`${column} in ${bindIfParam(values, column)}`;
|
|
6899
|
+
}
|
|
6900
|
+
function notInArray(column, values) {
|
|
6901
|
+
if (Array.isArray(values)) {
|
|
6902
|
+
if (values.length === 0) {
|
|
6903
|
+
return sql`true`;
|
|
6904
|
+
}
|
|
6905
|
+
return sql`${column} not in ${values.map((v) => bindIfParam(v, column))}`;
|
|
6906
|
+
}
|
|
6907
|
+
return sql`${column} not in ${bindIfParam(values, column)}`;
|
|
6908
|
+
}
|
|
6909
|
+
function isNull(value) {
|
|
6910
|
+
return sql`${value} is null`;
|
|
6911
|
+
}
|
|
6912
|
+
function isNotNull(value) {
|
|
6913
|
+
return sql`${value} is not null`;
|
|
6914
|
+
}
|
|
6915
|
+
function exists(subquery) {
|
|
6916
|
+
return sql`exists ${subquery}`;
|
|
6917
|
+
}
|
|
6918
|
+
function notExists(subquery) {
|
|
6919
|
+
return sql`not exists ${subquery}`;
|
|
6920
|
+
}
|
|
6921
|
+
function between(column, min, max) {
|
|
6922
|
+
return sql`${column} between ${bindIfParam(min, column)} and ${bindIfParam(
|
|
6923
|
+
max,
|
|
6924
|
+
column
|
|
6925
|
+
)}`;
|
|
6926
|
+
}
|
|
6927
|
+
function notBetween(column, min, max) {
|
|
6928
|
+
return sql`${column} not between ${bindIfParam(
|
|
6929
|
+
min,
|
|
6930
|
+
column
|
|
6931
|
+
)} and ${bindIfParam(max, column)}`;
|
|
6932
|
+
}
|
|
6933
|
+
function like(column, value) {
|
|
6934
|
+
return sql`${column} like ${value}`;
|
|
6935
|
+
}
|
|
6936
|
+
function notLike(column, value) {
|
|
6937
|
+
return sql`${column} not like ${value}`;
|
|
6938
|
+
}
|
|
6939
|
+
function ilike(column, value) {
|
|
6940
|
+
return sql`${column} ilike ${value}`;
|
|
6941
|
+
}
|
|
6942
|
+
function notIlike(column, value) {
|
|
6943
|
+
return sql`${column} not ilike ${value}`;
|
|
6944
|
+
}
|
|
6945
|
+
|
|
6946
|
+
function asc(column) {
|
|
6947
|
+
return sql`${column} asc`;
|
|
6948
|
+
}
|
|
6949
|
+
function desc(column) {
|
|
6950
|
+
return sql`${column} desc`;
|
|
6951
|
+
}
|
|
6952
|
+
|
|
6953
|
+
class Relation {
|
|
6954
|
+
constructor(sourceTable, referencedTable, relationName) {
|
|
6955
|
+
this.sourceTable = sourceTable;
|
|
6956
|
+
this.referencedTable = referencedTable;
|
|
6957
|
+
this.relationName = relationName;
|
|
6958
|
+
this.referencedTableName = referencedTable[Table.Symbol.Name];
|
|
6959
|
+
}
|
|
6960
|
+
static [entityKind] = "Relation";
|
|
6961
|
+
referencedTableName;
|
|
6962
|
+
fieldName;
|
|
6963
|
+
}
|
|
6964
|
+
class One extends Relation {
|
|
6965
|
+
constructor(sourceTable, referencedTable, config, isNullable) {
|
|
6966
|
+
super(sourceTable, referencedTable, config?.relationName);
|
|
6967
|
+
this.config = config;
|
|
6968
|
+
this.isNullable = isNullable;
|
|
6969
|
+
}
|
|
6970
|
+
static [entityKind] = "One";
|
|
6971
|
+
withFieldName(fieldName) {
|
|
6972
|
+
const relation = new One(
|
|
6973
|
+
this.sourceTable,
|
|
6974
|
+
this.referencedTable,
|
|
6975
|
+
this.config,
|
|
6976
|
+
this.isNullable
|
|
6977
|
+
);
|
|
6978
|
+
relation.fieldName = fieldName;
|
|
6979
|
+
return relation;
|
|
6980
|
+
}
|
|
6981
|
+
}
|
|
6982
|
+
class Many extends Relation {
|
|
6983
|
+
constructor(sourceTable, referencedTable, config) {
|
|
6984
|
+
super(sourceTable, referencedTable, config?.relationName);
|
|
6985
|
+
this.config = config;
|
|
6986
|
+
}
|
|
6987
|
+
static [entityKind] = "Many";
|
|
6988
|
+
withFieldName(fieldName) {
|
|
6989
|
+
const relation = new Many(
|
|
6990
|
+
this.sourceTable,
|
|
6991
|
+
this.referencedTable,
|
|
6992
|
+
this.config
|
|
6993
|
+
);
|
|
6994
|
+
relation.fieldName = fieldName;
|
|
6995
|
+
return relation;
|
|
6996
|
+
}
|
|
6997
|
+
}
|
|
6998
|
+
function getOperators() {
|
|
6999
|
+
return {
|
|
7000
|
+
and,
|
|
7001
|
+
between,
|
|
7002
|
+
eq,
|
|
7003
|
+
exists,
|
|
7004
|
+
gt,
|
|
7005
|
+
gte,
|
|
7006
|
+
ilike,
|
|
7007
|
+
inArray,
|
|
7008
|
+
isNull,
|
|
7009
|
+
isNotNull,
|
|
7010
|
+
like,
|
|
7011
|
+
lt,
|
|
7012
|
+
lte,
|
|
7013
|
+
ne,
|
|
7014
|
+
not,
|
|
7015
|
+
notBetween,
|
|
7016
|
+
notExists,
|
|
7017
|
+
notLike,
|
|
7018
|
+
notIlike,
|
|
7019
|
+
notInArray,
|
|
7020
|
+
or,
|
|
7021
|
+
sql
|
|
7022
|
+
};
|
|
7023
|
+
}
|
|
7024
|
+
function getOrderByOperators() {
|
|
7025
|
+
return {
|
|
7026
|
+
sql,
|
|
7027
|
+
asc,
|
|
7028
|
+
desc
|
|
7029
|
+
};
|
|
7030
|
+
}
|
|
7031
|
+
function normalizeRelation(schema, tableNamesMap, relation) {
|
|
7032
|
+
if (is(relation, One) && relation.config) {
|
|
7033
|
+
return {
|
|
7034
|
+
fields: relation.config.fields,
|
|
7035
|
+
references: relation.config.references
|
|
7036
|
+
};
|
|
7037
|
+
}
|
|
7038
|
+
const referencedTableTsName = tableNamesMap[getTableUniqueName(relation.referencedTable)];
|
|
7039
|
+
if (!referencedTableTsName) {
|
|
7040
|
+
throw new Error(
|
|
7041
|
+
`Table "${relation.referencedTable[Table.Symbol.Name]}" not found in schema`
|
|
7042
|
+
);
|
|
7043
|
+
}
|
|
7044
|
+
const referencedTableConfig = schema[referencedTableTsName];
|
|
7045
|
+
if (!referencedTableConfig) {
|
|
7046
|
+
throw new Error(`Table "${referencedTableTsName}" not found in schema`);
|
|
7047
|
+
}
|
|
7048
|
+
const sourceTable = relation.sourceTable;
|
|
7049
|
+
const sourceTableTsName = tableNamesMap[getTableUniqueName(sourceTable)];
|
|
7050
|
+
if (!sourceTableTsName) {
|
|
7051
|
+
throw new Error(
|
|
7052
|
+
`Table "${sourceTable[Table.Symbol.Name]}" not found in schema`
|
|
7053
|
+
);
|
|
7054
|
+
}
|
|
7055
|
+
const reverseRelations = [];
|
|
7056
|
+
for (const referencedTableRelation of Object.values(
|
|
7057
|
+
referencedTableConfig.relations
|
|
7058
|
+
)) {
|
|
7059
|
+
if (relation.relationName && relation !== referencedTableRelation && referencedTableRelation.relationName === relation.relationName || !relation.relationName && referencedTableRelation.referencedTable === relation.sourceTable) {
|
|
7060
|
+
reverseRelations.push(referencedTableRelation);
|
|
7061
|
+
}
|
|
7062
|
+
}
|
|
7063
|
+
if (reverseRelations.length > 1) {
|
|
7064
|
+
throw relation.relationName ? new Error(
|
|
7065
|
+
`There are multiple relations with name "${relation.relationName}" in table "${referencedTableTsName}"`
|
|
7066
|
+
) : new Error(
|
|
7067
|
+
`There are multiple relations between "${referencedTableTsName}" and "${relation.sourceTable[Table.Symbol.Name]}". Please specify relation name`
|
|
7068
|
+
);
|
|
7069
|
+
}
|
|
7070
|
+
if (reverseRelations[0] && is(reverseRelations[0], One) && reverseRelations[0].config) {
|
|
7071
|
+
return {
|
|
7072
|
+
fields: reverseRelations[0].config.references,
|
|
7073
|
+
references: reverseRelations[0].config.fields
|
|
7074
|
+
};
|
|
7075
|
+
}
|
|
7076
|
+
throw new Error(
|
|
7077
|
+
`There is not enough information to infer relation "${sourceTableTsName}.${relation.fieldName}"`
|
|
7078
|
+
);
|
|
7079
|
+
}
|
|
7080
|
+
|
|
7081
|
+
class PgViewBase extends View {
|
|
7082
|
+
static [entityKind] = "PgViewBase";
|
|
7083
|
+
}
|
|
7084
|
+
|
|
7085
|
+
class PgDialect {
|
|
7086
|
+
static [entityKind] = "PgDialect";
|
|
7087
|
+
/** @internal */
|
|
7088
|
+
casing;
|
|
7089
|
+
constructor(config) {
|
|
7090
|
+
this.casing = new CasingCache(config?.casing);
|
|
7091
|
+
}
|
|
7092
|
+
async migrate(migrations, session, config) {
|
|
7093
|
+
const migrationsTable = typeof config === "string" ? "__drizzle_migrations" : config.migrationsTable ?? "__drizzle_migrations";
|
|
7094
|
+
const migrationsSchema = typeof config === "string" ? "drizzle" : config.migrationsSchema ?? "drizzle";
|
|
7095
|
+
const migrationTableCreate = sql`
|
|
7096
|
+
CREATE TABLE IF NOT EXISTS ${sql.identifier(migrationsSchema)}.${sql.identifier(migrationsTable)} (
|
|
7097
|
+
id SERIAL PRIMARY KEY,
|
|
7098
|
+
hash text NOT NULL,
|
|
7099
|
+
created_at bigint
|
|
7100
|
+
)
|
|
7101
|
+
`;
|
|
7102
|
+
await session.execute(sql`CREATE SCHEMA IF NOT EXISTS ${sql.identifier(migrationsSchema)}`);
|
|
7103
|
+
await session.execute(migrationTableCreate);
|
|
7104
|
+
const dbMigrations = await session.all(
|
|
7105
|
+
sql`select id, hash, created_at from ${sql.identifier(migrationsSchema)}.${sql.identifier(migrationsTable)} order by created_at desc limit 1`
|
|
7106
|
+
);
|
|
7107
|
+
const lastDbMigration = dbMigrations[0];
|
|
7108
|
+
await session.transaction(async (tx) => {
|
|
7109
|
+
for await (const migration of migrations) {
|
|
7110
|
+
if (!lastDbMigration || Number(lastDbMigration.created_at) < migration.folderMillis) {
|
|
7111
|
+
for (const stmt of migration.sql) {
|
|
7112
|
+
await tx.execute(sql.raw(stmt));
|
|
7113
|
+
}
|
|
7114
|
+
await tx.execute(
|
|
7115
|
+
sql`insert into ${sql.identifier(migrationsSchema)}.${sql.identifier(migrationsTable)} ("hash", "created_at") values(${migration.hash}, ${migration.folderMillis})`
|
|
7116
|
+
);
|
|
7117
|
+
}
|
|
7118
|
+
}
|
|
7119
|
+
});
|
|
7120
|
+
}
|
|
7121
|
+
escapeName(name) {
|
|
7122
|
+
return `"${name}"`;
|
|
7123
|
+
}
|
|
7124
|
+
escapeParam(num) {
|
|
7125
|
+
return `$${num + 1}`;
|
|
7126
|
+
}
|
|
7127
|
+
escapeString(str) {
|
|
7128
|
+
return `'${str.replace(/'/g, "''")}'`;
|
|
7129
|
+
}
|
|
7130
|
+
buildWithCTE(queries) {
|
|
7131
|
+
if (!queries?.length) return void 0;
|
|
7132
|
+
const withSqlChunks = [sql`with `];
|
|
7133
|
+
for (const [i, w] of queries.entries()) {
|
|
7134
|
+
withSqlChunks.push(sql`${sql.identifier(w._.alias)} as (${w._.sql})`);
|
|
7135
|
+
if (i < queries.length - 1) {
|
|
7136
|
+
withSqlChunks.push(sql`, `);
|
|
7137
|
+
}
|
|
7138
|
+
}
|
|
7139
|
+
withSqlChunks.push(sql` `);
|
|
7140
|
+
return sql.join(withSqlChunks);
|
|
7141
|
+
}
|
|
7142
|
+
buildDeleteQuery({ table, where, returning, withList }) {
|
|
7143
|
+
const withSql = this.buildWithCTE(withList);
|
|
7144
|
+
const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;
|
|
7145
|
+
const whereSql = where ? sql` where ${where}` : void 0;
|
|
7146
|
+
return sql`${withSql}delete from ${table}${whereSql}${returningSql}`;
|
|
7147
|
+
}
|
|
7148
|
+
buildUpdateSet(table, set) {
|
|
7149
|
+
const tableColumns = table[Table.Symbol.Columns];
|
|
7150
|
+
const columnNames = Object.keys(tableColumns).filter(
|
|
7151
|
+
(colName) => set[colName] !== void 0 || tableColumns[colName]?.onUpdateFn !== void 0
|
|
7152
|
+
);
|
|
7153
|
+
const setSize = columnNames.length;
|
|
7154
|
+
return sql.join(columnNames.flatMap((colName, i) => {
|
|
7155
|
+
const col = tableColumns[colName];
|
|
7156
|
+
const onUpdateFnResult = col.onUpdateFn?.();
|
|
7157
|
+
const value = set[colName] ?? (is(onUpdateFnResult, SQL) ? onUpdateFnResult : sql.param(onUpdateFnResult, col));
|
|
7158
|
+
const res = sql`${sql.identifier(this.casing.getColumnCasing(col))} = ${value}`;
|
|
7159
|
+
if (i < setSize - 1) {
|
|
7160
|
+
return [res, sql.raw(", ")];
|
|
7161
|
+
}
|
|
7162
|
+
return [res];
|
|
7163
|
+
}));
|
|
7164
|
+
}
|
|
7165
|
+
buildUpdateQuery({ table, set, where, returning, withList, from, joins }) {
|
|
7166
|
+
const withSql = this.buildWithCTE(withList);
|
|
7167
|
+
const tableName = table[PgTable.Symbol.Name];
|
|
7168
|
+
const tableSchema = table[PgTable.Symbol.Schema];
|
|
7169
|
+
const origTableName = table[PgTable.Symbol.OriginalName];
|
|
7170
|
+
const alias = tableName === origTableName ? void 0 : tableName;
|
|
7171
|
+
const tableSql = sql`${tableSchema ? sql`${sql.identifier(tableSchema)}.` : void 0}${sql.identifier(origTableName)}${alias && sql` ${sql.identifier(alias)}`}`;
|
|
7172
|
+
const setSql = this.buildUpdateSet(table, set);
|
|
7173
|
+
const fromSql = from && sql.join([sql.raw(" from "), this.buildFromTable(from)]);
|
|
7174
|
+
const joinsSql = this.buildJoins(joins);
|
|
7175
|
+
const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: !from })}` : void 0;
|
|
7176
|
+
const whereSql = where ? sql` where ${where}` : void 0;
|
|
7177
|
+
return sql`${withSql}update ${tableSql} set ${setSql}${fromSql}${joinsSql}${whereSql}${returningSql}`;
|
|
7178
|
+
}
|
|
7179
|
+
/**
|
|
7180
|
+
* Builds selection SQL with provided fields/expressions
|
|
7181
|
+
*
|
|
7182
|
+
* Examples:
|
|
7183
|
+
*
|
|
7184
|
+
* `select <selection> from`
|
|
7185
|
+
*
|
|
7186
|
+
* `insert ... returning <selection>`
|
|
7187
|
+
*
|
|
7188
|
+
* If `isSingleTable` is true, then columns won't be prefixed with table name
|
|
7189
|
+
*/
|
|
7190
|
+
buildSelection(fields, { isSingleTable = false } = {}) {
|
|
7191
|
+
const columnsLen = fields.length;
|
|
7192
|
+
const chunks = fields.flatMap(({ field }, i) => {
|
|
7193
|
+
const chunk = [];
|
|
7194
|
+
if (is(field, SQL.Aliased) && field.isSelectionField) {
|
|
7195
|
+
chunk.push(sql.identifier(field.fieldAlias));
|
|
7196
|
+
} else if (is(field, SQL.Aliased) || is(field, SQL)) {
|
|
7197
|
+
const query = is(field, SQL.Aliased) ? field.sql : field;
|
|
7198
|
+
if (isSingleTable) {
|
|
7199
|
+
chunk.push(
|
|
7200
|
+
new SQL(
|
|
7201
|
+
query.queryChunks.map((c) => {
|
|
7202
|
+
if (is(c, PgColumn)) {
|
|
7203
|
+
return sql.identifier(this.casing.getColumnCasing(c));
|
|
7204
|
+
}
|
|
7205
|
+
return c;
|
|
7206
|
+
})
|
|
7207
|
+
)
|
|
7208
|
+
);
|
|
7209
|
+
} else {
|
|
7210
|
+
chunk.push(query);
|
|
7211
|
+
}
|
|
7212
|
+
if (is(field, SQL.Aliased)) {
|
|
7213
|
+
chunk.push(sql` as ${sql.identifier(field.fieldAlias)}`);
|
|
7214
|
+
}
|
|
7215
|
+
} else if (is(field, Column)) {
|
|
7216
|
+
if (isSingleTable) {
|
|
7217
|
+
chunk.push(sql.identifier(this.casing.getColumnCasing(field)));
|
|
7218
|
+
} else {
|
|
7219
|
+
chunk.push(field);
|
|
7220
|
+
}
|
|
7221
|
+
} else if (is(field, Subquery)) {
|
|
7222
|
+
const entries = Object.entries(field._.selectedFields);
|
|
7223
|
+
if (entries.length === 1) {
|
|
7224
|
+
const entry = entries[0][1];
|
|
7225
|
+
const fieldDecoder = is(entry, SQL) ? entry.decoder : is(entry, Column) ? { mapFromDriverValue: (v) => entry.mapFromDriverValue(v) } : entry.sql.decoder;
|
|
7226
|
+
if (fieldDecoder) {
|
|
7227
|
+
field._.sql.decoder = fieldDecoder;
|
|
7228
|
+
}
|
|
7229
|
+
}
|
|
7230
|
+
chunk.push(field);
|
|
7231
|
+
}
|
|
7232
|
+
if (i < columnsLen - 1) {
|
|
7233
|
+
chunk.push(sql`, `);
|
|
7234
|
+
}
|
|
7235
|
+
return chunk;
|
|
7236
|
+
});
|
|
7237
|
+
return sql.join(chunks);
|
|
7238
|
+
}
|
|
7239
|
+
buildJoins(joins) {
|
|
7240
|
+
if (!joins || joins.length === 0) {
|
|
7241
|
+
return void 0;
|
|
7242
|
+
}
|
|
7243
|
+
const joinsArray = [];
|
|
7244
|
+
for (const [index, joinMeta] of joins.entries()) {
|
|
7245
|
+
if (index === 0) {
|
|
7246
|
+
joinsArray.push(sql` `);
|
|
7247
|
+
}
|
|
7248
|
+
const table = joinMeta.table;
|
|
7249
|
+
const lateralSql = joinMeta.lateral ? sql` lateral` : void 0;
|
|
7250
|
+
const onSql = joinMeta.on ? sql` on ${joinMeta.on}` : void 0;
|
|
7251
|
+
if (is(table, PgTable)) {
|
|
7252
|
+
const tableName = table[PgTable.Symbol.Name];
|
|
7253
|
+
const tableSchema = table[PgTable.Symbol.Schema];
|
|
7254
|
+
const origTableName = table[PgTable.Symbol.OriginalName];
|
|
7255
|
+
const alias = tableName === origTableName ? void 0 : joinMeta.alias;
|
|
7256
|
+
joinsArray.push(
|
|
7257
|
+
sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${tableSchema ? sql`${sql.identifier(tableSchema)}.` : void 0}${sql.identifier(origTableName)}${alias && sql` ${sql.identifier(alias)}`}${onSql}`
|
|
7258
|
+
);
|
|
7259
|
+
} else if (is(table, View)) {
|
|
7260
|
+
const viewName = table[ViewBaseConfig].name;
|
|
7261
|
+
const viewSchema = table[ViewBaseConfig].schema;
|
|
7262
|
+
const origViewName = table[ViewBaseConfig].originalName;
|
|
7263
|
+
const alias = viewName === origViewName ? void 0 : joinMeta.alias;
|
|
7264
|
+
joinsArray.push(
|
|
7265
|
+
sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${viewSchema ? sql`${sql.identifier(viewSchema)}.` : void 0}${sql.identifier(origViewName)}${alias && sql` ${sql.identifier(alias)}`}${onSql}`
|
|
7266
|
+
);
|
|
7267
|
+
} else {
|
|
7268
|
+
joinsArray.push(
|
|
7269
|
+
sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${table}${onSql}`
|
|
7270
|
+
);
|
|
7271
|
+
}
|
|
7272
|
+
if (index < joins.length - 1) {
|
|
7273
|
+
joinsArray.push(sql` `);
|
|
7274
|
+
}
|
|
7275
|
+
}
|
|
7276
|
+
return sql.join(joinsArray);
|
|
7277
|
+
}
|
|
7278
|
+
buildFromTable(table) {
|
|
7279
|
+
if (is(table, Table) && table[Table.Symbol.IsAlias]) {
|
|
7280
|
+
let fullName = sql`${sql.identifier(table[Table.Symbol.OriginalName])}`;
|
|
7281
|
+
if (table[Table.Symbol.Schema]) {
|
|
7282
|
+
fullName = sql`${sql.identifier(table[Table.Symbol.Schema])}.${fullName}`;
|
|
7283
|
+
}
|
|
7284
|
+
return sql`${fullName} ${sql.identifier(table[Table.Symbol.Name])}`;
|
|
7285
|
+
}
|
|
7286
|
+
return table;
|
|
7287
|
+
}
|
|
7288
|
+
buildSelectQuery({
|
|
7289
|
+
withList,
|
|
7290
|
+
fields,
|
|
7291
|
+
fieldsFlat,
|
|
7292
|
+
where,
|
|
7293
|
+
having,
|
|
7294
|
+
table,
|
|
7295
|
+
joins,
|
|
7296
|
+
orderBy,
|
|
7297
|
+
groupBy,
|
|
7298
|
+
limit,
|
|
7299
|
+
offset,
|
|
7300
|
+
lockingClause,
|
|
7301
|
+
distinct,
|
|
7302
|
+
setOperators
|
|
7303
|
+
}) {
|
|
7304
|
+
const fieldsList = fieldsFlat ?? orderSelectedFields(fields);
|
|
7305
|
+
for (const f of fieldsList) {
|
|
7306
|
+
if (is(f.field, Column) && getTableName(f.field.table) !== (is(table, Subquery) ? table._.alias : is(table, PgViewBase) ? table[ViewBaseConfig].name : is(table, SQL) ? void 0 : getTableName(table)) && !((table2) => joins?.some(
|
|
7307
|
+
({ alias }) => alias === (table2[Table.Symbol.IsAlias] ? getTableName(table2) : table2[Table.Symbol.BaseName])
|
|
7308
|
+
))(f.field.table)) {
|
|
7309
|
+
const tableName = getTableName(f.field.table);
|
|
7310
|
+
throw new Error(
|
|
7311
|
+
`Your "${f.path.join("->")}" field references a column "${tableName}"."${f.field.name}", but the table "${tableName}" is not part of the query! Did you forget to join it?`
|
|
7312
|
+
);
|
|
7313
|
+
}
|
|
7314
|
+
}
|
|
7315
|
+
const isSingleTable = !joins || joins.length === 0;
|
|
7316
|
+
const withSql = this.buildWithCTE(withList);
|
|
7317
|
+
let distinctSql;
|
|
7318
|
+
if (distinct) {
|
|
7319
|
+
distinctSql = distinct === true ? sql` distinct` : sql` distinct on (${sql.join(distinct.on, sql`, `)})`;
|
|
7320
|
+
}
|
|
7321
|
+
const selection = this.buildSelection(fieldsList, { isSingleTable });
|
|
7322
|
+
const tableSql = this.buildFromTable(table);
|
|
7323
|
+
const joinsSql = this.buildJoins(joins);
|
|
7324
|
+
const whereSql = where ? sql` where ${where}` : void 0;
|
|
7325
|
+
const havingSql = having ? sql` having ${having}` : void 0;
|
|
7326
|
+
let orderBySql;
|
|
7327
|
+
if (orderBy && orderBy.length > 0) {
|
|
7328
|
+
orderBySql = sql` order by ${sql.join(orderBy, sql`, `)}`;
|
|
7329
|
+
}
|
|
7330
|
+
let groupBySql;
|
|
7331
|
+
if (groupBy && groupBy.length > 0) {
|
|
7332
|
+
groupBySql = sql` group by ${sql.join(groupBy, sql`, `)}`;
|
|
7333
|
+
}
|
|
7334
|
+
const limitSql = typeof limit === "object" || typeof limit === "number" && limit >= 0 ? sql` limit ${limit}` : void 0;
|
|
7335
|
+
const offsetSql = offset ? sql` offset ${offset}` : void 0;
|
|
7336
|
+
const lockingClauseSql = sql.empty();
|
|
7337
|
+
if (lockingClause) {
|
|
7338
|
+
const clauseSql = sql` for ${sql.raw(lockingClause.strength)}`;
|
|
7339
|
+
if (lockingClause.config.of) {
|
|
7340
|
+
clauseSql.append(
|
|
7341
|
+
sql` of ${sql.join(
|
|
7342
|
+
Array.isArray(lockingClause.config.of) ? lockingClause.config.of : [lockingClause.config.of],
|
|
7343
|
+
sql`, `
|
|
7344
|
+
)}`
|
|
7345
|
+
);
|
|
7346
|
+
}
|
|
7347
|
+
if (lockingClause.config.noWait) {
|
|
7348
|
+
clauseSql.append(sql` nowait`);
|
|
7349
|
+
} else if (lockingClause.config.skipLocked) {
|
|
7350
|
+
clauseSql.append(sql` skip locked`);
|
|
7351
|
+
}
|
|
7352
|
+
lockingClauseSql.append(clauseSql);
|
|
7353
|
+
}
|
|
7354
|
+
const finalQuery = sql`${withSql}select${distinctSql} ${selection} from ${tableSql}${joinsSql}${whereSql}${groupBySql}${havingSql}${orderBySql}${limitSql}${offsetSql}${lockingClauseSql}`;
|
|
7355
|
+
if (setOperators.length > 0) {
|
|
7356
|
+
return this.buildSetOperations(finalQuery, setOperators);
|
|
7357
|
+
}
|
|
7358
|
+
return finalQuery;
|
|
7359
|
+
}
|
|
7360
|
+
buildSetOperations(leftSelect, setOperators) {
|
|
7361
|
+
const [setOperator, ...rest] = setOperators;
|
|
7362
|
+
if (!setOperator) {
|
|
7363
|
+
throw new Error("Cannot pass undefined values to any set operator");
|
|
7364
|
+
}
|
|
7365
|
+
if (rest.length === 0) {
|
|
7366
|
+
return this.buildSetOperationQuery({ leftSelect, setOperator });
|
|
7367
|
+
}
|
|
7368
|
+
return this.buildSetOperations(
|
|
7369
|
+
this.buildSetOperationQuery({ leftSelect, setOperator }),
|
|
7370
|
+
rest
|
|
7371
|
+
);
|
|
7372
|
+
}
|
|
7373
|
+
buildSetOperationQuery({
|
|
7374
|
+
leftSelect,
|
|
7375
|
+
setOperator: { type, isAll, rightSelect, limit, orderBy, offset }
|
|
7376
|
+
}) {
|
|
7377
|
+
const leftChunk = sql`(${leftSelect.getSQL()}) `;
|
|
7378
|
+
const rightChunk = sql`(${rightSelect.getSQL()})`;
|
|
7379
|
+
let orderBySql;
|
|
7380
|
+
if (orderBy && orderBy.length > 0) {
|
|
7381
|
+
const orderByValues = [];
|
|
7382
|
+
for (const singleOrderBy of orderBy) {
|
|
7383
|
+
if (is(singleOrderBy, PgColumn)) {
|
|
7384
|
+
orderByValues.push(sql.identifier(singleOrderBy.name));
|
|
7385
|
+
} else if (is(singleOrderBy, SQL)) {
|
|
7386
|
+
for (let i = 0; i < singleOrderBy.queryChunks.length; i++) {
|
|
7387
|
+
const chunk = singleOrderBy.queryChunks[i];
|
|
7388
|
+
if (is(chunk, PgColumn)) {
|
|
7389
|
+
singleOrderBy.queryChunks[i] = sql.identifier(chunk.name);
|
|
7390
|
+
}
|
|
7391
|
+
}
|
|
7392
|
+
orderByValues.push(sql`${singleOrderBy}`);
|
|
7393
|
+
} else {
|
|
7394
|
+
orderByValues.push(sql`${singleOrderBy}`);
|
|
7395
|
+
}
|
|
7396
|
+
}
|
|
7397
|
+
orderBySql = sql` order by ${sql.join(orderByValues, sql`, `)} `;
|
|
7398
|
+
}
|
|
7399
|
+
const limitSql = typeof limit === "object" || typeof limit === "number" && limit >= 0 ? sql` limit ${limit}` : void 0;
|
|
7400
|
+
const operatorChunk = sql.raw(`${type} ${isAll ? "all " : ""}`);
|
|
7401
|
+
const offsetSql = offset ? sql` offset ${offset}` : void 0;
|
|
7402
|
+
return sql`${leftChunk}${operatorChunk}${rightChunk}${orderBySql}${limitSql}${offsetSql}`;
|
|
7403
|
+
}
|
|
7404
|
+
buildInsertQuery({ table, values: valuesOrSelect, onConflict, returning, withList, select, overridingSystemValue_ }) {
|
|
7405
|
+
const valuesSqlList = [];
|
|
7406
|
+
const columns = table[Table.Symbol.Columns];
|
|
7407
|
+
const colEntries = Object.entries(columns).filter(([_, col]) => !col.shouldDisableInsert());
|
|
7408
|
+
const insertOrder = colEntries.map(
|
|
7409
|
+
([, column]) => sql.identifier(this.casing.getColumnCasing(column))
|
|
7410
|
+
);
|
|
7411
|
+
if (select) {
|
|
7412
|
+
const select2 = valuesOrSelect;
|
|
7413
|
+
if (is(select2, SQL)) {
|
|
7414
|
+
valuesSqlList.push(select2);
|
|
7415
|
+
} else {
|
|
7416
|
+
valuesSqlList.push(select2.getSQL());
|
|
7417
|
+
}
|
|
7418
|
+
} else {
|
|
7419
|
+
const values = valuesOrSelect;
|
|
7420
|
+
valuesSqlList.push(sql.raw("values "));
|
|
7421
|
+
for (const [valueIndex, value] of values.entries()) {
|
|
7422
|
+
const valueList = [];
|
|
7423
|
+
for (const [fieldName, col] of colEntries) {
|
|
7424
|
+
const colValue = value[fieldName];
|
|
7425
|
+
if (colValue === void 0 || is(colValue, Param) && colValue.value === void 0) {
|
|
7426
|
+
if (col.defaultFn !== void 0) {
|
|
7427
|
+
const defaultFnResult = col.defaultFn();
|
|
7428
|
+
const defaultValue = is(defaultFnResult, SQL) ? defaultFnResult : sql.param(defaultFnResult, col);
|
|
7429
|
+
valueList.push(defaultValue);
|
|
7430
|
+
} else if (!col.default && col.onUpdateFn !== void 0) {
|
|
7431
|
+
const onUpdateFnResult = col.onUpdateFn();
|
|
7432
|
+
const newValue = is(onUpdateFnResult, SQL) ? onUpdateFnResult : sql.param(onUpdateFnResult, col);
|
|
7433
|
+
valueList.push(newValue);
|
|
7434
|
+
} else {
|
|
7435
|
+
valueList.push(sql`default`);
|
|
7436
|
+
}
|
|
7437
|
+
} else {
|
|
7438
|
+
valueList.push(colValue);
|
|
7439
|
+
}
|
|
7440
|
+
}
|
|
7441
|
+
valuesSqlList.push(valueList);
|
|
7442
|
+
if (valueIndex < values.length - 1) {
|
|
7443
|
+
valuesSqlList.push(sql`, `);
|
|
7444
|
+
}
|
|
7445
|
+
}
|
|
7446
|
+
}
|
|
7447
|
+
const withSql = this.buildWithCTE(withList);
|
|
7448
|
+
const valuesSql = sql.join(valuesSqlList);
|
|
7449
|
+
const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;
|
|
7450
|
+
const onConflictSql = onConflict ? sql` on conflict ${onConflict}` : void 0;
|
|
7451
|
+
const overridingSql = overridingSystemValue_ === true ? sql`overriding system value ` : void 0;
|
|
7452
|
+
return sql`${withSql}insert into ${table} ${insertOrder} ${overridingSql}${valuesSql}${onConflictSql}${returningSql}`;
|
|
7453
|
+
}
|
|
7454
|
+
buildRefreshMaterializedViewQuery({ view, concurrently, withNoData }) {
|
|
7455
|
+
const concurrentlySql = concurrently ? sql` concurrently` : void 0;
|
|
7456
|
+
const withNoDataSql = withNoData ? sql` with no data` : void 0;
|
|
7457
|
+
return sql`refresh materialized view${concurrentlySql} ${view}${withNoDataSql}`;
|
|
7458
|
+
}
|
|
7459
|
+
prepareTyping(encoder) {
|
|
7460
|
+
if (is(encoder, PgJsonb) || is(encoder, PgJson)) {
|
|
7461
|
+
return "json";
|
|
7462
|
+
} else if (is(encoder, PgNumeric)) {
|
|
7463
|
+
return "decimal";
|
|
7464
|
+
} else if (is(encoder, PgTime)) {
|
|
7465
|
+
return "time";
|
|
7466
|
+
} else if (is(encoder, PgTimestamp) || is(encoder, PgTimestampString)) {
|
|
7467
|
+
return "timestamp";
|
|
7468
|
+
} else if (is(encoder, PgDate) || is(encoder, PgDateString)) {
|
|
7469
|
+
return "date";
|
|
7470
|
+
} else if (is(encoder, PgUUID)) {
|
|
7471
|
+
return "uuid";
|
|
7472
|
+
} else {
|
|
7473
|
+
return "none";
|
|
7474
|
+
}
|
|
7475
|
+
}
|
|
7476
|
+
sqlToQuery(sql2, invokeSource) {
|
|
7477
|
+
return sql2.toQuery({
|
|
7478
|
+
casing: this.casing,
|
|
7479
|
+
escapeName: this.escapeName,
|
|
7480
|
+
escapeParam: this.escapeParam,
|
|
7481
|
+
escapeString: this.escapeString,
|
|
7482
|
+
prepareTyping: this.prepareTyping,
|
|
7483
|
+
invokeSource
|
|
7484
|
+
});
|
|
7485
|
+
}
|
|
7486
|
+
// buildRelationalQueryWithPK({
|
|
7487
|
+
// fullSchema,
|
|
7488
|
+
// schema,
|
|
7489
|
+
// tableNamesMap,
|
|
7490
|
+
// table,
|
|
7491
|
+
// tableConfig,
|
|
7492
|
+
// queryConfig: config,
|
|
7493
|
+
// tableAlias,
|
|
7494
|
+
// isRoot = false,
|
|
7495
|
+
// joinOn,
|
|
7496
|
+
// }: {
|
|
7497
|
+
// fullSchema: Record<string, unknown>;
|
|
7498
|
+
// schema: TablesRelationalConfig;
|
|
7499
|
+
// tableNamesMap: Record<string, string>;
|
|
7500
|
+
// table: PgTable;
|
|
7501
|
+
// tableConfig: TableRelationalConfig;
|
|
7502
|
+
// queryConfig: true | DBQueryConfig<'many', true>;
|
|
7503
|
+
// tableAlias: string;
|
|
7504
|
+
// isRoot?: boolean;
|
|
7505
|
+
// joinOn?: SQL;
|
|
7506
|
+
// }): BuildRelationalQueryResult<PgTable, PgColumn> {
|
|
7507
|
+
// // For { "<relation>": true }, return a table with selection of all columns
|
|
7508
|
+
// if (config === true) {
|
|
7509
|
+
// const selectionEntries = Object.entries(tableConfig.columns);
|
|
7510
|
+
// const selection: BuildRelationalQueryResult<PgTable, PgColumn>['selection'] = selectionEntries.map((
|
|
7511
|
+
// [key, value],
|
|
7512
|
+
// ) => ({
|
|
7513
|
+
// dbKey: value.name,
|
|
7514
|
+
// tsKey: key,
|
|
7515
|
+
// field: value as PgColumn,
|
|
7516
|
+
// relationTableTsKey: undefined,
|
|
7517
|
+
// isJson: false,
|
|
7518
|
+
// selection: [],
|
|
7519
|
+
// }));
|
|
7520
|
+
// return {
|
|
7521
|
+
// tableTsKey: tableConfig.tsName,
|
|
7522
|
+
// sql: table,
|
|
7523
|
+
// selection,
|
|
7524
|
+
// };
|
|
7525
|
+
// }
|
|
7526
|
+
// // let selection: BuildRelationalQueryResult<PgTable, PgColumn>['selection'] = [];
|
|
7527
|
+
// // let selectionForBuild = selection;
|
|
7528
|
+
// const aliasedColumns = Object.fromEntries(
|
|
7529
|
+
// Object.entries(tableConfig.columns).map(([key, value]) => [key, aliasedTableColumn(value, tableAlias)]),
|
|
7530
|
+
// );
|
|
7531
|
+
// const aliasedRelations = Object.fromEntries(
|
|
7532
|
+
// Object.entries(tableConfig.relations).map(([key, value]) => [key, aliasedRelation(value, tableAlias)]),
|
|
7533
|
+
// );
|
|
7534
|
+
// const aliasedFields = Object.assign({}, aliasedColumns, aliasedRelations);
|
|
7535
|
+
// let where, hasUserDefinedWhere;
|
|
7536
|
+
// if (config.where) {
|
|
7537
|
+
// const whereSql = typeof config.where === 'function' ? config.where(aliasedFields, operators) : config.where;
|
|
7538
|
+
// where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias);
|
|
7539
|
+
// hasUserDefinedWhere = !!where;
|
|
7540
|
+
// }
|
|
7541
|
+
// where = and(joinOn, where);
|
|
7542
|
+
// // const fieldsSelection: { tsKey: string; value: PgColumn | SQL.Aliased; isExtra?: boolean }[] = [];
|
|
7543
|
+
// let joins: Join[] = [];
|
|
7544
|
+
// let selectedColumns: string[] = [];
|
|
7545
|
+
// // Figure out which columns to select
|
|
7546
|
+
// if (config.columns) {
|
|
7547
|
+
// let isIncludeMode = false;
|
|
7548
|
+
// for (const [field, value] of Object.entries(config.columns)) {
|
|
7549
|
+
// if (value === undefined) {
|
|
7550
|
+
// continue;
|
|
7551
|
+
// }
|
|
7552
|
+
// if (field in tableConfig.columns) {
|
|
7553
|
+
// if (!isIncludeMode && value === true) {
|
|
7554
|
+
// isIncludeMode = true;
|
|
7555
|
+
// }
|
|
7556
|
+
// selectedColumns.push(field);
|
|
7557
|
+
// }
|
|
7558
|
+
// }
|
|
7559
|
+
// if (selectedColumns.length > 0) {
|
|
7560
|
+
// selectedColumns = isIncludeMode
|
|
7561
|
+
// ? selectedColumns.filter((c) => config.columns?.[c] === true)
|
|
7562
|
+
// : Object.keys(tableConfig.columns).filter((key) => !selectedColumns.includes(key));
|
|
7563
|
+
// }
|
|
7564
|
+
// } else {
|
|
7565
|
+
// // Select all columns if selection is not specified
|
|
7566
|
+
// selectedColumns = Object.keys(tableConfig.columns);
|
|
7567
|
+
// }
|
|
7568
|
+
// // for (const field of selectedColumns) {
|
|
7569
|
+
// // const column = tableConfig.columns[field]! as PgColumn;
|
|
7570
|
+
// // fieldsSelection.push({ tsKey: field, value: column });
|
|
7571
|
+
// // }
|
|
7572
|
+
// let initiallySelectedRelations: {
|
|
7573
|
+
// tsKey: string;
|
|
7574
|
+
// queryConfig: true | DBQueryConfig<'many', false>;
|
|
7575
|
+
// relation: Relation;
|
|
7576
|
+
// }[] = [];
|
|
7577
|
+
// // let selectedRelations: BuildRelationalQueryResult<PgTable, PgColumn>['selection'] = [];
|
|
7578
|
+
// // Figure out which relations to select
|
|
7579
|
+
// if (config.with) {
|
|
7580
|
+
// initiallySelectedRelations = Object.entries(config.with)
|
|
7581
|
+
// .filter((entry): entry is [typeof entry[0], NonNullable<typeof entry[1]>] => !!entry[1])
|
|
7582
|
+
// .map(([tsKey, queryConfig]) => ({ tsKey, queryConfig, relation: tableConfig.relations[tsKey]! }));
|
|
7583
|
+
// }
|
|
7584
|
+
// const manyRelations = initiallySelectedRelations.filter((r) =>
|
|
7585
|
+
// is(r.relation, Many)
|
|
7586
|
+
// && (schema[tableNamesMap[r.relation.referencedTable[Table.Symbol.Name]]!]?.primaryKey.length ?? 0) > 0
|
|
7587
|
+
// );
|
|
7588
|
+
// // If this is the last Many relation (or there are no Many relations), we are on the innermost subquery level
|
|
7589
|
+
// const isInnermostQuery = manyRelations.length < 2;
|
|
7590
|
+
// const selectedExtras: {
|
|
7591
|
+
// tsKey: string;
|
|
7592
|
+
// value: SQL.Aliased;
|
|
7593
|
+
// }[] = [];
|
|
7594
|
+
// // Figure out which extras to select
|
|
7595
|
+
// if (isInnermostQuery && config.extras) {
|
|
7596
|
+
// const extras = typeof config.extras === 'function'
|
|
7597
|
+
// ? config.extras(aliasedFields, { sql })
|
|
7598
|
+
// : config.extras;
|
|
7599
|
+
// for (const [tsKey, value] of Object.entries(extras)) {
|
|
7600
|
+
// selectedExtras.push({
|
|
7601
|
+
// tsKey,
|
|
7602
|
+
// value: mapColumnsInAliasedSQLToAlias(value, tableAlias),
|
|
7603
|
+
// });
|
|
7604
|
+
// }
|
|
7605
|
+
// }
|
|
7606
|
+
// // Transform `fieldsSelection` into `selection`
|
|
7607
|
+
// // `fieldsSelection` shouldn't be used after this point
|
|
7608
|
+
// // for (const { tsKey, value, isExtra } of fieldsSelection) {
|
|
7609
|
+
// // selection.push({
|
|
7610
|
+
// // dbKey: is(value, SQL.Aliased) ? value.fieldAlias : tableConfig.columns[tsKey]!.name,
|
|
7611
|
+
// // tsKey,
|
|
7612
|
+
// // field: is(value, Column) ? aliasedTableColumn(value, tableAlias) : value,
|
|
7613
|
+
// // relationTableTsKey: undefined,
|
|
7614
|
+
// // isJson: false,
|
|
7615
|
+
// // isExtra,
|
|
7616
|
+
// // selection: [],
|
|
7617
|
+
// // });
|
|
7618
|
+
// // }
|
|
7619
|
+
// let orderByOrig = typeof config.orderBy === 'function'
|
|
7620
|
+
// ? config.orderBy(aliasedFields, orderByOperators)
|
|
7621
|
+
// : config.orderBy ?? [];
|
|
7622
|
+
// if (!Array.isArray(orderByOrig)) {
|
|
7623
|
+
// orderByOrig = [orderByOrig];
|
|
7624
|
+
// }
|
|
7625
|
+
// const orderBy = orderByOrig.map((orderByValue) => {
|
|
7626
|
+
// if (is(orderByValue, Column)) {
|
|
7627
|
+
// return aliasedTableColumn(orderByValue, tableAlias) as PgColumn;
|
|
7628
|
+
// }
|
|
7629
|
+
// return mapColumnsInSQLToAlias(orderByValue, tableAlias);
|
|
7630
|
+
// });
|
|
7631
|
+
// const limit = isInnermostQuery ? config.limit : undefined;
|
|
7632
|
+
// const offset = isInnermostQuery ? config.offset : undefined;
|
|
7633
|
+
// // For non-root queries without additional config except columns, return a table with selection
|
|
7634
|
+
// if (
|
|
7635
|
+
// !isRoot
|
|
7636
|
+
// && initiallySelectedRelations.length === 0
|
|
7637
|
+
// && selectedExtras.length === 0
|
|
7638
|
+
// && !where
|
|
7639
|
+
// && orderBy.length === 0
|
|
7640
|
+
// && limit === undefined
|
|
7641
|
+
// && offset === undefined
|
|
7642
|
+
// ) {
|
|
7643
|
+
// return {
|
|
7644
|
+
// tableTsKey: tableConfig.tsName,
|
|
7645
|
+
// sql: table,
|
|
7646
|
+
// selection: selectedColumns.map((key) => ({
|
|
7647
|
+
// dbKey: tableConfig.columns[key]!.name,
|
|
7648
|
+
// tsKey: key,
|
|
7649
|
+
// field: tableConfig.columns[key] as PgColumn,
|
|
7650
|
+
// relationTableTsKey: undefined,
|
|
7651
|
+
// isJson: false,
|
|
7652
|
+
// selection: [],
|
|
7653
|
+
// })),
|
|
7654
|
+
// };
|
|
7655
|
+
// }
|
|
7656
|
+
// const selectedRelationsWithoutPK:
|
|
7657
|
+
// // Process all relations without primary keys, because they need to be joined differently and will all be on the same query level
|
|
7658
|
+
// for (
|
|
7659
|
+
// const {
|
|
7660
|
+
// tsKey: selectedRelationTsKey,
|
|
7661
|
+
// queryConfig: selectedRelationConfigValue,
|
|
7662
|
+
// relation,
|
|
7663
|
+
// } of initiallySelectedRelations
|
|
7664
|
+
// ) {
|
|
7665
|
+
// const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation);
|
|
7666
|
+
// const relationTableName = relation.referencedTable[Table.Symbol.Name];
|
|
7667
|
+
// const relationTableTsName = tableNamesMap[relationTableName]!;
|
|
7668
|
+
// const relationTable = schema[relationTableTsName]!;
|
|
7669
|
+
// if (relationTable.primaryKey.length > 0) {
|
|
7670
|
+
// continue;
|
|
7671
|
+
// }
|
|
7672
|
+
// const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`;
|
|
7673
|
+
// const joinOn = and(
|
|
7674
|
+
// ...normalizedRelation.fields.map((field, i) =>
|
|
7675
|
+
// eq(
|
|
7676
|
+
// aliasedTableColumn(normalizedRelation.references[i]!, relationTableAlias),
|
|
7677
|
+
// aliasedTableColumn(field, tableAlias),
|
|
7678
|
+
// )
|
|
7679
|
+
// ),
|
|
7680
|
+
// );
|
|
7681
|
+
// const builtRelation = this.buildRelationalQueryWithoutPK({
|
|
7682
|
+
// fullSchema,
|
|
7683
|
+
// schema,
|
|
7684
|
+
// tableNamesMap,
|
|
7685
|
+
// table: fullSchema[relationTableTsName] as PgTable,
|
|
7686
|
+
// tableConfig: schema[relationTableTsName]!,
|
|
7687
|
+
// queryConfig: selectedRelationConfigValue,
|
|
7688
|
+
// tableAlias: relationTableAlias,
|
|
7689
|
+
// joinOn,
|
|
7690
|
+
// nestedQueryRelation: relation,
|
|
7691
|
+
// });
|
|
7692
|
+
// const field = sql`${sql.identifier(relationTableAlias)}.${sql.identifier('data')}`.as(selectedRelationTsKey);
|
|
7693
|
+
// joins.push({
|
|
7694
|
+
// on: sql`true`,
|
|
7695
|
+
// table: new Subquery(builtRelation.sql as SQL, {}, relationTableAlias),
|
|
7696
|
+
// alias: relationTableAlias,
|
|
7697
|
+
// joinType: 'left',
|
|
7698
|
+
// lateral: true,
|
|
7699
|
+
// });
|
|
7700
|
+
// selectedRelations.push({
|
|
7701
|
+
// dbKey: selectedRelationTsKey,
|
|
7702
|
+
// tsKey: selectedRelationTsKey,
|
|
7703
|
+
// field,
|
|
7704
|
+
// relationTableTsKey: relationTableTsName,
|
|
7705
|
+
// isJson: true,
|
|
7706
|
+
// selection: builtRelation.selection,
|
|
7707
|
+
// });
|
|
7708
|
+
// }
|
|
7709
|
+
// const oneRelations = initiallySelectedRelations.filter((r): r is typeof r & { relation: One } =>
|
|
7710
|
+
// is(r.relation, One)
|
|
7711
|
+
// );
|
|
7712
|
+
// // Process all One relations with PKs, because they can all be joined on the same level
|
|
7713
|
+
// for (
|
|
7714
|
+
// const {
|
|
7715
|
+
// tsKey: selectedRelationTsKey,
|
|
7716
|
+
// queryConfig: selectedRelationConfigValue,
|
|
7717
|
+
// relation,
|
|
7718
|
+
// } of oneRelations
|
|
7719
|
+
// ) {
|
|
7720
|
+
// const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation);
|
|
7721
|
+
// const relationTableName = relation.referencedTable[Table.Symbol.Name];
|
|
7722
|
+
// const relationTableTsName = tableNamesMap[relationTableName]!;
|
|
7723
|
+
// const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`;
|
|
7724
|
+
// const relationTable = schema[relationTableTsName]!;
|
|
7725
|
+
// if (relationTable.primaryKey.length === 0) {
|
|
7726
|
+
// continue;
|
|
7727
|
+
// }
|
|
7728
|
+
// const joinOn = and(
|
|
7729
|
+
// ...normalizedRelation.fields.map((field, i) =>
|
|
7730
|
+
// eq(
|
|
7731
|
+
// aliasedTableColumn(normalizedRelation.references[i]!, relationTableAlias),
|
|
7732
|
+
// aliasedTableColumn(field, tableAlias),
|
|
7733
|
+
// )
|
|
7734
|
+
// ),
|
|
7735
|
+
// );
|
|
7736
|
+
// const builtRelation = this.buildRelationalQueryWithPK({
|
|
7737
|
+
// fullSchema,
|
|
7738
|
+
// schema,
|
|
7739
|
+
// tableNamesMap,
|
|
7740
|
+
// table: fullSchema[relationTableTsName] as PgTable,
|
|
7741
|
+
// tableConfig: schema[relationTableTsName]!,
|
|
7742
|
+
// queryConfig: selectedRelationConfigValue,
|
|
7743
|
+
// tableAlias: relationTableAlias,
|
|
7744
|
+
// joinOn,
|
|
7745
|
+
// });
|
|
7746
|
+
// const field = sql`case when ${sql.identifier(relationTableAlias)} is null then null else json_build_array(${
|
|
7747
|
+
// sql.join(
|
|
7748
|
+
// builtRelation.selection.map(({ field }) =>
|
|
7749
|
+
// is(field, SQL.Aliased)
|
|
7750
|
+
// ? sql`${sql.identifier(relationTableAlias)}.${sql.identifier(field.fieldAlias)}`
|
|
7751
|
+
// : is(field, Column)
|
|
7752
|
+
// ? aliasedTableColumn(field, relationTableAlias)
|
|
7753
|
+
// : field
|
|
7754
|
+
// ),
|
|
7755
|
+
// sql`, `,
|
|
7756
|
+
// )
|
|
7757
|
+
// }) end`.as(selectedRelationTsKey);
|
|
7758
|
+
// const isLateralJoin = is(builtRelation.sql, SQL);
|
|
7759
|
+
// joins.push({
|
|
7760
|
+
// on: isLateralJoin ? sql`true` : joinOn,
|
|
7761
|
+
// table: is(builtRelation.sql, SQL)
|
|
7762
|
+
// ? new Subquery(builtRelation.sql, {}, relationTableAlias)
|
|
7763
|
+
// : aliasedTable(builtRelation.sql, relationTableAlias),
|
|
7764
|
+
// alias: relationTableAlias,
|
|
7765
|
+
// joinType: 'left',
|
|
7766
|
+
// lateral: is(builtRelation.sql, SQL),
|
|
7767
|
+
// });
|
|
7768
|
+
// selectedRelations.push({
|
|
7769
|
+
// dbKey: selectedRelationTsKey,
|
|
7770
|
+
// tsKey: selectedRelationTsKey,
|
|
7771
|
+
// field,
|
|
7772
|
+
// relationTableTsKey: relationTableTsName,
|
|
7773
|
+
// isJson: true,
|
|
7774
|
+
// selection: builtRelation.selection,
|
|
7775
|
+
// });
|
|
7776
|
+
// }
|
|
7777
|
+
// let distinct: PgSelectConfig['distinct'];
|
|
7778
|
+
// let tableFrom: PgTable | Subquery = table;
|
|
7779
|
+
// // Process first Many relation - each one requires a nested subquery
|
|
7780
|
+
// const manyRelation = manyRelations[0];
|
|
7781
|
+
// if (manyRelation) {
|
|
7782
|
+
// const {
|
|
7783
|
+
// tsKey: selectedRelationTsKey,
|
|
7784
|
+
// queryConfig: selectedRelationQueryConfig,
|
|
7785
|
+
// relation,
|
|
7786
|
+
// } = manyRelation;
|
|
7787
|
+
// distinct = {
|
|
7788
|
+
// on: tableConfig.primaryKey.map((c) => aliasedTableColumn(c as PgColumn, tableAlias)),
|
|
7789
|
+
// };
|
|
7790
|
+
// const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation);
|
|
7791
|
+
// const relationTableName = relation.referencedTable[Table.Symbol.Name];
|
|
7792
|
+
// const relationTableTsName = tableNamesMap[relationTableName]!;
|
|
7793
|
+
// const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`;
|
|
7794
|
+
// const joinOn = and(
|
|
7795
|
+
// ...normalizedRelation.fields.map((field, i) =>
|
|
7796
|
+
// eq(
|
|
7797
|
+
// aliasedTableColumn(normalizedRelation.references[i]!, relationTableAlias),
|
|
7798
|
+
// aliasedTableColumn(field, tableAlias),
|
|
7799
|
+
// )
|
|
7800
|
+
// ),
|
|
7801
|
+
// );
|
|
7802
|
+
// const builtRelationJoin = this.buildRelationalQueryWithPK({
|
|
7803
|
+
// fullSchema,
|
|
7804
|
+
// schema,
|
|
7805
|
+
// tableNamesMap,
|
|
7806
|
+
// table: fullSchema[relationTableTsName] as PgTable,
|
|
7807
|
+
// tableConfig: schema[relationTableTsName]!,
|
|
7808
|
+
// queryConfig: selectedRelationQueryConfig,
|
|
7809
|
+
// tableAlias: relationTableAlias,
|
|
7810
|
+
// joinOn,
|
|
7811
|
+
// });
|
|
7812
|
+
// const builtRelationSelectionField = sql`case when ${
|
|
7813
|
+
// sql.identifier(relationTableAlias)
|
|
7814
|
+
// } is null then '[]' else json_agg(json_build_array(${
|
|
7815
|
+
// sql.join(
|
|
7816
|
+
// builtRelationJoin.selection.map(({ field }) =>
|
|
7817
|
+
// is(field, SQL.Aliased)
|
|
7818
|
+
// ? sql`${sql.identifier(relationTableAlias)}.${sql.identifier(field.fieldAlias)}`
|
|
7819
|
+
// : is(field, Column)
|
|
7820
|
+
// ? aliasedTableColumn(field, relationTableAlias)
|
|
7821
|
+
// : field
|
|
7822
|
+
// ),
|
|
7823
|
+
// sql`, `,
|
|
7824
|
+
// )
|
|
7825
|
+
// })) over (partition by ${sql.join(distinct.on, sql`, `)}) end`.as(selectedRelationTsKey);
|
|
7826
|
+
// const isLateralJoin = is(builtRelationJoin.sql, SQL);
|
|
7827
|
+
// joins.push({
|
|
7828
|
+
// on: isLateralJoin ? sql`true` : joinOn,
|
|
7829
|
+
// table: isLateralJoin
|
|
7830
|
+
// ? new Subquery(builtRelationJoin.sql as SQL, {}, relationTableAlias)
|
|
7831
|
+
// : aliasedTable(builtRelationJoin.sql as PgTable, relationTableAlias),
|
|
7832
|
+
// alias: relationTableAlias,
|
|
7833
|
+
// joinType: 'left',
|
|
7834
|
+
// lateral: isLateralJoin,
|
|
7835
|
+
// });
|
|
7836
|
+
// // Build the "from" subquery with the remaining Many relations
|
|
7837
|
+
// const builtTableFrom = this.buildRelationalQueryWithPK({
|
|
7838
|
+
// fullSchema,
|
|
7839
|
+
// schema,
|
|
7840
|
+
// tableNamesMap,
|
|
7841
|
+
// table,
|
|
7842
|
+
// tableConfig,
|
|
7843
|
+
// queryConfig: {
|
|
7844
|
+
// ...config,
|
|
7845
|
+
// where: undefined,
|
|
7846
|
+
// orderBy: undefined,
|
|
7847
|
+
// limit: undefined,
|
|
7848
|
+
// offset: undefined,
|
|
7849
|
+
// with: manyRelations.slice(1).reduce<NonNullable<typeof config['with']>>(
|
|
7850
|
+
// (result, { tsKey, queryConfig: configValue }) => {
|
|
7851
|
+
// result[tsKey] = configValue;
|
|
7852
|
+
// return result;
|
|
7853
|
+
// },
|
|
7854
|
+
// {},
|
|
7855
|
+
// ),
|
|
7856
|
+
// },
|
|
7857
|
+
// tableAlias,
|
|
7858
|
+
// });
|
|
7859
|
+
// selectedRelations.push({
|
|
7860
|
+
// dbKey: selectedRelationTsKey,
|
|
7861
|
+
// tsKey: selectedRelationTsKey,
|
|
7862
|
+
// field: builtRelationSelectionField,
|
|
7863
|
+
// relationTableTsKey: relationTableTsName,
|
|
7864
|
+
// isJson: true,
|
|
7865
|
+
// selection: builtRelationJoin.selection,
|
|
7866
|
+
// });
|
|
7867
|
+
// // selection = builtTableFrom.selection.map((item) =>
|
|
7868
|
+
// // is(item.field, SQL.Aliased)
|
|
7869
|
+
// // ? { ...item, field: sql`${sql.identifier(tableAlias)}.${sql.identifier(item.field.fieldAlias)}` }
|
|
7870
|
+
// // : item
|
|
7871
|
+
// // );
|
|
7872
|
+
// // selectionForBuild = [{
|
|
7873
|
+
// // dbKey: '*',
|
|
7874
|
+
// // tsKey: '*',
|
|
7875
|
+
// // field: sql`${sql.identifier(tableAlias)}.*`,
|
|
7876
|
+
// // selection: [],
|
|
7877
|
+
// // isJson: false,
|
|
7878
|
+
// // relationTableTsKey: undefined,
|
|
7879
|
+
// // }];
|
|
7880
|
+
// // const newSelectionItem: (typeof selection)[number] = {
|
|
7881
|
+
// // dbKey: selectedRelationTsKey,
|
|
7882
|
+
// // tsKey: selectedRelationTsKey,
|
|
7883
|
+
// // field,
|
|
7884
|
+
// // relationTableTsKey: relationTableTsName,
|
|
7885
|
+
// // isJson: true,
|
|
7886
|
+
// // selection: builtRelationJoin.selection,
|
|
7887
|
+
// // };
|
|
7888
|
+
// // selection.push(newSelectionItem);
|
|
7889
|
+
// // selectionForBuild.push(newSelectionItem);
|
|
7890
|
+
// tableFrom = is(builtTableFrom.sql, PgTable)
|
|
7891
|
+
// ? builtTableFrom.sql
|
|
7892
|
+
// : new Subquery(builtTableFrom.sql, {}, tableAlias);
|
|
7893
|
+
// }
|
|
7894
|
+
// if (selectedColumns.length === 0 && selectedRelations.length === 0 && selectedExtras.length === 0) {
|
|
7895
|
+
// throw new DrizzleError(`No fields selected for table "${tableConfig.tsName}" ("${tableAlias}")`);
|
|
7896
|
+
// }
|
|
7897
|
+
// let selection: BuildRelationalQueryResult<PgTable, PgColumn>['selection'];
|
|
7898
|
+
// function prepareSelectedColumns() {
|
|
7899
|
+
// return selectedColumns.map((key) => ({
|
|
7900
|
+
// dbKey: tableConfig.columns[key]!.name,
|
|
7901
|
+
// tsKey: key,
|
|
7902
|
+
// field: tableConfig.columns[key] as PgColumn,
|
|
7903
|
+
// relationTableTsKey: undefined,
|
|
7904
|
+
// isJson: false,
|
|
7905
|
+
// selection: [],
|
|
7906
|
+
// }));
|
|
7907
|
+
// }
|
|
7908
|
+
// function prepareSelectedExtras() {
|
|
7909
|
+
// return selectedExtras.map((item) => ({
|
|
7910
|
+
// dbKey: item.value.fieldAlias,
|
|
7911
|
+
// tsKey: item.tsKey,
|
|
7912
|
+
// field: item.value,
|
|
7913
|
+
// relationTableTsKey: undefined,
|
|
7914
|
+
// isJson: false,
|
|
7915
|
+
// selection: [],
|
|
7916
|
+
// }));
|
|
7917
|
+
// }
|
|
7918
|
+
// if (isRoot) {
|
|
7919
|
+
// selection = [
|
|
7920
|
+
// ...prepareSelectedColumns(),
|
|
7921
|
+
// ...prepareSelectedExtras(),
|
|
7922
|
+
// ];
|
|
7923
|
+
// }
|
|
7924
|
+
// if (hasUserDefinedWhere || orderBy.length > 0) {
|
|
7925
|
+
// tableFrom = new Subquery(
|
|
7926
|
+
// this.buildSelectQuery({
|
|
7927
|
+
// table: is(tableFrom, PgTable) ? aliasedTable(tableFrom, tableAlias) : tableFrom,
|
|
7928
|
+
// fields: {},
|
|
7929
|
+
// fieldsFlat: selectionForBuild.map(({ field }) => ({
|
|
7930
|
+
// path: [],
|
|
7931
|
+
// field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field,
|
|
7932
|
+
// })),
|
|
7933
|
+
// joins,
|
|
7934
|
+
// distinct,
|
|
7935
|
+
// }),
|
|
7936
|
+
// {},
|
|
7937
|
+
// tableAlias,
|
|
7938
|
+
// );
|
|
7939
|
+
// selectionForBuild = selection.map((item) =>
|
|
7940
|
+
// is(item.field, SQL.Aliased)
|
|
7941
|
+
// ? { ...item, field: sql`${sql.identifier(tableAlias)}.${sql.identifier(item.field.fieldAlias)}` }
|
|
7942
|
+
// : item
|
|
7943
|
+
// );
|
|
7944
|
+
// joins = [];
|
|
7945
|
+
// distinct = undefined;
|
|
7946
|
+
// }
|
|
7947
|
+
// const result = this.buildSelectQuery({
|
|
7948
|
+
// table: is(tableFrom, PgTable) ? aliasedTable(tableFrom, tableAlias) : tableFrom,
|
|
7949
|
+
// fields: {},
|
|
7950
|
+
// fieldsFlat: selectionForBuild.map(({ field }) => ({
|
|
7951
|
+
// path: [],
|
|
7952
|
+
// field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field,
|
|
7953
|
+
// })),
|
|
7954
|
+
// where,
|
|
7955
|
+
// limit,
|
|
7956
|
+
// offset,
|
|
7957
|
+
// joins,
|
|
7958
|
+
// orderBy,
|
|
7959
|
+
// distinct,
|
|
7960
|
+
// });
|
|
7961
|
+
// return {
|
|
7962
|
+
// tableTsKey: tableConfig.tsName,
|
|
7963
|
+
// sql: result,
|
|
7964
|
+
// selection,
|
|
7965
|
+
// };
|
|
7966
|
+
// }
|
|
7967
|
+
buildRelationalQueryWithoutPK({
|
|
7968
|
+
fullSchema,
|
|
7969
|
+
schema,
|
|
7970
|
+
tableNamesMap,
|
|
7971
|
+
table,
|
|
7972
|
+
tableConfig,
|
|
7973
|
+
queryConfig: config,
|
|
7974
|
+
tableAlias,
|
|
7975
|
+
nestedQueryRelation,
|
|
7976
|
+
joinOn
|
|
7977
|
+
}) {
|
|
7978
|
+
let selection = [];
|
|
7979
|
+
let limit, offset, orderBy = [], where;
|
|
7980
|
+
const joins = [];
|
|
7981
|
+
if (config === true) {
|
|
7982
|
+
const selectionEntries = Object.entries(tableConfig.columns);
|
|
7983
|
+
selection = selectionEntries.map(([key, value]) => ({
|
|
7984
|
+
dbKey: value.name,
|
|
7985
|
+
tsKey: key,
|
|
7986
|
+
field: aliasedTableColumn(value, tableAlias),
|
|
7987
|
+
relationTableTsKey: void 0,
|
|
7988
|
+
isJson: false,
|
|
7989
|
+
selection: []
|
|
7990
|
+
}));
|
|
7991
|
+
} else {
|
|
7992
|
+
const aliasedColumns = Object.fromEntries(
|
|
7993
|
+
Object.entries(tableConfig.columns).map(([key, value]) => [key, aliasedTableColumn(value, tableAlias)])
|
|
7994
|
+
);
|
|
7995
|
+
if (config.where) {
|
|
7996
|
+
const whereSql = typeof config.where === "function" ? config.where(aliasedColumns, getOperators()) : config.where;
|
|
7997
|
+
where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias);
|
|
7998
|
+
}
|
|
7999
|
+
const fieldsSelection = [];
|
|
8000
|
+
let selectedColumns = [];
|
|
8001
|
+
if (config.columns) {
|
|
8002
|
+
let isIncludeMode = false;
|
|
8003
|
+
for (const [field, value] of Object.entries(config.columns)) {
|
|
8004
|
+
if (value === void 0) {
|
|
8005
|
+
continue;
|
|
8006
|
+
}
|
|
8007
|
+
if (field in tableConfig.columns) {
|
|
8008
|
+
if (!isIncludeMode && value === true) {
|
|
8009
|
+
isIncludeMode = true;
|
|
8010
|
+
}
|
|
8011
|
+
selectedColumns.push(field);
|
|
8012
|
+
}
|
|
8013
|
+
}
|
|
8014
|
+
if (selectedColumns.length > 0) {
|
|
8015
|
+
selectedColumns = isIncludeMode ? selectedColumns.filter((c) => config.columns?.[c] === true) : Object.keys(tableConfig.columns).filter((key) => !selectedColumns.includes(key));
|
|
8016
|
+
}
|
|
8017
|
+
} else {
|
|
8018
|
+
selectedColumns = Object.keys(tableConfig.columns);
|
|
8019
|
+
}
|
|
8020
|
+
for (const field of selectedColumns) {
|
|
8021
|
+
const column = tableConfig.columns[field];
|
|
8022
|
+
fieldsSelection.push({ tsKey: field, value: column });
|
|
8023
|
+
}
|
|
8024
|
+
let selectedRelations = [];
|
|
8025
|
+
if (config.with) {
|
|
8026
|
+
selectedRelations = Object.entries(config.with).filter((entry) => !!entry[1]).map(([tsKey, queryConfig]) => ({ tsKey, queryConfig, relation: tableConfig.relations[tsKey] }));
|
|
8027
|
+
}
|
|
8028
|
+
let extras;
|
|
8029
|
+
if (config.extras) {
|
|
8030
|
+
extras = typeof config.extras === "function" ? config.extras(aliasedColumns, { sql }) : config.extras;
|
|
8031
|
+
for (const [tsKey, value] of Object.entries(extras)) {
|
|
8032
|
+
fieldsSelection.push({
|
|
8033
|
+
tsKey,
|
|
8034
|
+
value: mapColumnsInAliasedSQLToAlias(value, tableAlias)
|
|
8035
|
+
});
|
|
8036
|
+
}
|
|
8037
|
+
}
|
|
8038
|
+
for (const { tsKey, value } of fieldsSelection) {
|
|
8039
|
+
selection.push({
|
|
8040
|
+
dbKey: is(value, SQL.Aliased) ? value.fieldAlias : tableConfig.columns[tsKey].name,
|
|
8041
|
+
tsKey,
|
|
8042
|
+
field: is(value, Column) ? aliasedTableColumn(value, tableAlias) : value,
|
|
8043
|
+
relationTableTsKey: void 0,
|
|
8044
|
+
isJson: false,
|
|
8045
|
+
selection: []
|
|
8046
|
+
});
|
|
8047
|
+
}
|
|
8048
|
+
let orderByOrig = typeof config.orderBy === "function" ? config.orderBy(aliasedColumns, getOrderByOperators()) : config.orderBy ?? [];
|
|
8049
|
+
if (!Array.isArray(orderByOrig)) {
|
|
8050
|
+
orderByOrig = [orderByOrig];
|
|
8051
|
+
}
|
|
8052
|
+
orderBy = orderByOrig.map((orderByValue) => {
|
|
8053
|
+
if (is(orderByValue, Column)) {
|
|
8054
|
+
return aliasedTableColumn(orderByValue, tableAlias);
|
|
8055
|
+
}
|
|
8056
|
+
return mapColumnsInSQLToAlias(orderByValue, tableAlias);
|
|
8057
|
+
});
|
|
8058
|
+
limit = config.limit;
|
|
8059
|
+
offset = config.offset;
|
|
8060
|
+
for (const {
|
|
8061
|
+
tsKey: selectedRelationTsKey,
|
|
8062
|
+
queryConfig: selectedRelationConfigValue,
|
|
8063
|
+
relation
|
|
8064
|
+
} of selectedRelations) {
|
|
8065
|
+
const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation);
|
|
8066
|
+
const relationTableName = getTableUniqueName(relation.referencedTable);
|
|
8067
|
+
const relationTableTsName = tableNamesMap[relationTableName];
|
|
8068
|
+
const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`;
|
|
8069
|
+
const joinOn2 = and(
|
|
8070
|
+
...normalizedRelation.fields.map(
|
|
8071
|
+
(field2, i) => eq(
|
|
8072
|
+
aliasedTableColumn(normalizedRelation.references[i], relationTableAlias),
|
|
8073
|
+
aliasedTableColumn(field2, tableAlias)
|
|
8074
|
+
)
|
|
8075
|
+
)
|
|
8076
|
+
);
|
|
8077
|
+
const builtRelation = this.buildRelationalQueryWithoutPK({
|
|
8078
|
+
fullSchema,
|
|
8079
|
+
schema,
|
|
8080
|
+
tableNamesMap,
|
|
8081
|
+
table: fullSchema[relationTableTsName],
|
|
8082
|
+
tableConfig: schema[relationTableTsName],
|
|
8083
|
+
queryConfig: is(relation, One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue,
|
|
8084
|
+
tableAlias: relationTableAlias,
|
|
8085
|
+
joinOn: joinOn2,
|
|
8086
|
+
nestedQueryRelation: relation
|
|
8087
|
+
});
|
|
8088
|
+
const field = sql`${sql.identifier(relationTableAlias)}.${sql.identifier("data")}`.as(selectedRelationTsKey);
|
|
8089
|
+
joins.push({
|
|
8090
|
+
on: sql`true`,
|
|
8091
|
+
table: new Subquery(builtRelation.sql, {}, relationTableAlias),
|
|
8092
|
+
alias: relationTableAlias,
|
|
8093
|
+
joinType: "left",
|
|
8094
|
+
lateral: true
|
|
8095
|
+
});
|
|
8096
|
+
selection.push({
|
|
8097
|
+
dbKey: selectedRelationTsKey,
|
|
8098
|
+
tsKey: selectedRelationTsKey,
|
|
8099
|
+
field,
|
|
8100
|
+
relationTableTsKey: relationTableTsName,
|
|
8101
|
+
isJson: true,
|
|
8102
|
+
selection: builtRelation.selection
|
|
8103
|
+
});
|
|
8104
|
+
}
|
|
8105
|
+
}
|
|
8106
|
+
if (selection.length === 0) {
|
|
8107
|
+
throw new DrizzleError({ message: `No fields selected for table "${tableConfig.tsName}" ("${tableAlias}")` });
|
|
8108
|
+
}
|
|
8109
|
+
let result;
|
|
8110
|
+
where = and(joinOn, where);
|
|
8111
|
+
if (nestedQueryRelation) {
|
|
8112
|
+
let field = sql`json_build_array(${sql.join(
|
|
8113
|
+
selection.map(
|
|
8114
|
+
({ field: field2, tsKey, isJson }) => isJson ? sql`${sql.identifier(`${tableAlias}_${tsKey}`)}.${sql.identifier("data")}` : is(field2, SQL.Aliased) ? field2.sql : field2
|
|
8115
|
+
),
|
|
8116
|
+
sql`, `
|
|
8117
|
+
)})`;
|
|
8118
|
+
if (is(nestedQueryRelation, Many)) {
|
|
8119
|
+
field = sql`coalesce(json_agg(${field}${orderBy.length > 0 ? sql` order by ${sql.join(orderBy, sql`, `)}` : void 0}), '[]'::json)`;
|
|
8120
|
+
}
|
|
8121
|
+
const nestedSelection = [{
|
|
8122
|
+
dbKey: "data",
|
|
8123
|
+
tsKey: "data",
|
|
8124
|
+
field: field.as("data"),
|
|
8125
|
+
isJson: true,
|
|
8126
|
+
relationTableTsKey: tableConfig.tsName,
|
|
8127
|
+
selection
|
|
8128
|
+
}];
|
|
8129
|
+
const needsSubquery = limit !== void 0 || offset !== void 0 || orderBy.length > 0;
|
|
8130
|
+
if (needsSubquery) {
|
|
8131
|
+
result = this.buildSelectQuery({
|
|
8132
|
+
table: aliasedTable(table, tableAlias),
|
|
8133
|
+
fields: {},
|
|
8134
|
+
fieldsFlat: [{
|
|
8135
|
+
path: [],
|
|
8136
|
+
field: sql.raw("*")
|
|
8137
|
+
}],
|
|
8138
|
+
where,
|
|
8139
|
+
limit,
|
|
8140
|
+
offset,
|
|
8141
|
+
orderBy,
|
|
8142
|
+
setOperators: []
|
|
8143
|
+
});
|
|
8144
|
+
where = void 0;
|
|
8145
|
+
limit = void 0;
|
|
8146
|
+
offset = void 0;
|
|
8147
|
+
orderBy = [];
|
|
8148
|
+
} else {
|
|
8149
|
+
result = aliasedTable(table, tableAlias);
|
|
8150
|
+
}
|
|
8151
|
+
result = this.buildSelectQuery({
|
|
8152
|
+
table: is(result, PgTable) ? result : new Subquery(result, {}, tableAlias),
|
|
8153
|
+
fields: {},
|
|
8154
|
+
fieldsFlat: nestedSelection.map(({ field: field2 }) => ({
|
|
8155
|
+
path: [],
|
|
8156
|
+
field: is(field2, Column) ? aliasedTableColumn(field2, tableAlias) : field2
|
|
8157
|
+
})),
|
|
8158
|
+
joins,
|
|
8159
|
+
where,
|
|
8160
|
+
limit,
|
|
8161
|
+
offset,
|
|
8162
|
+
orderBy,
|
|
8163
|
+
setOperators: []
|
|
8164
|
+
});
|
|
8165
|
+
} else {
|
|
8166
|
+
result = this.buildSelectQuery({
|
|
8167
|
+
table: aliasedTable(table, tableAlias),
|
|
8168
|
+
fields: {},
|
|
8169
|
+
fieldsFlat: selection.map(({ field }) => ({
|
|
8170
|
+
path: [],
|
|
8171
|
+
field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field
|
|
8172
|
+
})),
|
|
8173
|
+
joins,
|
|
8174
|
+
where,
|
|
8175
|
+
limit,
|
|
8176
|
+
offset,
|
|
8177
|
+
orderBy,
|
|
8178
|
+
setOperators: []
|
|
8179
|
+
});
|
|
8180
|
+
}
|
|
8181
|
+
return {
|
|
8182
|
+
tableTsKey: tableConfig.tsName,
|
|
8183
|
+
sql: result,
|
|
8184
|
+
selection
|
|
8185
|
+
};
|
|
8186
|
+
}
|
|
8187
|
+
}
|
|
8188
|
+
|
|
8189
|
+
class TypedQueryBuilder {
|
|
8190
|
+
static [entityKind] = "TypedQueryBuilder";
|
|
8191
|
+
/** @internal */
|
|
8192
|
+
getSelectedFields() {
|
|
8193
|
+
return this._.selectedFields;
|
|
8194
|
+
}
|
|
8195
|
+
}
|
|
8196
|
+
|
|
8197
|
+
class PgSelectBuilder {
|
|
8198
|
+
static [entityKind] = "PgSelectBuilder";
|
|
8199
|
+
fields;
|
|
8200
|
+
session;
|
|
8201
|
+
dialect;
|
|
8202
|
+
withList = [];
|
|
8203
|
+
distinct;
|
|
8204
|
+
constructor(config) {
|
|
8205
|
+
this.fields = config.fields;
|
|
8206
|
+
this.session = config.session;
|
|
8207
|
+
this.dialect = config.dialect;
|
|
8208
|
+
if (config.withList) {
|
|
8209
|
+
this.withList = config.withList;
|
|
8210
|
+
}
|
|
8211
|
+
this.distinct = config.distinct;
|
|
8212
|
+
}
|
|
8213
|
+
authToken;
|
|
8214
|
+
/** @internal */
|
|
8215
|
+
setToken(token) {
|
|
8216
|
+
this.authToken = token;
|
|
8217
|
+
return this;
|
|
8218
|
+
}
|
|
8219
|
+
/**
|
|
8220
|
+
* Specify the table, subquery, or other target that you're
|
|
8221
|
+
* building a select query against.
|
|
8222
|
+
*
|
|
8223
|
+
* {@link https://www.postgresql.org/docs/current/sql-select.html#SQL-FROM | Postgres from documentation}
|
|
8224
|
+
*/
|
|
8225
|
+
from(source) {
|
|
8226
|
+
const isPartialSelect = !!this.fields;
|
|
8227
|
+
const src = source;
|
|
8228
|
+
let fields;
|
|
8229
|
+
if (this.fields) {
|
|
8230
|
+
fields = this.fields;
|
|
8231
|
+
} else if (is(src, Subquery)) {
|
|
8232
|
+
fields = Object.fromEntries(
|
|
8233
|
+
Object.keys(src._.selectedFields).map((key) => [key, src[key]])
|
|
8234
|
+
);
|
|
8235
|
+
} else if (is(src, PgViewBase)) {
|
|
8236
|
+
fields = src[ViewBaseConfig].selectedFields;
|
|
8237
|
+
} else if (is(src, SQL)) {
|
|
8238
|
+
fields = {};
|
|
8239
|
+
} else {
|
|
8240
|
+
fields = getTableColumns(src);
|
|
8241
|
+
}
|
|
8242
|
+
return new PgSelectBase({
|
|
8243
|
+
table: src,
|
|
8244
|
+
fields,
|
|
8245
|
+
isPartialSelect,
|
|
8246
|
+
session: this.session,
|
|
8247
|
+
dialect: this.dialect,
|
|
8248
|
+
withList: this.withList,
|
|
8249
|
+
distinct: this.distinct
|
|
8250
|
+
}).setToken(this.authToken);
|
|
8251
|
+
}
|
|
8252
|
+
}
|
|
8253
|
+
class PgSelectQueryBuilderBase extends TypedQueryBuilder {
|
|
8254
|
+
static [entityKind] = "PgSelectQueryBuilder";
|
|
8255
|
+
_;
|
|
8256
|
+
config;
|
|
8257
|
+
joinsNotNullableMap;
|
|
8258
|
+
tableName;
|
|
8259
|
+
isPartialSelect;
|
|
8260
|
+
session;
|
|
8261
|
+
dialect;
|
|
8262
|
+
cacheConfig = void 0;
|
|
8263
|
+
usedTables = /* @__PURE__ */ new Set();
|
|
8264
|
+
constructor({ table, fields, isPartialSelect, session, dialect, withList, distinct }) {
|
|
8265
|
+
super();
|
|
8266
|
+
this.config = {
|
|
8267
|
+
withList,
|
|
8268
|
+
table,
|
|
8269
|
+
fields: { ...fields },
|
|
8270
|
+
distinct,
|
|
8271
|
+
setOperators: []
|
|
8272
|
+
};
|
|
8273
|
+
this.isPartialSelect = isPartialSelect;
|
|
8274
|
+
this.session = session;
|
|
8275
|
+
this.dialect = dialect;
|
|
8276
|
+
this._ = {
|
|
8277
|
+
selectedFields: fields,
|
|
8278
|
+
config: this.config
|
|
8279
|
+
};
|
|
8280
|
+
this.tableName = getTableLikeName(table);
|
|
8281
|
+
this.joinsNotNullableMap = typeof this.tableName === "string" ? { [this.tableName]: true } : {};
|
|
8282
|
+
for (const item of extractUsedTable(table)) this.usedTables.add(item);
|
|
8283
|
+
}
|
|
8284
|
+
/** @internal */
|
|
8285
|
+
getUsedTables() {
|
|
8286
|
+
return [...this.usedTables];
|
|
8287
|
+
}
|
|
8288
|
+
createJoin(joinType, lateral) {
|
|
8289
|
+
return (table, on) => {
|
|
8290
|
+
const baseTableName = this.tableName;
|
|
8291
|
+
const tableName = getTableLikeName(table);
|
|
8292
|
+
for (const item of extractUsedTable(table)) this.usedTables.add(item);
|
|
8293
|
+
if (typeof tableName === "string" && this.config.joins?.some((join) => join.alias === tableName)) {
|
|
8294
|
+
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
8295
|
+
}
|
|
8296
|
+
if (!this.isPartialSelect) {
|
|
8297
|
+
if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") {
|
|
8298
|
+
this.config.fields = {
|
|
8299
|
+
[baseTableName]: this.config.fields
|
|
8300
|
+
};
|
|
8301
|
+
}
|
|
8302
|
+
if (typeof tableName === "string" && !is(table, SQL)) {
|
|
8303
|
+
const selection = is(table, Subquery) ? table._.selectedFields : is(table, View) ? table[ViewBaseConfig].selectedFields : table[Table.Symbol.Columns];
|
|
8304
|
+
this.config.fields[tableName] = selection;
|
|
8305
|
+
}
|
|
8306
|
+
}
|
|
8307
|
+
if (typeof on === "function") {
|
|
8308
|
+
on = on(
|
|
8309
|
+
new Proxy(
|
|
8310
|
+
this.config.fields,
|
|
8311
|
+
new SelectionProxyHandler({ sqlAliasedBehavior: "sql", sqlBehavior: "sql" })
|
|
8312
|
+
)
|
|
8313
|
+
);
|
|
8314
|
+
}
|
|
8315
|
+
if (!this.config.joins) {
|
|
8316
|
+
this.config.joins = [];
|
|
8317
|
+
}
|
|
8318
|
+
this.config.joins.push({ on, table, joinType, alias: tableName, lateral });
|
|
8319
|
+
if (typeof tableName === "string") {
|
|
8320
|
+
switch (joinType) {
|
|
8321
|
+
case "left": {
|
|
8322
|
+
this.joinsNotNullableMap[tableName] = false;
|
|
8323
|
+
break;
|
|
8324
|
+
}
|
|
8325
|
+
case "right": {
|
|
8326
|
+
this.joinsNotNullableMap = Object.fromEntries(
|
|
8327
|
+
Object.entries(this.joinsNotNullableMap).map(([key]) => [key, false])
|
|
8328
|
+
);
|
|
8329
|
+
this.joinsNotNullableMap[tableName] = true;
|
|
8330
|
+
break;
|
|
8331
|
+
}
|
|
8332
|
+
case "cross":
|
|
8333
|
+
case "inner": {
|
|
8334
|
+
this.joinsNotNullableMap[tableName] = true;
|
|
8335
|
+
break;
|
|
8336
|
+
}
|
|
8337
|
+
case "full": {
|
|
8338
|
+
this.joinsNotNullableMap = Object.fromEntries(
|
|
8339
|
+
Object.entries(this.joinsNotNullableMap).map(([key]) => [key, false])
|
|
8340
|
+
);
|
|
8341
|
+
this.joinsNotNullableMap[tableName] = false;
|
|
8342
|
+
break;
|
|
8343
|
+
}
|
|
8344
|
+
}
|
|
8345
|
+
}
|
|
8346
|
+
return this;
|
|
8347
|
+
};
|
|
8348
|
+
}
|
|
8349
|
+
/**
|
|
8350
|
+
* Executes a `left join` operation by adding another table to the current query.
|
|
8351
|
+
*
|
|
8352
|
+
* Calling this method associates each row of the table with the corresponding row from the joined table, if a match is found. If no matching row exists, it sets all columns of the joined table to null.
|
|
8353
|
+
*
|
|
8354
|
+
* See docs: {@link https://orm.drizzle.team/docs/joins#left-join}
|
|
8355
|
+
*
|
|
8356
|
+
* @param table the table to join.
|
|
8357
|
+
* @param on the `on` clause.
|
|
8358
|
+
*
|
|
8359
|
+
* @example
|
|
8360
|
+
*
|
|
8361
|
+
* ```ts
|
|
8362
|
+
* // Select all users and their pets
|
|
8363
|
+
* const usersWithPets: { user: User; pets: Pet | null; }[] = await db.select()
|
|
8364
|
+
* .from(users)
|
|
8365
|
+
* .leftJoin(pets, eq(users.id, pets.ownerId))
|
|
8366
|
+
*
|
|
8367
|
+
* // Select userId and petId
|
|
8368
|
+
* const usersIdsAndPetIds: { userId: number; petId: number | null; }[] = await db.select({
|
|
8369
|
+
* userId: users.id,
|
|
8370
|
+
* petId: pets.id,
|
|
8371
|
+
* })
|
|
8372
|
+
* .from(users)
|
|
8373
|
+
* .leftJoin(pets, eq(users.id, pets.ownerId))
|
|
8374
|
+
* ```
|
|
8375
|
+
*/
|
|
8376
|
+
leftJoin = this.createJoin("left", false);
|
|
8377
|
+
/**
|
|
8378
|
+
* Executes a `left join lateral` operation by adding subquery to the current query.
|
|
8379
|
+
*
|
|
8380
|
+
* A `lateral` join allows the right-hand expression to refer to columns from the left-hand side.
|
|
8381
|
+
*
|
|
8382
|
+
* Calling this method associates each row of the table with the corresponding row from the joined table, if a match is found. If no matching row exists, it sets all columns of the joined table to null.
|
|
8383
|
+
*
|
|
8384
|
+
* See docs: {@link https://orm.drizzle.team/docs/joins#left-join-lateral}
|
|
8385
|
+
*
|
|
8386
|
+
* @param table the subquery to join.
|
|
8387
|
+
* @param on the `on` clause.
|
|
8388
|
+
*/
|
|
8389
|
+
leftJoinLateral = this.createJoin("left", true);
|
|
8390
|
+
/**
|
|
8391
|
+
* Executes a `right join` operation by adding another table to the current query.
|
|
8392
|
+
*
|
|
8393
|
+
* Calling this method associates each row of the joined table with the corresponding row from the main table, if a match is found. If no matching row exists, it sets all columns of the main table to null.
|
|
8394
|
+
*
|
|
8395
|
+
* See docs: {@link https://orm.drizzle.team/docs/joins#right-join}
|
|
8396
|
+
*
|
|
8397
|
+
* @param table the table to join.
|
|
8398
|
+
* @param on the `on` clause.
|
|
8399
|
+
*
|
|
8400
|
+
* @example
|
|
8401
|
+
*
|
|
8402
|
+
* ```ts
|
|
8403
|
+
* // Select all users and their pets
|
|
8404
|
+
* const usersWithPets: { user: User | null; pets: Pet; }[] = await db.select()
|
|
8405
|
+
* .from(users)
|
|
8406
|
+
* .rightJoin(pets, eq(users.id, pets.ownerId))
|
|
8407
|
+
*
|
|
8408
|
+
* // Select userId and petId
|
|
8409
|
+
* const usersIdsAndPetIds: { userId: number | null; petId: number; }[] = await db.select({
|
|
8410
|
+
* userId: users.id,
|
|
8411
|
+
* petId: pets.id,
|
|
8412
|
+
* })
|
|
8413
|
+
* .from(users)
|
|
8414
|
+
* .rightJoin(pets, eq(users.id, pets.ownerId))
|
|
8415
|
+
* ```
|
|
8416
|
+
*/
|
|
8417
|
+
rightJoin = this.createJoin("right", false);
|
|
8418
|
+
/**
|
|
8419
|
+
* Executes an `inner join` operation, creating a new table by combining rows from two tables that have matching values.
|
|
8420
|
+
*
|
|
8421
|
+
* Calling this method retrieves rows that have corresponding entries in both joined tables. Rows without matching entries in either table are excluded, resulting in a table that includes only matching pairs.
|
|
8422
|
+
*
|
|
8423
|
+
* See docs: {@link https://orm.drizzle.team/docs/joins#inner-join}
|
|
8424
|
+
*
|
|
8425
|
+
* @param table the table to join.
|
|
8426
|
+
* @param on the `on` clause.
|
|
8427
|
+
*
|
|
8428
|
+
* @example
|
|
8429
|
+
*
|
|
8430
|
+
* ```ts
|
|
8431
|
+
* // Select all users and their pets
|
|
8432
|
+
* const usersWithPets: { user: User; pets: Pet; }[] = await db.select()
|
|
8433
|
+
* .from(users)
|
|
8434
|
+
* .innerJoin(pets, eq(users.id, pets.ownerId))
|
|
8435
|
+
*
|
|
8436
|
+
* // Select userId and petId
|
|
8437
|
+
* const usersIdsAndPetIds: { userId: number; petId: number; }[] = await db.select({
|
|
8438
|
+
* userId: users.id,
|
|
8439
|
+
* petId: pets.id,
|
|
8440
|
+
* })
|
|
8441
|
+
* .from(users)
|
|
8442
|
+
* .innerJoin(pets, eq(users.id, pets.ownerId))
|
|
8443
|
+
* ```
|
|
8444
|
+
*/
|
|
8445
|
+
innerJoin = this.createJoin("inner", false);
|
|
8446
|
+
/**
|
|
8447
|
+
* Executes an `inner join lateral` operation, creating a new table by combining rows from two queries that have matching values.
|
|
8448
|
+
*
|
|
8449
|
+
* A `lateral` join allows the right-hand expression to refer to columns from the left-hand side.
|
|
8450
|
+
*
|
|
8451
|
+
* Calling this method retrieves rows that have corresponding entries in both joined tables. Rows without matching entries in either table are excluded, resulting in a table that includes only matching pairs.
|
|
8452
|
+
*
|
|
8453
|
+
* See docs: {@link https://orm.drizzle.team/docs/joins#inner-join-lateral}
|
|
8454
|
+
*
|
|
8455
|
+
* @param table the subquery to join.
|
|
8456
|
+
* @param on the `on` clause.
|
|
8457
|
+
*/
|
|
8458
|
+
innerJoinLateral = this.createJoin("inner", true);
|
|
8459
|
+
/**
|
|
8460
|
+
* Executes a `full join` operation by combining rows from two tables into a new table.
|
|
8461
|
+
*
|
|
8462
|
+
* Calling this method retrieves all rows from both main and joined tables, merging rows with matching values and filling in `null` for non-matching columns.
|
|
8463
|
+
*
|
|
8464
|
+
* See docs: {@link https://orm.drizzle.team/docs/joins#full-join}
|
|
8465
|
+
*
|
|
8466
|
+
* @param table the table to join.
|
|
8467
|
+
* @param on the `on` clause.
|
|
8468
|
+
*
|
|
8469
|
+
* @example
|
|
8470
|
+
*
|
|
8471
|
+
* ```ts
|
|
8472
|
+
* // Select all users and their pets
|
|
8473
|
+
* const usersWithPets: { user: User | null; pets: Pet | null; }[] = await db.select()
|
|
8474
|
+
* .from(users)
|
|
8475
|
+
* .fullJoin(pets, eq(users.id, pets.ownerId))
|
|
8476
|
+
*
|
|
8477
|
+
* // Select userId and petId
|
|
8478
|
+
* const usersIdsAndPetIds: { userId: number | null; petId: number | null; }[] = await db.select({
|
|
8479
|
+
* userId: users.id,
|
|
8480
|
+
* petId: pets.id,
|
|
8481
|
+
* })
|
|
8482
|
+
* .from(users)
|
|
8483
|
+
* .fullJoin(pets, eq(users.id, pets.ownerId))
|
|
8484
|
+
* ```
|
|
8485
|
+
*/
|
|
8486
|
+
fullJoin = this.createJoin("full", false);
|
|
8487
|
+
/**
|
|
8488
|
+
* Executes a `cross join` operation by combining rows from two tables into a new table.
|
|
8489
|
+
*
|
|
8490
|
+
* Calling this method retrieves all rows from both main and joined tables, merging all rows from each table.
|
|
8491
|
+
*
|
|
8492
|
+
* See docs: {@link https://orm.drizzle.team/docs/joins#cross-join}
|
|
8493
|
+
*
|
|
8494
|
+
* @param table the table to join.
|
|
8495
|
+
*
|
|
8496
|
+
* @example
|
|
8497
|
+
*
|
|
8498
|
+
* ```ts
|
|
8499
|
+
* // Select all users, each user with every pet
|
|
8500
|
+
* const usersWithPets: { user: User; pets: Pet; }[] = await db.select()
|
|
8501
|
+
* .from(users)
|
|
8502
|
+
* .crossJoin(pets)
|
|
8503
|
+
*
|
|
8504
|
+
* // Select userId and petId
|
|
8505
|
+
* const usersIdsAndPetIds: { userId: number; petId: number; }[] = await db.select({
|
|
8506
|
+
* userId: users.id,
|
|
8507
|
+
* petId: pets.id,
|
|
8508
|
+
* })
|
|
8509
|
+
* .from(users)
|
|
8510
|
+
* .crossJoin(pets)
|
|
8511
|
+
* ```
|
|
8512
|
+
*/
|
|
8513
|
+
crossJoin = this.createJoin("cross", false);
|
|
8514
|
+
/**
|
|
8515
|
+
* Executes a `cross join lateral` operation by combining rows from two queries into a new table.
|
|
8516
|
+
*
|
|
8517
|
+
* A `lateral` join allows the right-hand expression to refer to columns from the left-hand side.
|
|
8518
|
+
*
|
|
8519
|
+
* Calling this method retrieves all rows from both main and joined queries, merging all rows from each query.
|
|
8520
|
+
*
|
|
8521
|
+
* See docs: {@link https://orm.drizzle.team/docs/joins#cross-join-lateral}
|
|
8522
|
+
*
|
|
8523
|
+
* @param table the query to join.
|
|
8524
|
+
*/
|
|
8525
|
+
crossJoinLateral = this.createJoin("cross", true);
|
|
8526
|
+
createSetOperator(type, isAll) {
|
|
8527
|
+
return (rightSelection) => {
|
|
8528
|
+
const rightSelect = typeof rightSelection === "function" ? rightSelection(getPgSetOperators()) : rightSelection;
|
|
8529
|
+
if (!haveSameKeys(this.getSelectedFields(), rightSelect.getSelectedFields())) {
|
|
8530
|
+
throw new Error(
|
|
8531
|
+
"Set operator error (union / intersect / except): selected fields are not the same or are in a different order"
|
|
8532
|
+
);
|
|
8533
|
+
}
|
|
8534
|
+
this.config.setOperators.push({ type, isAll, rightSelect });
|
|
8535
|
+
return this;
|
|
8536
|
+
};
|
|
8537
|
+
}
|
|
8538
|
+
/**
|
|
8539
|
+
* Adds `union` set operator to the query.
|
|
8540
|
+
*
|
|
8541
|
+
* Calling this method will combine the result sets of the `select` statements and remove any duplicate rows that appear across them.
|
|
8542
|
+
*
|
|
8543
|
+
* See docs: {@link https://orm.drizzle.team/docs/set-operations#union}
|
|
8544
|
+
*
|
|
8545
|
+
* @example
|
|
8546
|
+
*
|
|
8547
|
+
* ```ts
|
|
8548
|
+
* // Select all unique names from customers and users tables
|
|
8549
|
+
* await db.select({ name: users.name })
|
|
8550
|
+
* .from(users)
|
|
8551
|
+
* .union(
|
|
8552
|
+
* db.select({ name: customers.name }).from(customers)
|
|
8553
|
+
* );
|
|
8554
|
+
* // or
|
|
8555
|
+
* import { union } from 'drizzle-orm/pg-core'
|
|
8556
|
+
*
|
|
8557
|
+
* await union(
|
|
8558
|
+
* db.select({ name: users.name }).from(users),
|
|
8559
|
+
* db.select({ name: customers.name }).from(customers)
|
|
8560
|
+
* );
|
|
8561
|
+
* ```
|
|
8562
|
+
*/
|
|
8563
|
+
union = this.createSetOperator("union", false);
|
|
8564
|
+
/**
|
|
8565
|
+
* Adds `union all` set operator to the query.
|
|
8566
|
+
*
|
|
8567
|
+
* Calling this method will combine the result-set of the `select` statements and keep all duplicate rows that appear across them.
|
|
8568
|
+
*
|
|
8569
|
+
* See docs: {@link https://orm.drizzle.team/docs/set-operations#union-all}
|
|
8570
|
+
*
|
|
8571
|
+
* @example
|
|
8572
|
+
*
|
|
8573
|
+
* ```ts
|
|
8574
|
+
* // Select all transaction ids from both online and in-store sales
|
|
8575
|
+
* await db.select({ transaction: onlineSales.transactionId })
|
|
8576
|
+
* .from(onlineSales)
|
|
8577
|
+
* .unionAll(
|
|
8578
|
+
* db.select({ transaction: inStoreSales.transactionId }).from(inStoreSales)
|
|
8579
|
+
* );
|
|
8580
|
+
* // or
|
|
8581
|
+
* import { unionAll } from 'drizzle-orm/pg-core'
|
|
8582
|
+
*
|
|
8583
|
+
* await unionAll(
|
|
8584
|
+
* db.select({ transaction: onlineSales.transactionId }).from(onlineSales),
|
|
8585
|
+
* db.select({ transaction: inStoreSales.transactionId }).from(inStoreSales)
|
|
8586
|
+
* );
|
|
8587
|
+
* ```
|
|
8588
|
+
*/
|
|
8589
|
+
unionAll = this.createSetOperator("union", true);
|
|
8590
|
+
/**
|
|
8591
|
+
* Adds `intersect` set operator to the query.
|
|
8592
|
+
*
|
|
8593
|
+
* Calling this method will retain only the rows that are present in both result sets and eliminate duplicates.
|
|
8594
|
+
*
|
|
8595
|
+
* See docs: {@link https://orm.drizzle.team/docs/set-operations#intersect}
|
|
8596
|
+
*
|
|
8597
|
+
* @example
|
|
8598
|
+
*
|
|
8599
|
+
* ```ts
|
|
8600
|
+
* // Select course names that are offered in both departments A and B
|
|
8601
|
+
* await db.select({ courseName: depA.courseName })
|
|
8602
|
+
* .from(depA)
|
|
8603
|
+
* .intersect(
|
|
8604
|
+
* db.select({ courseName: depB.courseName }).from(depB)
|
|
8605
|
+
* );
|
|
8606
|
+
* // or
|
|
8607
|
+
* import { intersect } from 'drizzle-orm/pg-core'
|
|
8608
|
+
*
|
|
8609
|
+
* await intersect(
|
|
8610
|
+
* db.select({ courseName: depA.courseName }).from(depA),
|
|
8611
|
+
* db.select({ courseName: depB.courseName }).from(depB)
|
|
8612
|
+
* );
|
|
8613
|
+
* ```
|
|
8614
|
+
*/
|
|
8615
|
+
intersect = this.createSetOperator("intersect", false);
|
|
8616
|
+
/**
|
|
8617
|
+
* Adds `intersect all` set operator to the query.
|
|
8618
|
+
*
|
|
8619
|
+
* Calling this method will retain only the rows that are present in both result sets including all duplicates.
|
|
8620
|
+
*
|
|
8621
|
+
* See docs: {@link https://orm.drizzle.team/docs/set-operations#intersect-all}
|
|
8622
|
+
*
|
|
8623
|
+
* @example
|
|
8624
|
+
*
|
|
8625
|
+
* ```ts
|
|
8626
|
+
* // Select all products and quantities that are ordered by both regular and VIP customers
|
|
8627
|
+
* await db.select({
|
|
8628
|
+
* productId: regularCustomerOrders.productId,
|
|
8629
|
+
* quantityOrdered: regularCustomerOrders.quantityOrdered
|
|
8630
|
+
* })
|
|
8631
|
+
* .from(regularCustomerOrders)
|
|
8632
|
+
* .intersectAll(
|
|
8633
|
+
* db.select({
|
|
8634
|
+
* productId: vipCustomerOrders.productId,
|
|
8635
|
+
* quantityOrdered: vipCustomerOrders.quantityOrdered
|
|
8636
|
+
* })
|
|
8637
|
+
* .from(vipCustomerOrders)
|
|
8638
|
+
* );
|
|
8639
|
+
* // or
|
|
8640
|
+
* import { intersectAll } from 'drizzle-orm/pg-core'
|
|
8641
|
+
*
|
|
8642
|
+
* await intersectAll(
|
|
8643
|
+
* db.select({
|
|
8644
|
+
* productId: regularCustomerOrders.productId,
|
|
8645
|
+
* quantityOrdered: regularCustomerOrders.quantityOrdered
|
|
8646
|
+
* })
|
|
8647
|
+
* .from(regularCustomerOrders),
|
|
8648
|
+
* db.select({
|
|
8649
|
+
* productId: vipCustomerOrders.productId,
|
|
8650
|
+
* quantityOrdered: vipCustomerOrders.quantityOrdered
|
|
8651
|
+
* })
|
|
8652
|
+
* .from(vipCustomerOrders)
|
|
8653
|
+
* );
|
|
8654
|
+
* ```
|
|
8655
|
+
*/
|
|
8656
|
+
intersectAll = this.createSetOperator("intersect", true);
|
|
8657
|
+
/**
|
|
8658
|
+
* Adds `except` set operator to the query.
|
|
8659
|
+
*
|
|
8660
|
+
* Calling this method will retrieve all unique rows from the left query, except for the rows that are present in the result set of the right query.
|
|
8661
|
+
*
|
|
8662
|
+
* See docs: {@link https://orm.drizzle.team/docs/set-operations#except}
|
|
8663
|
+
*
|
|
8664
|
+
* @example
|
|
8665
|
+
*
|
|
8666
|
+
* ```ts
|
|
8667
|
+
* // Select all courses offered in department A but not in department B
|
|
8668
|
+
* await db.select({ courseName: depA.courseName })
|
|
8669
|
+
* .from(depA)
|
|
8670
|
+
* .except(
|
|
8671
|
+
* db.select({ courseName: depB.courseName }).from(depB)
|
|
8672
|
+
* );
|
|
8673
|
+
* // or
|
|
8674
|
+
* import { except } from 'drizzle-orm/pg-core'
|
|
8675
|
+
*
|
|
8676
|
+
* await except(
|
|
8677
|
+
* db.select({ courseName: depA.courseName }).from(depA),
|
|
8678
|
+
* db.select({ courseName: depB.courseName }).from(depB)
|
|
8679
|
+
* );
|
|
8680
|
+
* ```
|
|
8681
|
+
*/
|
|
8682
|
+
except = this.createSetOperator("except", false);
|
|
8683
|
+
/**
|
|
8684
|
+
* Adds `except all` set operator to the query.
|
|
8685
|
+
*
|
|
8686
|
+
* Calling this method will retrieve all rows from the left query, except for the rows that are present in the result set of the right query.
|
|
8687
|
+
*
|
|
8688
|
+
* See docs: {@link https://orm.drizzle.team/docs/set-operations#except-all}
|
|
8689
|
+
*
|
|
8690
|
+
* @example
|
|
8691
|
+
*
|
|
8692
|
+
* ```ts
|
|
8693
|
+
* // Select all products that are ordered by regular customers but not by VIP customers
|
|
8694
|
+
* await db.select({
|
|
8695
|
+
* productId: regularCustomerOrders.productId,
|
|
8696
|
+
* quantityOrdered: regularCustomerOrders.quantityOrdered,
|
|
8697
|
+
* })
|
|
8698
|
+
* .from(regularCustomerOrders)
|
|
8699
|
+
* .exceptAll(
|
|
8700
|
+
* db.select({
|
|
8701
|
+
* productId: vipCustomerOrders.productId,
|
|
8702
|
+
* quantityOrdered: vipCustomerOrders.quantityOrdered,
|
|
8703
|
+
* })
|
|
8704
|
+
* .from(vipCustomerOrders)
|
|
8705
|
+
* );
|
|
8706
|
+
* // or
|
|
8707
|
+
* import { exceptAll } from 'drizzle-orm/pg-core'
|
|
8708
|
+
*
|
|
8709
|
+
* await exceptAll(
|
|
8710
|
+
* db.select({
|
|
8711
|
+
* productId: regularCustomerOrders.productId,
|
|
8712
|
+
* quantityOrdered: regularCustomerOrders.quantityOrdered
|
|
8713
|
+
* })
|
|
8714
|
+
* .from(regularCustomerOrders),
|
|
8715
|
+
* db.select({
|
|
8716
|
+
* productId: vipCustomerOrders.productId,
|
|
8717
|
+
* quantityOrdered: vipCustomerOrders.quantityOrdered
|
|
8718
|
+
* })
|
|
8719
|
+
* .from(vipCustomerOrders)
|
|
8720
|
+
* );
|
|
8721
|
+
* ```
|
|
8722
|
+
*/
|
|
8723
|
+
exceptAll = this.createSetOperator("except", true);
|
|
8724
|
+
/** @internal */
|
|
8725
|
+
addSetOperators(setOperators) {
|
|
8726
|
+
this.config.setOperators.push(...setOperators);
|
|
8727
|
+
return this;
|
|
8728
|
+
}
|
|
8729
|
+
/**
|
|
8730
|
+
* Adds a `where` clause to the query.
|
|
8731
|
+
*
|
|
8732
|
+
* Calling this method will select only those rows that fulfill a specified condition.
|
|
8733
|
+
*
|
|
8734
|
+
* See docs: {@link https://orm.drizzle.team/docs/select#filtering}
|
|
8735
|
+
*
|
|
8736
|
+
* @param where the `where` clause.
|
|
8737
|
+
*
|
|
8738
|
+
* @example
|
|
8739
|
+
* You can use conditional operators and `sql function` to filter the rows to be selected.
|
|
8740
|
+
*
|
|
8741
|
+
* ```ts
|
|
8742
|
+
* // Select all cars with green color
|
|
8743
|
+
* await db.select().from(cars).where(eq(cars.color, 'green'));
|
|
8744
|
+
* // or
|
|
8745
|
+
* await db.select().from(cars).where(sql`${cars.color} = 'green'`)
|
|
8746
|
+
* ```
|
|
8747
|
+
*
|
|
8748
|
+
* You can logically combine conditional operators with `and()` and `or()` operators:
|
|
8749
|
+
*
|
|
8750
|
+
* ```ts
|
|
8751
|
+
* // Select all BMW cars with a green color
|
|
8752
|
+
* await db.select().from(cars).where(and(eq(cars.color, 'green'), eq(cars.brand, 'BMW')));
|
|
8753
|
+
*
|
|
8754
|
+
* // Select all cars with the green or blue color
|
|
8755
|
+
* await db.select().from(cars).where(or(eq(cars.color, 'green'), eq(cars.color, 'blue')));
|
|
8756
|
+
* ```
|
|
8757
|
+
*/
|
|
8758
|
+
where(where) {
|
|
8759
|
+
if (typeof where === "function") {
|
|
8760
|
+
where = where(
|
|
8761
|
+
new Proxy(
|
|
8762
|
+
this.config.fields,
|
|
8763
|
+
new SelectionProxyHandler({ sqlAliasedBehavior: "sql", sqlBehavior: "sql" })
|
|
8764
|
+
)
|
|
8765
|
+
);
|
|
8766
|
+
}
|
|
8767
|
+
this.config.where = where;
|
|
8768
|
+
return this;
|
|
8769
|
+
}
|
|
8770
|
+
/**
|
|
8771
|
+
* Adds a `having` clause to the query.
|
|
8772
|
+
*
|
|
8773
|
+
* Calling this method will select only those rows that fulfill a specified condition. It is typically used with aggregate functions to filter the aggregated data based on a specified condition.
|
|
8774
|
+
*
|
|
8775
|
+
* See docs: {@link https://orm.drizzle.team/docs/select#aggregations}
|
|
8776
|
+
*
|
|
8777
|
+
* @param having the `having` clause.
|
|
8778
|
+
*
|
|
8779
|
+
* @example
|
|
8780
|
+
*
|
|
8781
|
+
* ```ts
|
|
8782
|
+
* // Select all brands with more than one car
|
|
8783
|
+
* await db.select({
|
|
8784
|
+
* brand: cars.brand,
|
|
8785
|
+
* count: sql<number>`cast(count(${cars.id}) as int)`,
|
|
8786
|
+
* })
|
|
8787
|
+
* .from(cars)
|
|
8788
|
+
* .groupBy(cars.brand)
|
|
8789
|
+
* .having(({ count }) => gt(count, 1));
|
|
8790
|
+
* ```
|
|
8791
|
+
*/
|
|
8792
|
+
having(having) {
|
|
8793
|
+
if (typeof having === "function") {
|
|
8794
|
+
having = having(
|
|
8795
|
+
new Proxy(
|
|
8796
|
+
this.config.fields,
|
|
8797
|
+
new SelectionProxyHandler({ sqlAliasedBehavior: "sql", sqlBehavior: "sql" })
|
|
8798
|
+
)
|
|
8799
|
+
);
|
|
8800
|
+
}
|
|
8801
|
+
this.config.having = having;
|
|
8802
|
+
return this;
|
|
8803
|
+
}
|
|
8804
|
+
groupBy(...columns) {
|
|
8805
|
+
if (typeof columns[0] === "function") {
|
|
8806
|
+
const groupBy = columns[0](
|
|
8807
|
+
new Proxy(
|
|
8808
|
+
this.config.fields,
|
|
8809
|
+
new SelectionProxyHandler({ sqlAliasedBehavior: "alias", sqlBehavior: "sql" })
|
|
8810
|
+
)
|
|
8811
|
+
);
|
|
8812
|
+
this.config.groupBy = Array.isArray(groupBy) ? groupBy : [groupBy];
|
|
8813
|
+
} else {
|
|
8814
|
+
this.config.groupBy = columns;
|
|
8815
|
+
}
|
|
8816
|
+
return this;
|
|
8817
|
+
}
|
|
8818
|
+
orderBy(...columns) {
|
|
8819
|
+
if (typeof columns[0] === "function") {
|
|
8820
|
+
const orderBy = columns[0](
|
|
8821
|
+
new Proxy(
|
|
8822
|
+
this.config.fields,
|
|
8823
|
+
new SelectionProxyHandler({ sqlAliasedBehavior: "alias", sqlBehavior: "sql" })
|
|
8824
|
+
)
|
|
8825
|
+
);
|
|
8826
|
+
const orderByArray = Array.isArray(orderBy) ? orderBy : [orderBy];
|
|
8827
|
+
if (this.config.setOperators.length > 0) {
|
|
8828
|
+
this.config.setOperators.at(-1).orderBy = orderByArray;
|
|
8829
|
+
} else {
|
|
8830
|
+
this.config.orderBy = orderByArray;
|
|
8831
|
+
}
|
|
8832
|
+
} else {
|
|
8833
|
+
const orderByArray = columns;
|
|
8834
|
+
if (this.config.setOperators.length > 0) {
|
|
8835
|
+
this.config.setOperators.at(-1).orderBy = orderByArray;
|
|
8836
|
+
} else {
|
|
8837
|
+
this.config.orderBy = orderByArray;
|
|
8838
|
+
}
|
|
8839
|
+
}
|
|
8840
|
+
return this;
|
|
8841
|
+
}
|
|
8842
|
+
/**
|
|
8843
|
+
* Adds a `limit` clause to the query.
|
|
8844
|
+
*
|
|
8845
|
+
* Calling this method will set the maximum number of rows that will be returned by this query.
|
|
8846
|
+
*
|
|
8847
|
+
* See docs: {@link https://orm.drizzle.team/docs/select#limit--offset}
|
|
8848
|
+
*
|
|
8849
|
+
* @param limit the `limit` clause.
|
|
8850
|
+
*
|
|
8851
|
+
* @example
|
|
8852
|
+
*
|
|
8853
|
+
* ```ts
|
|
8854
|
+
* // Get the first 10 people from this query.
|
|
8855
|
+
* await db.select().from(people).limit(10);
|
|
8856
|
+
* ```
|
|
8857
|
+
*/
|
|
8858
|
+
limit(limit) {
|
|
8859
|
+
if (this.config.setOperators.length > 0) {
|
|
8860
|
+
this.config.setOperators.at(-1).limit = limit;
|
|
8861
|
+
} else {
|
|
8862
|
+
this.config.limit = limit;
|
|
8863
|
+
}
|
|
8864
|
+
return this;
|
|
8865
|
+
}
|
|
8866
|
+
/**
|
|
8867
|
+
* Adds an `offset` clause to the query.
|
|
8868
|
+
*
|
|
8869
|
+
* Calling this method will skip a number of rows when returning results from this query.
|
|
8870
|
+
*
|
|
8871
|
+
* See docs: {@link https://orm.drizzle.team/docs/select#limit--offset}
|
|
8872
|
+
*
|
|
8873
|
+
* @param offset the `offset` clause.
|
|
8874
|
+
*
|
|
8875
|
+
* @example
|
|
8876
|
+
*
|
|
8877
|
+
* ```ts
|
|
8878
|
+
* // Get the 10th-20th people from this query.
|
|
8879
|
+
* await db.select().from(people).offset(10).limit(10);
|
|
8880
|
+
* ```
|
|
8881
|
+
*/
|
|
8882
|
+
offset(offset) {
|
|
8883
|
+
if (this.config.setOperators.length > 0) {
|
|
8884
|
+
this.config.setOperators.at(-1).offset = offset;
|
|
8885
|
+
} else {
|
|
8886
|
+
this.config.offset = offset;
|
|
8887
|
+
}
|
|
8888
|
+
return this;
|
|
8889
|
+
}
|
|
8890
|
+
/**
|
|
8891
|
+
* Adds a `for` clause to the query.
|
|
8892
|
+
*
|
|
8893
|
+
* Calling this method will specify a lock strength for this query that controls how strictly it acquires exclusive access to the rows being queried.
|
|
8894
|
+
*
|
|
8895
|
+
* See docs: {@link https://www.postgresql.org/docs/current/sql-select.html#SQL-FOR-UPDATE-SHARE}
|
|
8896
|
+
*
|
|
8897
|
+
* @param strength the lock strength.
|
|
8898
|
+
* @param config the lock configuration.
|
|
8899
|
+
*/
|
|
8900
|
+
for(strength, config = {}) {
|
|
8901
|
+
this.config.lockingClause = { strength, config };
|
|
8902
|
+
return this;
|
|
8903
|
+
}
|
|
8904
|
+
/** @internal */
|
|
8905
|
+
getSQL() {
|
|
8906
|
+
return this.dialect.buildSelectQuery(this.config);
|
|
8907
|
+
}
|
|
8908
|
+
toSQL() {
|
|
8909
|
+
const { typings: _typings, ...rest } = this.dialect.sqlToQuery(this.getSQL());
|
|
8910
|
+
return rest;
|
|
8911
|
+
}
|
|
8912
|
+
as(alias) {
|
|
8913
|
+
const usedTables = [];
|
|
8914
|
+
usedTables.push(...extractUsedTable(this.config.table));
|
|
8915
|
+
if (this.config.joins) {
|
|
8916
|
+
for (const it of this.config.joins) usedTables.push(...extractUsedTable(it.table));
|
|
8917
|
+
}
|
|
8918
|
+
return new Proxy(
|
|
8919
|
+
new Subquery(this.getSQL(), this.config.fields, alias, false, [...new Set(usedTables)]),
|
|
8920
|
+
new SelectionProxyHandler({ alias, sqlAliasedBehavior: "alias", sqlBehavior: "error" })
|
|
8921
|
+
);
|
|
8922
|
+
}
|
|
8923
|
+
/** @internal */
|
|
8924
|
+
getSelectedFields() {
|
|
8925
|
+
return new Proxy(
|
|
8926
|
+
this.config.fields,
|
|
8927
|
+
new SelectionProxyHandler({ alias: this.tableName, sqlAliasedBehavior: "alias", sqlBehavior: "error" })
|
|
8928
|
+
);
|
|
8929
|
+
}
|
|
8930
|
+
$dynamic() {
|
|
8931
|
+
return this;
|
|
8932
|
+
}
|
|
8933
|
+
$withCache(config) {
|
|
8934
|
+
this.cacheConfig = config === void 0 ? { config: {}, enable: true, autoInvalidate: true } : config === false ? { enable: false } : { enable: true, autoInvalidate: true, ...config };
|
|
8935
|
+
return this;
|
|
8936
|
+
}
|
|
8937
|
+
}
|
|
8938
|
+
class PgSelectBase extends PgSelectQueryBuilderBase {
|
|
8939
|
+
static [entityKind] = "PgSelect";
|
|
8940
|
+
/** @internal */
|
|
8941
|
+
_prepare(name) {
|
|
8942
|
+
const { session, config, dialect, joinsNotNullableMap, authToken, cacheConfig, usedTables } = this;
|
|
8943
|
+
if (!session) {
|
|
8944
|
+
throw new Error("Cannot execute a query on a query builder. Please use a database instance instead.");
|
|
8945
|
+
}
|
|
8946
|
+
const { fields } = config;
|
|
8947
|
+
return tracer.startActiveSpan("drizzle.prepareQuery", () => {
|
|
8948
|
+
const fieldsList = orderSelectedFields(fields);
|
|
8949
|
+
const query = session.prepareQuery(dialect.sqlToQuery(this.getSQL()), fieldsList, name, true, void 0, {
|
|
8950
|
+
type: "select",
|
|
8951
|
+
tables: [...usedTables]
|
|
8952
|
+
}, cacheConfig);
|
|
8953
|
+
query.joinsNotNullableMap = joinsNotNullableMap;
|
|
8954
|
+
return query.setToken(authToken);
|
|
8955
|
+
});
|
|
8956
|
+
}
|
|
8957
|
+
/**
|
|
8958
|
+
* Create a prepared statement for this query. This allows
|
|
8959
|
+
* the database to remember this query for the given session
|
|
8960
|
+
* and call it by name, rather than specifying the full query.
|
|
8961
|
+
*
|
|
8962
|
+
* {@link https://www.postgresql.org/docs/current/sql-prepare.html | Postgres prepare documentation}
|
|
8963
|
+
*/
|
|
8964
|
+
prepare(name) {
|
|
8965
|
+
return this._prepare(name);
|
|
8966
|
+
}
|
|
8967
|
+
authToken;
|
|
8968
|
+
/** @internal */
|
|
8969
|
+
setToken(token) {
|
|
8970
|
+
this.authToken = token;
|
|
8971
|
+
return this;
|
|
8972
|
+
}
|
|
8973
|
+
execute = (placeholderValues) => {
|
|
8974
|
+
return tracer.startActiveSpan("drizzle.operation", () => {
|
|
8975
|
+
return this._prepare().execute(placeholderValues, this.authToken);
|
|
8976
|
+
});
|
|
8977
|
+
};
|
|
8978
|
+
}
|
|
8979
|
+
applyMixins(PgSelectBase, [QueryPromise]);
|
|
8980
|
+
function createSetOperator(type, isAll) {
|
|
8981
|
+
return (leftSelect, rightSelect, ...restSelects) => {
|
|
8982
|
+
const setOperators = [rightSelect, ...restSelects].map((select) => ({
|
|
8983
|
+
type,
|
|
8984
|
+
isAll,
|
|
8985
|
+
rightSelect: select
|
|
8986
|
+
}));
|
|
8987
|
+
for (const setOperator of setOperators) {
|
|
8988
|
+
if (!haveSameKeys(leftSelect.getSelectedFields(), setOperator.rightSelect.getSelectedFields())) {
|
|
8989
|
+
throw new Error(
|
|
8990
|
+
"Set operator error (union / intersect / except): selected fields are not the same or are in a different order"
|
|
8991
|
+
);
|
|
8992
|
+
}
|
|
8993
|
+
}
|
|
8994
|
+
return leftSelect.addSetOperators(setOperators);
|
|
8995
|
+
};
|
|
8996
|
+
}
|
|
8997
|
+
const getPgSetOperators = () => ({
|
|
8998
|
+
union,
|
|
8999
|
+
unionAll,
|
|
9000
|
+
intersect,
|
|
9001
|
+
intersectAll,
|
|
9002
|
+
except,
|
|
9003
|
+
exceptAll
|
|
9004
|
+
});
|
|
9005
|
+
const union = createSetOperator("union", false);
|
|
9006
|
+
const unionAll = createSetOperator("union", true);
|
|
9007
|
+
const intersect = createSetOperator("intersect", false);
|
|
9008
|
+
const intersectAll = createSetOperator("intersect", true);
|
|
9009
|
+
const except = createSetOperator("except", false);
|
|
9010
|
+
const exceptAll = createSetOperator("except", true);
|
|
9011
|
+
|
|
9012
|
+
class QueryBuilder {
|
|
9013
|
+
static [entityKind] = "PgQueryBuilder";
|
|
9014
|
+
dialect;
|
|
9015
|
+
dialectConfig;
|
|
9016
|
+
constructor(dialect) {
|
|
9017
|
+
this.dialect = is(dialect, PgDialect) ? dialect : void 0;
|
|
9018
|
+
this.dialectConfig = is(dialect, PgDialect) ? void 0 : dialect;
|
|
9019
|
+
}
|
|
9020
|
+
$with = (alias, selection) => {
|
|
9021
|
+
const queryBuilder = this;
|
|
9022
|
+
const as = (qb) => {
|
|
9023
|
+
if (typeof qb === "function") {
|
|
9024
|
+
qb = qb(queryBuilder);
|
|
9025
|
+
}
|
|
9026
|
+
return new Proxy(
|
|
9027
|
+
new WithSubquery(
|
|
9028
|
+
qb.getSQL(),
|
|
9029
|
+
selection ?? ("getSelectedFields" in qb ? qb.getSelectedFields() ?? {} : {}),
|
|
9030
|
+
alias,
|
|
9031
|
+
true
|
|
9032
|
+
),
|
|
9033
|
+
new SelectionProxyHandler({ alias, sqlAliasedBehavior: "alias", sqlBehavior: "error" })
|
|
9034
|
+
);
|
|
9035
|
+
};
|
|
9036
|
+
return { as };
|
|
9037
|
+
};
|
|
9038
|
+
with(...queries) {
|
|
9039
|
+
const self = this;
|
|
9040
|
+
function select(fields) {
|
|
9041
|
+
return new PgSelectBuilder({
|
|
9042
|
+
fields: fields ?? void 0,
|
|
9043
|
+
session: void 0,
|
|
9044
|
+
dialect: self.getDialect(),
|
|
9045
|
+
withList: queries
|
|
9046
|
+
});
|
|
9047
|
+
}
|
|
9048
|
+
function selectDistinct(fields) {
|
|
9049
|
+
return new PgSelectBuilder({
|
|
9050
|
+
fields: fields ?? void 0,
|
|
9051
|
+
session: void 0,
|
|
9052
|
+
dialect: self.getDialect(),
|
|
9053
|
+
distinct: true
|
|
9054
|
+
});
|
|
9055
|
+
}
|
|
9056
|
+
function selectDistinctOn(on, fields) {
|
|
9057
|
+
return new PgSelectBuilder({
|
|
9058
|
+
fields: fields ?? void 0,
|
|
9059
|
+
session: void 0,
|
|
9060
|
+
dialect: self.getDialect(),
|
|
9061
|
+
distinct: { on }
|
|
9062
|
+
});
|
|
9063
|
+
}
|
|
9064
|
+
return { select, selectDistinct, selectDistinctOn };
|
|
9065
|
+
}
|
|
9066
|
+
select(fields) {
|
|
9067
|
+
return new PgSelectBuilder({
|
|
9068
|
+
fields: fields ?? void 0,
|
|
9069
|
+
session: void 0,
|
|
9070
|
+
dialect: this.getDialect()
|
|
9071
|
+
});
|
|
9072
|
+
}
|
|
9073
|
+
selectDistinct(fields) {
|
|
9074
|
+
return new PgSelectBuilder({
|
|
9075
|
+
fields: fields ?? void 0,
|
|
9076
|
+
session: void 0,
|
|
9077
|
+
dialect: this.getDialect(),
|
|
9078
|
+
distinct: true
|
|
9079
|
+
});
|
|
9080
|
+
}
|
|
9081
|
+
selectDistinctOn(on, fields) {
|
|
9082
|
+
return new PgSelectBuilder({
|
|
9083
|
+
fields: fields ?? void 0,
|
|
9084
|
+
session: void 0,
|
|
9085
|
+
dialect: this.getDialect(),
|
|
9086
|
+
distinct: { on }
|
|
9087
|
+
});
|
|
9088
|
+
}
|
|
9089
|
+
// Lazy load dialect to avoid circular dependency
|
|
9090
|
+
getDialect() {
|
|
9091
|
+
if (!this.dialect) {
|
|
9092
|
+
this.dialect = new PgDialect(this.dialectConfig);
|
|
9093
|
+
}
|
|
9094
|
+
return this.dialect;
|
|
9095
|
+
}
|
|
9096
|
+
}
|
|
9097
|
+
|
|
9098
|
+
class DefaultViewBuilderCore {
|
|
9099
|
+
constructor(name, schema) {
|
|
9100
|
+
this.name = name;
|
|
9101
|
+
this.schema = schema;
|
|
9102
|
+
}
|
|
9103
|
+
static [entityKind] = "PgDefaultViewBuilderCore";
|
|
9104
|
+
config = {};
|
|
9105
|
+
with(config) {
|
|
9106
|
+
this.config.with = config;
|
|
9107
|
+
return this;
|
|
9108
|
+
}
|
|
9109
|
+
}
|
|
9110
|
+
class ViewBuilder extends DefaultViewBuilderCore {
|
|
9111
|
+
static [entityKind] = "PgViewBuilder";
|
|
9112
|
+
as(qb) {
|
|
9113
|
+
if (typeof qb === "function") {
|
|
9114
|
+
qb = qb(new QueryBuilder());
|
|
9115
|
+
}
|
|
9116
|
+
const selectionProxy = new SelectionProxyHandler({
|
|
9117
|
+
alias: this.name,
|
|
9118
|
+
sqlBehavior: "error",
|
|
9119
|
+
sqlAliasedBehavior: "alias",
|
|
9120
|
+
replaceOriginalName: true
|
|
9121
|
+
});
|
|
9122
|
+
const aliasedSelection = new Proxy(qb.getSelectedFields(), selectionProxy);
|
|
9123
|
+
return new Proxy(
|
|
9124
|
+
new PgView({
|
|
9125
|
+
pgConfig: this.config,
|
|
9126
|
+
config: {
|
|
9127
|
+
name: this.name,
|
|
9128
|
+
schema: this.schema,
|
|
9129
|
+
selectedFields: aliasedSelection,
|
|
9130
|
+
query: qb.getSQL().inlineParams()
|
|
9131
|
+
}
|
|
9132
|
+
}),
|
|
9133
|
+
selectionProxy
|
|
9134
|
+
);
|
|
9135
|
+
}
|
|
9136
|
+
}
|
|
9137
|
+
class ManualViewBuilder extends DefaultViewBuilderCore {
|
|
9138
|
+
static [entityKind] = "PgManualViewBuilder";
|
|
9139
|
+
columns;
|
|
9140
|
+
constructor(name, columns, schema) {
|
|
9141
|
+
super(name, schema);
|
|
9142
|
+
this.columns = getTableColumns(pgTable(name, columns));
|
|
9143
|
+
}
|
|
9144
|
+
existing() {
|
|
9145
|
+
return new Proxy(
|
|
9146
|
+
new PgView({
|
|
9147
|
+
pgConfig: void 0,
|
|
9148
|
+
config: {
|
|
9149
|
+
name: this.name,
|
|
9150
|
+
schema: this.schema,
|
|
9151
|
+
selectedFields: this.columns,
|
|
9152
|
+
query: void 0
|
|
9153
|
+
}
|
|
9154
|
+
}),
|
|
9155
|
+
new SelectionProxyHandler({
|
|
9156
|
+
alias: this.name,
|
|
9157
|
+
sqlBehavior: "error",
|
|
9158
|
+
sqlAliasedBehavior: "alias",
|
|
9159
|
+
replaceOriginalName: true
|
|
9160
|
+
})
|
|
9161
|
+
);
|
|
9162
|
+
}
|
|
9163
|
+
as(query) {
|
|
9164
|
+
return new Proxy(
|
|
9165
|
+
new PgView({
|
|
9166
|
+
pgConfig: this.config,
|
|
9167
|
+
config: {
|
|
9168
|
+
name: this.name,
|
|
9169
|
+
schema: this.schema,
|
|
9170
|
+
selectedFields: this.columns,
|
|
9171
|
+
query: query.inlineParams()
|
|
9172
|
+
}
|
|
9173
|
+
}),
|
|
9174
|
+
new SelectionProxyHandler({
|
|
9175
|
+
alias: this.name,
|
|
9176
|
+
sqlBehavior: "error",
|
|
9177
|
+
sqlAliasedBehavior: "alias",
|
|
9178
|
+
replaceOriginalName: true
|
|
9179
|
+
})
|
|
9180
|
+
);
|
|
9181
|
+
}
|
|
9182
|
+
}
|
|
9183
|
+
class MaterializedViewBuilderCore {
|
|
9184
|
+
constructor(name, schema) {
|
|
9185
|
+
this.name = name;
|
|
9186
|
+
this.schema = schema;
|
|
9187
|
+
}
|
|
9188
|
+
static [entityKind] = "PgMaterializedViewBuilderCore";
|
|
9189
|
+
config = {};
|
|
9190
|
+
using(using) {
|
|
9191
|
+
this.config.using = using;
|
|
9192
|
+
return this;
|
|
9193
|
+
}
|
|
9194
|
+
with(config) {
|
|
9195
|
+
this.config.with = config;
|
|
9196
|
+
return this;
|
|
9197
|
+
}
|
|
9198
|
+
tablespace(tablespace) {
|
|
9199
|
+
this.config.tablespace = tablespace;
|
|
9200
|
+
return this;
|
|
9201
|
+
}
|
|
9202
|
+
withNoData() {
|
|
9203
|
+
this.config.withNoData = true;
|
|
9204
|
+
return this;
|
|
9205
|
+
}
|
|
9206
|
+
}
|
|
9207
|
+
class MaterializedViewBuilder extends MaterializedViewBuilderCore {
|
|
9208
|
+
static [entityKind] = "PgMaterializedViewBuilder";
|
|
9209
|
+
as(qb) {
|
|
9210
|
+
if (typeof qb === "function") {
|
|
9211
|
+
qb = qb(new QueryBuilder());
|
|
9212
|
+
}
|
|
9213
|
+
const selectionProxy = new SelectionProxyHandler({
|
|
9214
|
+
alias: this.name,
|
|
9215
|
+
sqlBehavior: "error",
|
|
9216
|
+
sqlAliasedBehavior: "alias",
|
|
9217
|
+
replaceOriginalName: true
|
|
9218
|
+
});
|
|
9219
|
+
const aliasedSelection = new Proxy(qb.getSelectedFields(), selectionProxy);
|
|
9220
|
+
return new Proxy(
|
|
9221
|
+
new PgMaterializedView({
|
|
9222
|
+
pgConfig: {
|
|
9223
|
+
with: this.config.with,
|
|
9224
|
+
using: this.config.using,
|
|
9225
|
+
tablespace: this.config.tablespace,
|
|
9226
|
+
withNoData: this.config.withNoData
|
|
9227
|
+
},
|
|
9228
|
+
config: {
|
|
9229
|
+
name: this.name,
|
|
9230
|
+
schema: this.schema,
|
|
9231
|
+
selectedFields: aliasedSelection,
|
|
9232
|
+
query: qb.getSQL().inlineParams()
|
|
9233
|
+
}
|
|
9234
|
+
}),
|
|
9235
|
+
selectionProxy
|
|
9236
|
+
);
|
|
9237
|
+
}
|
|
9238
|
+
}
|
|
9239
|
+
class ManualMaterializedViewBuilder extends MaterializedViewBuilderCore {
|
|
9240
|
+
static [entityKind] = "PgManualMaterializedViewBuilder";
|
|
9241
|
+
columns;
|
|
9242
|
+
constructor(name, columns, schema) {
|
|
9243
|
+
super(name, schema);
|
|
9244
|
+
this.columns = getTableColumns(pgTable(name, columns));
|
|
9245
|
+
}
|
|
9246
|
+
existing() {
|
|
9247
|
+
return new Proxy(
|
|
9248
|
+
new PgMaterializedView({
|
|
9249
|
+
pgConfig: {
|
|
9250
|
+
tablespace: this.config.tablespace,
|
|
9251
|
+
using: this.config.using,
|
|
9252
|
+
with: this.config.with,
|
|
9253
|
+
withNoData: this.config.withNoData
|
|
9254
|
+
},
|
|
9255
|
+
config: {
|
|
9256
|
+
name: this.name,
|
|
9257
|
+
schema: this.schema,
|
|
9258
|
+
selectedFields: this.columns,
|
|
9259
|
+
query: void 0
|
|
9260
|
+
}
|
|
9261
|
+
}),
|
|
9262
|
+
new SelectionProxyHandler({
|
|
9263
|
+
alias: this.name,
|
|
9264
|
+
sqlBehavior: "error",
|
|
9265
|
+
sqlAliasedBehavior: "alias",
|
|
9266
|
+
replaceOriginalName: true
|
|
9267
|
+
})
|
|
9268
|
+
);
|
|
9269
|
+
}
|
|
9270
|
+
as(query) {
|
|
9271
|
+
return new Proxy(
|
|
9272
|
+
new PgMaterializedView({
|
|
9273
|
+
pgConfig: {
|
|
9274
|
+
tablespace: this.config.tablespace,
|
|
9275
|
+
using: this.config.using,
|
|
9276
|
+
with: this.config.with,
|
|
9277
|
+
withNoData: this.config.withNoData
|
|
9278
|
+
},
|
|
9279
|
+
config: {
|
|
9280
|
+
name: this.name,
|
|
9281
|
+
schema: this.schema,
|
|
9282
|
+
selectedFields: this.columns,
|
|
9283
|
+
query: query.inlineParams()
|
|
9284
|
+
}
|
|
9285
|
+
}),
|
|
9286
|
+
new SelectionProxyHandler({
|
|
9287
|
+
alias: this.name,
|
|
9288
|
+
sqlBehavior: "error",
|
|
9289
|
+
sqlAliasedBehavior: "alias",
|
|
9290
|
+
replaceOriginalName: true
|
|
9291
|
+
})
|
|
9292
|
+
);
|
|
9293
|
+
}
|
|
9294
|
+
}
|
|
9295
|
+
class PgView extends PgViewBase {
|
|
9296
|
+
static [entityKind] = "PgView";
|
|
9297
|
+
[PgViewConfig];
|
|
9298
|
+
constructor({ pgConfig, config }) {
|
|
9299
|
+
super(config);
|
|
9300
|
+
if (pgConfig) {
|
|
9301
|
+
this[PgViewConfig] = {
|
|
9302
|
+
with: pgConfig.with
|
|
9303
|
+
};
|
|
9304
|
+
}
|
|
9305
|
+
}
|
|
9306
|
+
}
|
|
9307
|
+
const PgMaterializedViewConfig = Symbol.for("drizzle:PgMaterializedViewConfig");
|
|
9308
|
+
class PgMaterializedView extends PgViewBase {
|
|
9309
|
+
static [entityKind] = "PgMaterializedView";
|
|
9310
|
+
[PgMaterializedViewConfig];
|
|
9311
|
+
constructor({ pgConfig, config }) {
|
|
9312
|
+
super(config);
|
|
9313
|
+
this[PgMaterializedViewConfig] = {
|
|
9314
|
+
with: pgConfig?.with,
|
|
9315
|
+
using: pgConfig?.using,
|
|
9316
|
+
tablespace: pgConfig?.tablespace,
|
|
9317
|
+
withNoData: pgConfig?.withNoData
|
|
9318
|
+
};
|
|
9319
|
+
}
|
|
9320
|
+
}
|
|
9321
|
+
function pgViewWithSchema(name, selection, schema) {
|
|
9322
|
+
if (selection) {
|
|
9323
|
+
return new ManualViewBuilder(name, selection, schema);
|
|
9324
|
+
}
|
|
9325
|
+
return new ViewBuilder(name, schema);
|
|
9326
|
+
}
|
|
9327
|
+
function pgMaterializedViewWithSchema(name, selection, schema) {
|
|
9328
|
+
if (selection) {
|
|
9329
|
+
return new ManualMaterializedViewBuilder(name, selection, schema);
|
|
9330
|
+
}
|
|
9331
|
+
return new MaterializedViewBuilder(name, schema);
|
|
9332
|
+
}
|
|
9333
|
+
function pgView(name, columns) {
|
|
9334
|
+
return pgViewWithSchema(name, columns, void 0);
|
|
9335
|
+
}
|
|
9336
|
+
function pgMaterializedView(name, columns) {
|
|
9337
|
+
return pgMaterializedViewWithSchema(name, columns, void 0);
|
|
9338
|
+
}
|
|
9339
|
+
|
|
9340
|
+
function extractUsedTable(table) {
|
|
9341
|
+
if (is(table, PgTable)) {
|
|
9342
|
+
return [table[Schema] ? `${table[Schema]}.${table[Table.Symbol.BaseName]}` : table[Table.Symbol.BaseName]];
|
|
9343
|
+
}
|
|
9344
|
+
if (is(table, Subquery)) {
|
|
9345
|
+
return table._.usedTables ?? [];
|
|
9346
|
+
}
|
|
9347
|
+
if (is(table, SQL)) {
|
|
9348
|
+
return table.usedTables ?? [];
|
|
9349
|
+
}
|
|
9350
|
+
return [];
|
|
9351
|
+
}
|
|
9352
|
+
|
|
9353
|
+
class PgSequence {
|
|
9354
|
+
constructor(seqName, seqOptions, schema) {
|
|
9355
|
+
this.seqName = seqName;
|
|
9356
|
+
this.seqOptions = seqOptions;
|
|
9357
|
+
this.schema = schema;
|
|
9358
|
+
}
|
|
9359
|
+
static [entityKind] = "PgSequence";
|
|
9360
|
+
}
|
|
9361
|
+
function pgSequenceWithSchema(name, options, schema) {
|
|
9362
|
+
return new PgSequence(name, options, schema);
|
|
9363
|
+
}
|
|
9364
|
+
|
|
9365
|
+
class PgSchema {
|
|
9366
|
+
constructor(schemaName) {
|
|
9367
|
+
this.schemaName = schemaName;
|
|
9368
|
+
}
|
|
9369
|
+
static [entityKind] = "PgSchema";
|
|
9370
|
+
table = (name, columns, extraConfig) => {
|
|
9371
|
+
return pgTableWithSchema(name, columns, extraConfig, this.schemaName);
|
|
9372
|
+
};
|
|
9373
|
+
view = (name, columns) => {
|
|
9374
|
+
return pgViewWithSchema(name, columns, this.schemaName);
|
|
9375
|
+
};
|
|
9376
|
+
materializedView = (name, columns) => {
|
|
9377
|
+
return pgMaterializedViewWithSchema(name, columns, this.schemaName);
|
|
9378
|
+
};
|
|
9379
|
+
enum(enumName, input) {
|
|
9380
|
+
return Array.isArray(input) ? pgEnumWithSchema(
|
|
9381
|
+
enumName,
|
|
9382
|
+
[...input],
|
|
9383
|
+
this.schemaName
|
|
9384
|
+
) : pgEnumObjectWithSchema(enumName, input, this.schemaName);
|
|
9385
|
+
}
|
|
9386
|
+
sequence = (name, options) => {
|
|
9387
|
+
return pgSequenceWithSchema(name, options, this.schemaName);
|
|
9388
|
+
};
|
|
9389
|
+
getSQL() {
|
|
9390
|
+
return new SQL([sql.identifier(this.schemaName)]);
|
|
9391
|
+
}
|
|
9392
|
+
shouldOmitSQLParens() {
|
|
9393
|
+
return true;
|
|
9394
|
+
}
|
|
9395
|
+
}
|
|
9396
|
+
function pgSchema(name) {
|
|
9397
|
+
if (name === "public") {
|
|
9398
|
+
throw new Error(
|
|
9399
|
+
`You can't specify 'public' as schema name. Postgres is using public schema by default. If you want to use 'public' schema, just use pgTable() instead of creating a schema`
|
|
9400
|
+
);
|
|
9401
|
+
}
|
|
9402
|
+
return new PgSchema(name);
|
|
9403
|
+
}
|
|
9404
|
+
|
|
9405
|
+
export { ClickHouseConnector, CoreSqlTypes, DBConnector, DBError, DBNoSQLType, DBOLAPType, DBSQLType, DrizzlePostgresConnector, DrizzleSQLType, DrizzleSqlConnector, MySQLConnectionError, NoSQLConnector, OLAPConnector, SqlConnector, bigint, bigserial, boolean, char, check, cidr, date, decimal, doublePrecision, foreignKey, geometry, index, inet, integer, interval, json, jsonb, line, macaddr, macaddr8, numeric, pgEnum, pgMaterializedView, pgSchema, pgTable, pgView, point, primaryKey, real, serial, smallint, smallserial, text, time, timestamp, unique, uniqueIndex, uuid, varchar };
|