dialect.js 43 KB

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