CoolFace
Apppublic

AK-21/Graphite-Industrial-Intelligence

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
dialect.js1123 linesDownload Raw Back to gel-core
1import { aliasedTable, aliasedTableColumn, mapColumnsInAliasedSQLToAlias, mapColumnsInSQLToAlias } from "../alias.js";2import { CasingCache } from "../casing.js";3import { Column } from "../column.js";4import { entityKind, is } from "../entity.js";5import { DrizzleError } from "../errors.js";6import { GelColumn, GelDecimal, GelJson, GelUUID } from "./columns/index.js";7import { GelTable } from "./table.js";8import {9  getOperators,10  getOrderByOperators,11  Many,12  normalizeRelation,13  One14} from "../relations.js";15import { and, eq, View } from "../sql/index.js";16import {17  Param,18  SQL,19  sql20} from "../sql/sql.js";21import { Subquery } from "../subquery.js";22import { getTableName, getTableUniqueName, Table } from "../table.js";23import { orderSelectedFields } from "../utils.js";24import { ViewBaseConfig } from "../view-common.js";25import { GelTimestamp } from "./columns/timestamp.js";26import { GelViewBase } from "./view-base.js";27class GelDialect {28  static [entityKind] = "GelDialect";29  /** @internal */30  casing;31  constructor(config) {32    this.casing = new CasingCache(config?.casing);33  }34  // TODO can not migrate gel with drizzle35  // async migrate(migrations: MigrationMeta[], session: GelSession, config: string | MigrationConfig): Promise<void> {36  // 	const migrationsTable = typeof config === 'string'37  // 		? '__drizzle_migrations'38  // 		: config.migrationsTable ?? '__drizzle_migrations';39  // 	const migrationsSchema = typeof config === 'string' ? 'drizzle' : config.migrationsSchema ?? 'drizzle';40  // 	const migrationTableCreate = sql`41  // 		CREATE TABLE IF NOT EXISTS ${sql.identifier(migrationsSchema)}.${sql.identifier(migrationsTable)} (42  // 			id SERIAL PRIMARY KEY,43  // 			hash text NOT NULL,44  // 			created_at bigint45  // 		)46  // 	`;47  // 	await session.execute(sql`CREATE SCHEMA IF NOT EXISTS ${sql.identifier(migrationsSchema)}`);48  // 	await session.execute(migrationTableCreate);49  // 	const dbMigrations = await session.all<{ id: number; hash: string; created_at: string }>(50  // 		sql`select id, hash, created_at from ${sql.identifier(migrationsSchema)}.${51  // 			sql.identifier(migrationsTable)52  // 		} order by created_at desc limit 1`,53  // 	);54  // 	const lastDbMigration = dbMigrations[0];55  // 	await session.transaction(async (tx) => {56  // 		for await (const migration of migrations) {57  // 			if (58  // 				!lastDbMigration59  // 				|| Number(lastDbMigration.created_at) < migration.folderMillis60  // 			) {61  // 				for (const stmt of migration.sql) {62  // 					await tx.execute(sql.raw(stmt));63  // 				}64  // 				await tx.execute(65  // 					sql`insert into ${sql.identifier(migrationsSchema)}.${66  // 						sql.identifier(migrationsTable)67  // 					} ("hash", "created_at") values(${migration.hash}, ${migration.folderMillis})`,68  // 				);69  // 			}70  // 		}71  // 	});72  // }73  escapeName(name) {74    return `"${name}"`;75  }76  escapeParam(num) {77    return `$${num + 1}`;78  }79  escapeString(str) {80    return `'${str.replace(/'/g, "''")}'`;81  }82  buildWithCTE(queries) {83    if (!queries?.length) return void 0;84    const withSqlChunks = [sql`with `];85    for (const [i, w] of queries.entries()) {86      withSqlChunks.push(sql`${sql.identifier(w._.alias)} as (${w._.sql})`);87      if (i < queries.length - 1) {88        withSqlChunks.push(sql`, `);89      }90    }91    withSqlChunks.push(sql` `);92    return sql.join(withSqlChunks);93  }94  buildDeleteQuery({ table, where, returning, withList }) {95    const withSql = this.buildWithCTE(withList);96    const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;97    const whereSql = where ? sql` where ${where}` : void 0;98    return sql`${withSql}delete from ${table}${whereSql}${returningSql}`;99  }100  buildUpdateSet(table, set) {101    const tableColumns = table[Table.Symbol.Columns];102    const columnNames = Object.keys(tableColumns).filter(103      (colName) => set[colName] !== void 0 || tableColumns[colName]?.onUpdateFn !== void 0104    );105    const setSize = columnNames.length;106    return sql.join(columnNames.flatMap((colName, i) => {107      const col = tableColumns[colName];108      const onUpdateFnResult = col.onUpdateFn?.();109      const value = set[colName] ?? (is(onUpdateFnResult, SQL) ? onUpdateFnResult : sql.param(onUpdateFnResult, col));110      const res = sql`${sql.identifier(this.casing.getColumnCasing(col))} = ${value}`;111      if (i < setSize - 1) {112        return [res, sql.raw(", ")];113      }114      return [res];115    }));116  }117  buildUpdateQuery({ table, set, where, returning, withList, from, joins }) {118    const withSql = this.buildWithCTE(withList);119    const tableName = table[GelTable.Symbol.Name];120    const tableSchema = table[GelTable.Symbol.Schema];121    const origTableName = table[GelTable.Symbol.OriginalName];122    const alias = tableName === origTableName ? void 0 : tableName;123    const tableSql = sql`${tableSchema ? sql`${sql.identifier(tableSchema)}.` : void 0}${sql.identifier(origTableName)}${alias && sql` ${sql.identifier(alias)}`}`;124    const setSql = this.buildUpdateSet(table, set);125    const fromSql = from && sql.join([sql.raw(" from "), this.buildFromTable(from)]);126    const joinsSql = this.buildJoins(joins);127    const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: !from })}` : void 0;128    const whereSql = where ? sql` where ${where}` : void 0;129    return sql`${withSql}update ${tableSql} set ${setSql}${fromSql}${joinsSql}${whereSql}${returningSql}`;130  }131  /**132   * Builds selection SQL with provided fields/expressions133   *134   * Examples:135   *136   * `select <selection> from`137   *138   * `insert ... returning <selection>`139   *140   * If `isSingleTable` is true, then columns won't be prefixed with table name141   * ^ Temporarily disabled behaviour, see comments within method for a reasoning142   */143  buildSelection(fields, { isSingleTable = false } = {}) {144    const columnsLen = fields.length;145    const chunks = fields.flatMap(({ field }, i) => {146      const chunk = [];147      if (is(field, SQL.Aliased) && field.isSelectionField) {148        chunk.push(sql.identifier(field.fieldAlias));149      } else if (is(field, SQL.Aliased) || is(field, SQL)) {150        const query = is(field, SQL.Aliased) ? field.sql : field;151        chunk.push(query);152        if (is(field, SQL.Aliased)) {153          chunk.push(sql` as ${sql.identifier(field.fieldAlias)}`);154        }155      } else if (is(field, Column)) {156        chunk.push(field);157      } else if (is(field, Subquery)) {158        const entries = Object.entries(field._.selectedFields);159        if (entries.length === 1) {160          const entry = entries[0][1];161          const fieldDecoder = is(entry, SQL) ? entry.decoder : is(entry, Column) ? { mapFromDriverValue: (v) => entry.mapFromDriverValue(v) } : entry.sql.decoder;162          if (fieldDecoder) {163            field._.sql.decoder = fieldDecoder;164          }165        }166        chunk.push(field);167      }168      if (i < columnsLen - 1) {169        chunk.push(sql`, `);170      }171      return chunk;172    });173    return sql.join(chunks);174  }175  buildJoins(joins) {176    if (!joins || joins.length === 0) {177      return void 0;178    }179    const joinsArray = [];180    for (const [index, joinMeta] of joins.entries()) {181      if (index === 0) {182        joinsArray.push(sql` `);183      }184      const table = joinMeta.table;185      const lateralSql = joinMeta.lateral ? sql` lateral` : void 0;186      const onSql = joinMeta.on ? sql` on ${joinMeta.on}` : void 0;187      if (is(table, GelTable)) {188        const tableName = table[GelTable.Symbol.Name];189        const tableSchema = table[GelTable.Symbol.Schema];190        const origTableName = table[GelTable.Symbol.OriginalName];191        const alias = tableName === origTableName ? void 0 : joinMeta.alias;192        joinsArray.push(193          sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${tableSchema ? sql`${sql.identifier(tableSchema)}.` : void 0}${sql.identifier(origTableName)}${alias && sql` ${sql.identifier(alias)}`}${onSql}`194        );195      } else if (is(table, View)) {196        const viewName = table[ViewBaseConfig].name;197        const viewSchema = table[ViewBaseConfig].schema;198        const origViewName = table[ViewBaseConfig].originalName;199        const alias = viewName === origViewName ? void 0 : joinMeta.alias;200        joinsArray.push(201          sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${viewSchema ? sql`${sql.identifier(viewSchema)}.` : void 0}${sql.identifier(origViewName)}${alias && sql` ${sql.identifier(alias)}`}${onSql}`202        );203      } else {204        joinsArray.push(205          sql`${sql.raw(joinMeta.joinType)} join${lateralSql} ${table}${onSql}`206        );207      }208      if (index < joins.length - 1) {209        joinsArray.push(sql` `);210      }211    }212    return sql.join(joinsArray);213  }214  buildFromTable(table) {215    if (is(table, Table) && table[Table.Symbol.OriginalName] !== table[Table.Symbol.Name]) {216      let fullName = sql`${sql.identifier(table[Table.Symbol.OriginalName])}`;217      if (table[Table.Symbol.Schema]) {218        fullName = sql`${sql.identifier(table[Table.Symbol.Schema])}.${fullName}`;219      }220      return sql`${fullName} ${sql.identifier(table[Table.Symbol.Name])}`;221    }222    return table;223  }224  buildSelectQuery({225    withList,226    fields,227    fieldsFlat,228    where,229    having,230    table,231    joins,232    orderBy,233    groupBy,234    limit,235    offset,236    lockingClause,237    distinct,238    setOperators239  }) {240    const fieldsList = fieldsFlat ?? orderSelectedFields(fields);241    for (const f of fieldsList) {242      if (is(f.field, Column) && getTableName(f.field.table) !== (is(table, Subquery) ? table._.alias : is(table, GelViewBase) ? table[ViewBaseConfig].name : is(table, SQL) ? void 0 : getTableName(table)) && !((table2) => joins?.some(243        ({ alias }) => alias === (table2[Table.Symbol.IsAlias] ? getTableName(table2) : table2[Table.Symbol.BaseName])244      ))(f.field.table)) {245        const tableName = getTableName(f.field.table);246        throw new Error(247          `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?`248        );249      }250    }251    const isSingleTable = !joins || joins.length === 0;252    const withSql = this.buildWithCTE(withList);253    let distinctSql;254    if (distinct) {255      distinctSql = distinct === true ? sql` distinct` : sql` distinct on (${sql.join(distinct.on, sql`, `)})`;256    }257    const selection = this.buildSelection(fieldsList, { isSingleTable });258    const tableSql = this.buildFromTable(table);259    const joinsSql = this.buildJoins(joins);260    const whereSql = where ? sql` where ${where}` : void 0;261    const havingSql = having ? sql` having ${having}` : void 0;262    let orderBySql;263    if (orderBy && orderBy.length > 0) {264      orderBySql = sql` order by ${sql.join(orderBy, sql`, `)}`;265    }266    let groupBySql;267    if (groupBy && groupBy.length > 0) {268      groupBySql = sql` group by ${sql.join(groupBy, sql`, `)}`;269    }270    const limitSql = typeof limit === "object" || typeof limit === "number" && limit >= 0 ? sql` limit ${limit}` : void 0;271    const offsetSql = offset ? sql` offset ${offset}` : void 0;272    const lockingClauseSql = sql.empty();273    if (lockingClause) {274      const clauseSql = sql` for ${sql.raw(lockingClause.strength)}`;275      if (lockingClause.config.of) {276        clauseSql.append(277          sql` of ${sql.join(278            Array.isArray(lockingClause.config.of) ? lockingClause.config.of : [lockingClause.config.of],279            sql`, `280          )}`281        );282      }283      if (lockingClause.config.noWait) {284        clauseSql.append(sql` nowait`);285      } else if (lockingClause.config.skipLocked) {286        clauseSql.append(sql` skip locked`);287      }288      lockingClauseSql.append(clauseSql);289    }290    const finalQuery = sql`${withSql}select${distinctSql} ${selection} from ${tableSql}${joinsSql}${whereSql}${groupBySql}${havingSql}${orderBySql}${limitSql}${offsetSql}${lockingClauseSql}`;291    if (setOperators.length > 0) {292      return this.buildSetOperations(finalQuery, setOperators);293    }294    return finalQuery;295  }296  buildSetOperations(leftSelect, setOperators) {297    const [setOperator, ...rest] = setOperators;298    if (!setOperator) {299      throw new Error("Cannot pass undefined values to any set operator");300    }301    if (rest.length === 0) {302      return this.buildSetOperationQuery({ leftSelect, setOperator });303    }304    return this.buildSetOperations(305      this.buildSetOperationQuery({ leftSelect, setOperator }),306      rest307    );308  }309  buildSetOperationQuery({310    leftSelect,311    setOperator: { type, isAll, rightSelect, limit, orderBy, offset }312  }) {313    const leftChunk = sql`(${leftSelect.getSQL()}) `;314    const rightChunk = sql`(${rightSelect.getSQL()})`;315    let orderBySql;316    if (orderBy && orderBy.length > 0) {317      const orderByValues = [];318      for (const singleOrderBy of orderBy) {319        if (is(singleOrderBy, GelColumn)) {320          orderByValues.push(sql.identifier(singleOrderBy.name));321        } else if (is(singleOrderBy, SQL)) {322          for (let i = 0; i < singleOrderBy.queryChunks.length; i++) {323            const chunk = singleOrderBy.queryChunks[i];324            if (is(chunk, GelColumn)) {325              singleOrderBy.queryChunks[i] = sql.identifier(chunk.name);326            }327          }328          orderByValues.push(sql`${singleOrderBy}`);329        } else {330          orderByValues.push(sql`${singleOrderBy}`);331        }332      }333      orderBySql = sql` order by ${sql.join(orderByValues, sql`, `)} `;334    }335    const limitSql = typeof limit === "object" || typeof limit === "number" && limit >= 0 ? sql` limit ${limit}` : void 0;336    const operatorChunk = sql.raw(`${type} ${isAll ? "all " : ""}`);337    const offsetSql = offset ? sql` offset ${offset}` : void 0;338    return sql`${leftChunk}${operatorChunk}${rightChunk}${orderBySql}${limitSql}${offsetSql}`;339  }340  buildInsertQuery({ table, values: valuesOrSelect, onConflict, returning, withList, select, overridingSystemValue_ }) {341    const valuesSqlList = [];342    const columns = table[Table.Symbol.Columns];343    const colEntries = Object.entries(columns).filter(([_, col]) => !col.shouldDisableInsert());344    const insertOrder = colEntries.map(345      ([, column]) => sql.identifier(this.casing.getColumnCasing(column))346    );347    if (select) {348      const select2 = valuesOrSelect;349      if (is(select2, SQL)) {350        valuesSqlList.push(select2);351      } else {352        valuesSqlList.push(select2.getSQL());353      }354    } else {355      const values = valuesOrSelect;356      valuesSqlList.push(sql.raw("values "));357      for (const [valueIndex, value] of values.entries()) {358        const valueList = [];359        for (const [fieldName, col] of colEntries) {360          const colValue = value[fieldName];361          if (colValue === void 0 || is(colValue, Param) && colValue.value === void 0) {362            if (col.defaultFn !== void 0) {363              const defaultFnResult = col.defaultFn();364              const defaultValue = is(defaultFnResult, SQL) ? defaultFnResult : sql.param(defaultFnResult, col);365              valueList.push(defaultValue);366            } else if (!col.default && col.onUpdateFn !== void 0) {367              const onUpdateFnResult = col.onUpdateFn();368              const newValue = is(onUpdateFnResult, SQL) ? onUpdateFnResult : sql.param(onUpdateFnResult, col);369              valueList.push(newValue);370            } else {371              valueList.push(sql`default`);372            }373          } else {374            valueList.push(colValue);375          }376        }377        valuesSqlList.push(valueList);378        if (valueIndex < values.length - 1) {379          valuesSqlList.push(sql`, `);380        }381      }382    }383    const withSql = this.buildWithCTE(withList);384    const valuesSql = sql.join(valuesSqlList);385    const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;386    const onConflictSql = onConflict ? sql` on conflict ${onConflict}` : void 0;387    const overridingSql = overridingSystemValue_ === true ? sql`overriding system value ` : void 0;388    return sql`${withSql}insert into ${table} ${insertOrder} ${overridingSql}${valuesSql}${onConflictSql}${returningSql}`;389  }390  buildRefreshMaterializedViewQuery({ view, concurrently, withNoData }) {391    const concurrentlySql = concurrently ? sql` concurrently` : void 0;392    const withNoDataSql = withNoData ? sql` with no data` : void 0;393    return sql`refresh materialized view${concurrentlySql} ${view}${withNoDataSql}`;394  }395  prepareTyping(encoder) {396    if (is(encoder, GelJson)) {397      return "json";398    } else if (is(encoder, GelDecimal)) {399      return "decimal";400    } else if (is(encoder, GelTimestamp)) {401      return "timestamp";402    } else if (is(encoder, GelUUID)) {403      return "uuid";404    } else {405      return "none";406    }407  }408  sqlToQuery(sql2, invokeSource) {409    return sql2.toQuery({410      casing: this.casing,411      escapeName: this.escapeName,412      escapeParam: this.escapeParam,413      escapeString: this.escapeString,414      prepareTyping: this.prepareTyping,415      invokeSource416    });417  }418  // buildRelationalQueryWithPK({419  // 	fullSchema,420  // 	schema,421  // 	tableNamesMap,422  // 	table,423  // 	tableConfig,424  // 	queryConfig: config,425  // 	tableAlias,426  // 	isRoot = false,427  // 	joinOn,428  // }: {429  // 	fullSchema: Record<string, unknown>;430  // 	schema: TablesRelationalConfig;431  // 	tableNamesMap: Record<string, string>;432  // 	table: GelTable;433  // 	tableConfig: TableRelationalConfig;434  // 	queryConfig: true | DBQueryConfig<'many', true>;435  // 	tableAlias: string;436  // 	isRoot?: boolean;437  // 	joinOn?: SQL;438  // }): BuildRelationalQueryResult<GelTable, GelColumn> {439  // 	// For { "<relation>": true }, return a table with selection of all columns440  // 	if (config === true) {441  // 		const selectionEntries = Object.entries(tableConfig.columns);442  // 		const selection: BuildRelationalQueryResult<GelTable, GelColumn>['selection'] = selectionEntries.map((443  // 			[key, value],444  // 		) => ({445  // 			dbKey: value.name,446  // 			tsKey: key,447  // 			field: value as GelColumn,448  // 			relationTableTsKey: undefined,449  // 			isJson: false,450  // 			selection: [],451  // 		}));452  // 		return {453  // 			tableTsKey: tableConfig.tsName,454  // 			sql: table,455  // 			selection,456  // 		};457  // 	}458  // 	// let selection: BuildRelationalQueryResult<GelTable, GelColumn>['selection'] = [];459  // 	// let selectionForBuild = selection;460  // 	const aliasedColumns = Object.fromEntries(461  // 		Object.entries(tableConfig.columns).map(([key, value]) => [key, aliasedTableColumn(value, tableAlias)]),462  // 	);463  // 	const aliasedRelations = Object.fromEntries(464  // 		Object.entries(tableConfig.relations).map(([key, value]) => [key, aliasedRelation(value, tableAlias)]),465  // 	);466  // 	const aliasedFields = Object.assign({}, aliasedColumns, aliasedRelations);467  // 	let where, hasUserDefinedWhere;468  // 	if (config.where) {469  // 		const whereSql = typeof config.where === 'function' ? config.where(aliasedFields, operators) : config.where;470  // 		where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias);471  // 		hasUserDefinedWhere = !!where;472  // 	}473  // 	where = and(joinOn, where);474  // 	// const fieldsSelection: { tsKey: string; value: GelColumn | SQL.Aliased; isExtra?: boolean }[] = [];475  // 	let joins: Join[] = [];476  // 	let selectedColumns: string[] = [];477  // 	// Figure out which columns to select478  // 	if (config.columns) {479  // 		let isIncludeMode = false;480  // 		for (const [field, value] of Object.entries(config.columns)) {481  // 			if (value === undefined) {482  // 				continue;483  // 			}484  // 			if (field in tableConfig.columns) {485  // 				if (!isIncludeMode && value === true) {486  // 					isIncludeMode = true;487  // 				}488  // 				selectedColumns.push(field);489  // 			}490  // 		}491  // 		if (selectedColumns.length > 0) {492  // 			selectedColumns = isIncludeMode493  // 				? selectedColumns.filter((c) => config.columns?.[c] === true)494  // 				: Object.keys(tableConfig.columns).filter((key) => !selectedColumns.includes(key));495  // 		}496  // 	} else {497  // 		// Select all columns if selection is not specified498  // 		selectedColumns = Object.keys(tableConfig.columns);499  // 	}500  // 	// for (const field of selectedColumns) {501  // 	// 	const column = tableConfig.columns[field]! as GelColumn;502  // 	// 	fieldsSelection.push({ tsKey: field, value: column });503  // 	// }504  // 	let initiallySelectedRelations: {505  // 		tsKey: string;506  // 		queryConfig: true | DBQueryConfig<'many', false>;507  // 		relation: Relation;508  // 	}[] = [];509  // 	// let selectedRelations: BuildRelationalQueryResult<GelTable, GelColumn>['selection'] = [];510  // 	// Figure out which relations to select511  // 	if (config.with) {512  // 		initiallySelectedRelations = Object.entries(config.with)513  // 			.filter((entry): entry is [typeof entry[0], NonNullable<typeof entry[1]>] => !!entry[1])514  // 			.map(([tsKey, queryConfig]) => ({ tsKey, queryConfig, relation: tableConfig.relations[tsKey]! }));515  // 	}516  // 	const manyRelations = initiallySelectedRelations.filter((r) =>517  // 		is(r.relation, Many)518  // 		&& (schema[tableNamesMap[r.relation.referencedTable[Table.Symbol.Name]]!]?.primaryKey.length ?? 0) > 0519  // 	);520  // 	// If this is the last Many relation (or there are no Many relations), we are on the innermost subquery level521  // 	const isInnermostQuery = manyRelations.length < 2;522  // 	const selectedExtras: {523  // 		tsKey: string;524  // 		value: SQL.Aliased;525  // 	}[] = [];526  // 	// Figure out which extras to select527  // 	if (isInnermostQuery && config.extras) {528  // 		const extras = typeof config.extras === 'function'529  // 			? config.extras(aliasedFields, { sql })530  // 			: config.extras;531  // 		for (const [tsKey, value] of Object.entries(extras)) {532  // 			selectedExtras.push({533  // 				tsKey,534  // 				value: mapColumnsInAliasedSQLToAlias(value, tableAlias),535  // 			});536  // 		}537  // 	}538  // 	// Transform `fieldsSelection` into `selection`539  // 	// `fieldsSelection` shouldn't be used after this point540  // 	// for (const { tsKey, value, isExtra } of fieldsSelection) {541  // 	// 	selection.push({542  // 	// 		dbKey: is(value, SQL.Aliased) ? value.fieldAlias : tableConfig.columns[tsKey]!.name,543  // 	// 		tsKey,544  // 	// 		field: is(value, Column) ? aliasedTableColumn(value, tableAlias) : value,545  // 	// 		relationTableTsKey: undefined,546  // 	// 		isJson: false,547  // 	// 		isExtra,548  // 	// 		selection: [],549  // 	// 	});550  // 	// }551  // 	let orderByOrig = typeof config.orderBy === 'function'552  // 		? config.orderBy(aliasedFields, orderByOperators)553  // 		: config.orderBy ?? [];554  // 	if (!Array.isArray(orderByOrig)) {555  // 		orderByOrig = [orderByOrig];556  // 	}557  // 	const orderBy = orderByOrig.map((orderByValue) => {558  // 		if (is(orderByValue, Column)) {559  // 			return aliasedTableColumn(orderByValue, tableAlias) as GelColumn;560  // 		}561  // 		return mapColumnsInSQLToAlias(orderByValue, tableAlias);562  // 	});563  // 	const limit = isInnermostQuery ? config.limit : undefined;564  // 	const offset = isInnermostQuery ? config.offset : undefined;565  // 	// For non-root queries without additional config except columns, return a table with selection566  // 	if (567  // 		!isRoot568  // 		&& initiallySelectedRelations.length === 0569  // 		&& selectedExtras.length === 0570  // 		&& !where571  // 		&& orderBy.length === 0572  // 		&& limit === undefined573  // 		&& offset === undefined574  // 	) {575  // 		return {576  // 			tableTsKey: tableConfig.tsName,577  // 			sql: table,578  // 			selection: selectedColumns.map((key) => ({579  // 				dbKey: tableConfig.columns[key]!.name,580  // 				tsKey: key,581  // 				field: tableConfig.columns[key] as GelColumn,582  // 				relationTableTsKey: undefined,583  // 				isJson: false,584  // 				selection: [],585  // 			})),586  // 		};587  // 	}588  // 	const selectedRelationsWithoutPK:589  // 	// Process all relations without primary keys, because they need to be joined differently and will all be on the same query level590  // 	for (591  // 		const {592  // 			tsKey: selectedRelationTsKey,593  // 			queryConfig: selectedRelationConfigValue,594  // 			relation,595  // 		} of initiallySelectedRelations596  // 	) {597  // 		const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation);598  // 		const relationTableName = relation.referencedTable[Table.Symbol.Name];599  // 		const relationTableTsName = tableNamesMap[relationTableName]!;600  // 		const relationTable = schema[relationTableTsName]!;601  // 		if (relationTable.primaryKey.length > 0) {602  // 			continue;603  // 		}604  // 		const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`;605  // 		const joinOn = and(606  // 			...normalizedRelation.fields.map((field, i) =>607  // 				eq(608  // 					aliasedTableColumn(normalizedRelation.references[i]!, relationTableAlias),609  // 					aliasedTableColumn(field, tableAlias),610  // 				)611  // 			),612  // 		);613  // 		const builtRelation = this.buildRelationalQueryWithoutPK({614  // 			fullSchema,615  // 			schema,616  // 			tableNamesMap,617  // 			table: fullSchema[relationTableTsName] as GelTable,618  // 			tableConfig: schema[relationTableTsName]!,619  // 			queryConfig: selectedRelationConfigValue,620  // 			tableAlias: relationTableAlias,621  // 			joinOn,622  // 			nestedQueryRelation: relation,623  // 		});624  // 		const field = sql`${sql.identifier(relationTableAlias)}.${sql.identifier('data')}`.as(selectedRelationTsKey);625  // 		joins.push({626  // 			on: sql`true`,627  // 			table: new Subquery(builtRelation.sql as SQL, {}, relationTableAlias),628  // 			alias: relationTableAlias,629  // 			joinType: 'left',630  // 			lateral: true,631  // 		});632  // 		selectedRelations.push({633  // 			dbKey: selectedRelationTsKey,634  // 			tsKey: selectedRelationTsKey,635  // 			field,636  // 			relationTableTsKey: relationTableTsName,637  // 			isJson: true,638  // 			selection: builtRelation.selection,639  // 		});640  // 	}641  // 	const oneRelations = initiallySelectedRelations.filter((r): r is typeof r & { relation: One } =>642  // 		is(r.relation, One)643  // 	);644  // 	// Process all One relations with PKs, because they can all be joined on the same level645  // 	for (646  // 		const {647  // 			tsKey: selectedRelationTsKey,648  // 			queryConfig: selectedRelationConfigValue,649  // 			relation,650  // 		} of oneRelations651  // 	) {652  // 		const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation);653  // 		const relationTableName = relation.referencedTable[Table.Symbol.Name];654  // 		const relationTableTsName = tableNamesMap[relationTableName]!;655  // 		const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`;656  // 		const relationTable = schema[relationTableTsName]!;657  // 		if (relationTable.primaryKey.length === 0) {658  // 			continue;659  // 		}660  // 		const joinOn = and(661  // 			...normalizedRelation.fields.map((field, i) =>662  // 				eq(663  // 					aliasedTableColumn(normalizedRelation.references[i]!, relationTableAlias),664  // 					aliasedTableColumn(field, tableAlias),665  // 				)666  // 			),667  // 		);668  // 		const builtRelation = this.buildRelationalQueryWithPK({669  // 			fullSchema,670  // 			schema,671  // 			tableNamesMap,672  // 			table: fullSchema[relationTableTsName] as GelTable,673  // 			tableConfig: schema[relationTableTsName]!,674  // 			queryConfig: selectedRelationConfigValue,675  // 			tableAlias: relationTableAlias,676  // 			joinOn,677  // 		});678  // 		const field = sql`case when ${sql.identifier(relationTableAlias)} is null then null else json_build_array(${679  // 			sql.join(680  // 				builtRelation.selection.map(({ field }) =>681  // 					is(field, SQL.Aliased)682  // 						? sql`${sql.identifier(relationTableAlias)}.${sql.identifier(field.fieldAlias)}`683  // 						: is(field, Column)684  // 						? aliasedTableColumn(field, relationTableAlias)685  // 						: field686  // 				),687  // 				sql`, `,688  // 			)689  // 		}) end`.as(selectedRelationTsKey);690  // 		const isLateralJoin = is(builtRelation.sql, SQL);691  // 		joins.push({692  // 			on: isLateralJoin ? sql`true` : joinOn,693  // 			table: is(builtRelation.sql, SQL)694  // 				? new Subquery(builtRelation.sql, {}, relationTableAlias)695  // 				: aliasedTable(builtRelation.sql, relationTableAlias),696  // 			alias: relationTableAlias,697  // 			joinType: 'left',698  // 			lateral: is(builtRelation.sql, SQL),699  // 		});700  // 		selectedRelations.push({701  // 			dbKey: selectedRelationTsKey,702  // 			tsKey: selectedRelationTsKey,703  // 			field,704  // 			relationTableTsKey: relationTableTsName,705  // 			isJson: true,706  // 			selection: builtRelation.selection,707  // 		});708  // 	}709  // 	let distinct: GelSelectConfig['distinct'];710  // 	let tableFrom: GelTable | Subquery = table;711  // 	// Process first Many relation - each one requires a nested subquery712  // 	const manyRelation = manyRelations[0];713  // 	if (manyRelation) {714  // 		const {715  // 			tsKey: selectedRelationTsKey,716  // 			queryConfig: selectedRelationQueryConfig,717  // 			relation,718  // 		} = manyRelation;719  // 		distinct = {720  // 			on: tableConfig.primaryKey.map((c) => aliasedTableColumn(c as GelColumn, tableAlias)),721  // 		};722  // 		const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation);723  // 		const relationTableName = relation.referencedTable[Table.Symbol.Name];724  // 		const relationTableTsName = tableNamesMap[relationTableName]!;725  // 		const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`;726  // 		const joinOn = and(727  // 			...normalizedRelation.fields.map((field, i) =>728  // 				eq(729  // 					aliasedTableColumn(normalizedRelation.references[i]!, relationTableAlias),730  // 					aliasedTableColumn(field, tableAlias),731  // 				)732  // 			),733  // 		);734  // 		const builtRelationJoin = this.buildRelationalQueryWithPK({735  // 			fullSchema,736  // 			schema,737  // 			tableNamesMap,738  // 			table: fullSchema[relationTableTsName] as GelTable,739  // 			tableConfig: schema[relationTableTsName]!,740  // 			queryConfig: selectedRelationQueryConfig,741  // 			tableAlias: relationTableAlias,742  // 			joinOn,743  // 		});744  // 		const builtRelationSelectionField = sql`case when ${745  // 			sql.identifier(relationTableAlias)746  // 		} is null then '[]' else json_agg(json_build_array(${747  // 			sql.join(748  // 				builtRelationJoin.selection.map(({ field }) =>749  // 					is(field, SQL.Aliased)750  // 						? sql`${sql.identifier(relationTableAlias)}.${sql.identifier(field.fieldAlias)}`751  // 						: is(field, Column)752  // 						? aliasedTableColumn(field, relationTableAlias)753  // 						: field754  // 				),755  // 				sql`, `,756  // 			)757  // 		})) over (partition by ${sql.join(distinct.on, sql`, `)}) end`.as(selectedRelationTsKey);758  // 		const isLateralJoin = is(builtRelationJoin.sql, SQL);759  // 		joins.push({760  // 			on: isLateralJoin ? sql`true` : joinOn,761  // 			table: isLateralJoin762  // 				? new Subquery(builtRelationJoin.sql as SQL, {}, relationTableAlias)763  // 				: aliasedTable(builtRelationJoin.sql as GelTable, relationTableAlias),764  // 			alias: relationTableAlias,765  // 			joinType: 'left',766  // 			lateral: isLateralJoin,767  // 		});768  // 		// Build the "from" subquery with the remaining Many relations769  // 		const builtTableFrom = this.buildRelationalQueryWithPK({770  // 			fullSchema,771  // 			schema,772  // 			tableNamesMap,773  // 			table,774  // 			tableConfig,775  // 			queryConfig: {776  // 				...config,777  // 				where: undefined,778  // 				orderBy: undefined,779  // 				limit: undefined,780  // 				offset: undefined,781  // 				with: manyRelations.slice(1).reduce<NonNullable<typeof config['with']>>(782  // 					(result, { tsKey, queryConfig: configValue }) => {783  // 						result[tsKey] = configValue;784  // 						return result;785  // 					},786  // 					{},787  // 				),788  // 			},789  // 			tableAlias,790  // 		});791  // 		selectedRelations.push({792  // 			dbKey: selectedRelationTsKey,793  // 			tsKey: selectedRelationTsKey,794  // 			field: builtRelationSelectionField,795  // 			relationTableTsKey: relationTableTsName,796  // 			isJson: true,797  // 			selection: builtRelationJoin.selection,798  // 		});799  // 		// selection = builtTableFrom.selection.map((item) =>800  // 		// 	is(item.field, SQL.Aliased)801  // 		// 		? { ...item, field: sql`${sql.identifier(tableAlias)}.${sql.identifier(item.field.fieldAlias)}` }802  // 		// 		: item803  // 		// );804  // 		// selectionForBuild = [{805  // 		// 	dbKey: '*',806  // 		// 	tsKey: '*',807  // 		// 	field: sql`${sql.identifier(tableAlias)}.*`,808  // 		// 	selection: [],809  // 		// 	isJson: false,810  // 		// 	relationTableTsKey: undefined,811  // 		// }];812  // 		// const newSelectionItem: (typeof selection)[number] = {813  // 		// 	dbKey: selectedRelationTsKey,814  // 		// 	tsKey: selectedRelationTsKey,815  // 		// 	field,816  // 		// 	relationTableTsKey: relationTableTsName,817  // 		// 	isJson: true,818  // 		// 	selection: builtRelationJoin.selection,819  // 		// };820  // 		// selection.push(newSelectionItem);821  // 		// selectionForBuild.push(newSelectionItem);822  // 		tableFrom = is(builtTableFrom.sql, GelTable)823  // 			? builtTableFrom.sql824  // 			: new Subquery(builtTableFrom.sql, {}, tableAlias);825  // 	}826  // 	if (selectedColumns.length === 0 && selectedRelations.length === 0 && selectedExtras.length === 0) {827  // 		throw new DrizzleError(`No fields selected for table "${tableConfig.tsName}" ("${tableAlias}")`);828  // 	}829  // 	let selection: BuildRelationalQueryResult<GelTable, GelColumn>['selection'];830  // 	function prepareSelectedColumns() {831  // 		return selectedColumns.map((key) => ({832  // 			dbKey: tableConfig.columns[key]!.name,833  // 			tsKey: key,834  // 			field: tableConfig.columns[key] as GelColumn,835  // 			relationTableTsKey: undefined,836  // 			isJson: false,837  // 			selection: [],838  // 		}));839  // 	}840  // 	function prepareSelectedExtras() {841  // 		return selectedExtras.map((item) => ({842  // 			dbKey: item.value.fieldAlias,843  // 			tsKey: item.tsKey,844  // 			field: item.value,845  // 			relationTableTsKey: undefined,846  // 			isJson: false,847  // 			selection: [],848  // 		}));849  // 	}850  // 	if (isRoot) {851  // 		selection = [852  // 			...prepareSelectedColumns(),853  // 			...prepareSelectedExtras(),854  // 		];855  // 	}856  // 	if (hasUserDefinedWhere || orderBy.length > 0) {857  // 		tableFrom = new Subquery(858  // 			this.buildSelectQuery({859  // 				table: is(tableFrom, GelTable) ? aliasedTable(tableFrom, tableAlias) : tableFrom,860  // 				fields: {},861  // 				fieldsFlat: selectionForBuild.map(({ field }) => ({862  // 					path: [],863  // 					field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field,864  // 				})),865  // 				joins,866  // 				distinct,867  // 			}),868  // 			{},869  // 			tableAlias,870  // 		);871  // 		selectionForBuild = selection.map((item) =>872  // 			is(item.field, SQL.Aliased)873  // 				? { ...item, field: sql`${sql.identifier(tableAlias)}.${sql.identifier(item.field.fieldAlias)}` }874  // 				: item875  // 		);876  // 		joins = [];877  // 		distinct = undefined;878  // 	}879  // 	const result = this.buildSelectQuery({880  // 		table: is(tableFrom, GelTable) ? aliasedTable(tableFrom, tableAlias) : tableFrom,881  // 		fields: {},882  // 		fieldsFlat: selectionForBuild.map(({ field }) => ({883  // 			path: [],884  // 			field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field,885  // 		})),886  // 		where,887  // 		limit,888  // 		offset,889  // 		joins,890  // 		orderBy,891  // 		distinct,892  // 	});893  // 	return {894  // 		tableTsKey: tableConfig.tsName,895  // 		sql: result,896  // 		selection,897  // 	};898  // }899  buildRelationalQueryWithoutPK({900    fullSchema,901    schema,902    tableNamesMap,903    table,904    tableConfig,905    queryConfig: config,906    tableAlias,907    nestedQueryRelation,908    joinOn909  }) {910    let selection = [];911    let limit, offset, orderBy = [], where;912    const joins = [];913    if (config === true) {914      const selectionEntries = Object.entries(tableConfig.columns);915      selection = selectionEntries.map(([key, value]) => ({916        dbKey: value.name,917        tsKey: key,918        field: aliasedTableColumn(value, tableAlias),919        relationTableTsKey: void 0,920        isJson: false,921        selection: []922      }));923    } else {924      const aliasedColumns = Object.fromEntries(925        Object.entries(tableConfig.columns).map(([key, value]) => [key, aliasedTableColumn(value, tableAlias)])926      );927      if (config.where) {928        const whereSql = typeof config.where === "function" ? config.where(aliasedColumns, getOperators()) : config.where;929        where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias);930      }931      const fieldsSelection = [];932      let selectedColumns = [];933      if (config.columns) {934        let isIncludeMode = false;935        for (const [field, value] of Object.entries(config.columns)) {936          if (value === void 0) {937            continue;938          }939          if (field in tableConfig.columns) {940            if (!isIncludeMode && value === true) {941              isIncludeMode = true;942            }943            selectedColumns.push(field);944          }945        }946        if (selectedColumns.length > 0) {947          selectedColumns = isIncludeMode ? selectedColumns.filter((c) => config.columns?.[c] === true) : Object.keys(tableConfig.columns).filter((key) => !selectedColumns.includes(key));948        }949      } else {950        selectedColumns = Object.keys(tableConfig.columns);951      }952      for (const field of selectedColumns) {953        const column = tableConfig.columns[field];954        fieldsSelection.push({ tsKey: field, value: column });955      }956      let selectedRelations = [];957      if (config.with) {958        selectedRelations = Object.entries(config.with).filter((entry) => !!entry[1]).map(([tsKey, queryConfig]) => ({ tsKey, queryConfig, relation: tableConfig.relations[tsKey] }));959      }960      let extras;961      if (config.extras) {962        extras = typeof config.extras === "function" ? config.extras(aliasedColumns, { sql }) : config.extras;963        for (const [tsKey, value] of Object.entries(extras)) {964          fieldsSelection.push({965            tsKey,966            value: mapColumnsInAliasedSQLToAlias(value, tableAlias)967          });968        }969      }970      for (const { tsKey, value } of fieldsSelection) {971        selection.push({972          dbKey: is(value, SQL.Aliased) ? value.fieldAlias : tableConfig.columns[tsKey].name,973          tsKey,974          field: is(value, Column) ? aliasedTableColumn(value, tableAlias) : value,975          relationTableTsKey: void 0,976          isJson: false,977          selection: []978        });979      }980      let orderByOrig = typeof config.orderBy === "function" ? config.orderBy(aliasedColumns, getOrderByOperators()) : config.orderBy ?? [];981      if (!Array.isArray(orderByOrig)) {982        orderByOrig = [orderByOrig];983      }984      orderBy = orderByOrig.map((orderByValue) => {985        if (is(orderByValue, Column)) {986          return aliasedTableColumn(orderByValue, tableAlias);987        }988        return mapColumnsInSQLToAlias(orderByValue, tableAlias);989      });990      limit = config.limit;991      offset = config.offset;992      for (const {993        tsKey: selectedRelationTsKey,994        queryConfig: selectedRelationConfigValue,995        relation996      } of selectedRelations) {997        const normalizedRelation = normalizeRelation(schema, tableNamesMap, relation);998        const relationTableName = getTableUniqueName(relation.referencedTable);999        const relationTableTsName = tableNamesMap[relationTableName];1000        const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`;1001        const joinOn2 = and(1002          ...normalizedRelation.fields.map(1003            (field2, i) => eq(1004              aliasedTableColumn(normalizedRelation.references[i], relationTableAlias),1005              aliasedTableColumn(field2, tableAlias)1006            )1007          )1008        );1009        const builtRelation = this.buildRelationalQueryWithoutPK({1010          fullSchema,1011          schema,1012          tableNamesMap,1013          table: fullSchema[relationTableTsName],1014          tableConfig: schema[relationTableTsName],1015          queryConfig: is(relation, One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue,1016          tableAlias: relationTableAlias,1017          joinOn: joinOn2,1018          nestedQueryRelation: relation1019        });1020        const field = sql`${sql.identifier(relationTableAlias)}.${sql.identifier("data")}`.as(selectedRelationTsKey);1021        joins.push({1022          on: sql`true`,1023          table: new Subquery(builtRelation.sql, {}, relationTableAlias),1024          alias: relationTableAlias,1025          joinType: "left",1026          lateral: true1027        });1028        selection.push({1029          dbKey: selectedRelationTsKey,1030          tsKey: selectedRelationTsKey,1031          field,1032          relationTableTsKey: relationTableTsName,1033          isJson: true,1034          selection: builtRelation.selection1035        });1036      }1037    }1038    if (selection.length === 0) {1039      throw new DrizzleError({ message: `No fields selected for table "${tableConfig.tsName}" ("${tableAlias}")` });1040    }1041    let result;1042    where = and(joinOn, where);1043    if (nestedQueryRelation) {1044      let field = sql`json_build_array(${sql.join(1045        selection.map(1046          ({ field: field2, tsKey, isJson }) => isJson ? sql`${sql.identifier(`${tableAlias}_${tsKey}`)}.${sql.identifier("data")}` : is(field2, SQL.Aliased) ? field2.sql : field21047        ),1048        sql`, `1049      )})`;1050      if (is(nestedQueryRelation, Many)) {1051        field = sql`coalesce(json_agg(${field}${orderBy.length > 0 ? sql` order by ${sql.join(orderBy, sql`, `)}` : void 0}), '[]'::json)`;1052      }1053      const nestedSelection = [{1054        dbKey: "data",1055        tsKey: "data",1056        field: field.as("data"),1057        isJson: true,1058        relationTableTsKey: tableConfig.tsName,1059        selection1060      }];1061      const needsSubquery = limit !== void 0 || offset !== void 0 || orderBy.length > 0;1062      if (needsSubquery) {1063        result = this.buildSelectQuery({1064          table: aliasedTable(table, tableAlias),1065          fields: {},1066          fieldsFlat: [{1067            path: [],1068            field: sql.raw("*")1069          }],1070          where,1071          limit,1072          offset,1073          orderBy,1074          setOperators: []1075        });1076        where = void 0;1077        limit = void 0;1078        offset = void 0;1079        orderBy = [];1080      } else {1081        result = aliasedTable(table, tableAlias);1082      }1083      result = this.buildSelectQuery({1084        table: is(result, GelTable) ? result : new Subquery(result, {}, tableAlias),1085        fields: {},1086        fieldsFlat: nestedSelection.map(({ field: field2 }) => ({1087          path: [],1088          field: is(field2, Column) ? aliasedTableColumn(field2, tableAlias) : field21089        })),1090        joins,1091        where,1092        limit,1093        offset,1094        orderBy,1095        setOperators: []1096      });1097    } else {1098      result = this.buildSelectQuery({1099        table: aliasedTable(table, tableAlias),1100        fields: {},1101        fieldsFlat: selection.map(({ field }) => ({1102          path: [],1103          field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field1104        })),1105        joins,1106        where,1107        limit,1108        offset,1109        orderBy,1110        setOperators: []1111      });1112    }1113    return {1114      tableTsKey: tableConfig.tsName,1115      sql: result,1116      selection1117    };1118  }1119}1120export {1121  GelDialect1122};1123//# sourceMappingURL=dialect.js.map