dialect.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  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. getOperators,
  8. getOrderByOperators,
  9. Many,
  10. normalizeRelation,
  11. One
  12. } from "../relations.js";
  13. import { and, eq } from "../sql/index.js";
  14. import { Param, SQL, sql } from "../sql/sql.js";
  15. import { SQLiteColumn } from "./columns/index.js";
  16. import { SQLiteTable } from "./table.js";
  17. import { Subquery } from "../subquery.js";
  18. import { getTableName, getTableUniqueName, Table } from "../table.js";
  19. import { orderSelectedFields } from "../utils.js";
  20. import { ViewBaseConfig } from "../view-common.js";
  21. import { SQLiteViewBase } from "./view-base.js";
  22. class SQLiteDialect {
  23. static [entityKind] = "SQLiteDialect";
  24. /** @internal */
  25. casing;
  26. constructor(config) {
  27. this.casing = new CasingCache(config?.casing);
  28. }
  29. escapeName(name) {
  30. return `"${name.replace(/"/g, '""')}"`;
  31. }
  32. escapeParam(_num) {
  33. return "?";
  34. }
  35. escapeString(str) {
  36. return `'${str.replace(/'/g, "''")}'`;
  37. }
  38. buildWithCTE(queries) {
  39. if (!queries?.length) return void 0;
  40. const withSqlChunks = [sql`with `];
  41. for (const [i, w] of queries.entries()) {
  42. withSqlChunks.push(sql`${sql.identifier(w._.alias)} as (${w._.sql})`);
  43. if (i < queries.length - 1) {
  44. withSqlChunks.push(sql`, `);
  45. }
  46. }
  47. withSqlChunks.push(sql` `);
  48. return sql.join(withSqlChunks);
  49. }
  50. buildDeleteQuery({
  51. table,
  52. where,
  53. returning,
  54. withList,
  55. limit,
  56. orderBy
  57. }) {
  58. const withSql = this.buildWithCTE(withList);
  59. const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;
  60. const whereSql = where ? sql` where ${where}` : void 0;
  61. const orderBySql = this.buildOrderBy(orderBy);
  62. const limitSql = this.buildLimit(limit);
  63. return sql`${withSql}delete from ${table}${whereSql}${returningSql}${orderBySql}${limitSql}`;
  64. }
  65. buildUpdateSet(table, set) {
  66. const tableColumns = table[Table.Symbol.Columns];
  67. const columnNames = Object.keys(tableColumns).filter(
  68. (colName) => set[colName] !== void 0 || tableColumns[colName]?.onUpdateFn !== void 0
  69. );
  70. const setSize = columnNames.length;
  71. return sql.join(
  72. columnNames.flatMap((colName, i) => {
  73. const col = tableColumns[colName];
  74. const onUpdateFnResult = col.onUpdateFn?.();
  75. const value = set[colName] ?? (is(onUpdateFnResult, SQL) ? onUpdateFnResult : sql.param(onUpdateFnResult, col));
  76. const res = sql`${sql.identifier(this.casing.getColumnCasing(col))} = ${value}`;
  77. if (i < setSize - 1) {
  78. return [res, sql.raw(", ")];
  79. }
  80. return [res];
  81. })
  82. );
  83. }
  84. buildUpdateQuery({
  85. table,
  86. set,
  87. where,
  88. returning,
  89. withList,
  90. joins,
  91. from,
  92. limit,
  93. orderBy
  94. }) {
  95. const withSql = this.buildWithCTE(withList);
  96. const setSql = this.buildUpdateSet(table, set);
  97. const fromSql = from && sql.join([sql.raw(" from "), this.buildFromTable(from)]);
  98. const joinsSql = this.buildJoins(joins);
  99. const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;
  100. const whereSql = where ? sql` where ${where}` : void 0;
  101. const orderBySql = this.buildOrderBy(orderBy);
  102. const limitSql = this.buildLimit(limit);
  103. return sql`${withSql}update ${table} set ${setSql}${fromSql}${joinsSql}${whereSql}${returningSql}${orderBySql}${limitSql}`;
  104. }
  105. /**
  106. * Builds selection SQL with provided fields/expressions
  107. *
  108. * Examples:
  109. *
  110. * `select <selection> from`
  111. *
  112. * `insert ... returning <selection>`
  113. *
  114. * If `isSingleTable` is true, then columns won't be prefixed with table name
  115. */
  116. buildSelection(fields, { isSingleTable = false } = {}) {
  117. const columnsLen = fields.length;
  118. const chunks = fields.flatMap(({ field }, i) => {
  119. const chunk = [];
  120. if (is(field, SQL.Aliased) && field.isSelectionField) {
  121. chunk.push(sql.identifier(field.fieldAlias));
  122. } else if (is(field, SQL.Aliased) || is(field, SQL)) {
  123. const query = is(field, SQL.Aliased) ? field.sql : field;
  124. if (isSingleTable) {
  125. chunk.push(
  126. new SQL(
  127. query.queryChunks.map((c) => {
  128. if (is(c, Column)) {
  129. return sql.identifier(this.casing.getColumnCasing(c));
  130. }
  131. return c;
  132. })
  133. )
  134. );
  135. } else {
  136. chunk.push(query);
  137. }
  138. if (is(field, SQL.Aliased)) {
  139. chunk.push(sql` as ${sql.identifier(field.fieldAlias)}`);
  140. }
  141. } else if (is(field, Column)) {
  142. const tableName = field.table[Table.Symbol.Name];
  143. if (field.columnType === "SQLiteNumericBigInt") {
  144. if (isSingleTable) {
  145. chunk.push(
  146. sql`cast(${sql.identifier(this.casing.getColumnCasing(field))} as text)`
  147. );
  148. } else {
  149. chunk.push(
  150. sql`cast(${sql.identifier(tableName)}.${sql.identifier(this.casing.getColumnCasing(field))} as text)`
  151. );
  152. }
  153. } else {
  154. if (isSingleTable) {
  155. chunk.push(sql.identifier(this.casing.getColumnCasing(field)));
  156. } else {
  157. chunk.push(
  158. sql`${sql.identifier(tableName)}.${sql.identifier(this.casing.getColumnCasing(field))}`
  159. );
  160. }
  161. }
  162. } else if (is(field, Subquery)) {
  163. const entries = Object.entries(field._.selectedFields);
  164. if (entries.length === 1) {
  165. const entry = entries[0][1];
  166. const fieldDecoder = is(entry, SQL) ? entry.decoder : is(entry, Column) ? { mapFromDriverValue: (v) => entry.mapFromDriverValue(v) } : entry.sql.decoder;
  167. if (fieldDecoder) field._.sql.decoder = fieldDecoder;
  168. }
  169. chunk.push(field);
  170. }
  171. if (i < columnsLen - 1) {
  172. chunk.push(sql`, `);
  173. }
  174. return chunk;
  175. });
  176. return sql.join(chunks);
  177. }
  178. buildJoins(joins) {
  179. if (!joins || joins.length === 0) {
  180. return void 0;
  181. }
  182. const joinsArray = [];
  183. if (joins) {
  184. for (const [index, joinMeta] of joins.entries()) {
  185. if (index === 0) {
  186. joinsArray.push(sql` `);
  187. }
  188. const table = joinMeta.table;
  189. const onSql = joinMeta.on ? sql` on ${joinMeta.on}` : void 0;
  190. if (is(table, SQLiteTable)) {
  191. const tableName = table[SQLiteTable.Symbol.Name];
  192. const tableSchema = table[SQLiteTable.Symbol.Schema];
  193. const origTableName = table[SQLiteTable.Symbol.OriginalName];
  194. const alias = tableName === origTableName ? void 0 : joinMeta.alias;
  195. joinsArray.push(
  196. sql`${sql.raw(joinMeta.joinType)} join ${tableSchema ? sql`${sql.identifier(tableSchema)}.` : void 0}${sql.identifier(
  197. origTableName
  198. )}${alias && sql` ${sql.identifier(alias)}`}${onSql}`
  199. );
  200. } else {
  201. joinsArray.push(
  202. sql`${sql.raw(joinMeta.joinType)} join ${table}${onSql}`
  203. );
  204. }
  205. if (index < joins.length - 1) {
  206. joinsArray.push(sql` `);
  207. }
  208. }
  209. }
  210. return sql.join(joinsArray);
  211. }
  212. buildLimit(limit) {
  213. return typeof limit === "object" || typeof limit === "number" && limit >= 0 ? sql` limit ${limit}` : void 0;
  214. }
  215. buildOrderBy(orderBy) {
  216. const orderByList = [];
  217. if (orderBy) {
  218. for (const [index, orderByValue] of orderBy.entries()) {
  219. orderByList.push(orderByValue);
  220. if (index < orderBy.length - 1) {
  221. orderByList.push(sql`, `);
  222. }
  223. }
  224. }
  225. return orderByList.length > 0 ? sql` order by ${sql.join(orderByList)}` : void 0;
  226. }
  227. buildFromTable(table) {
  228. if (is(table, Table) && table[Table.Symbol.IsAlias]) {
  229. return sql`${sql`${sql.identifier(table[Table.Symbol.Schema] ?? "")}.`.if(table[Table.Symbol.Schema])}${sql.identifier(
  230. table[Table.Symbol.OriginalName]
  231. )} ${sql.identifier(table[Table.Symbol.Name])}`;
  232. }
  233. return table;
  234. }
  235. buildSelectQuery({
  236. withList,
  237. fields,
  238. fieldsFlat,
  239. where,
  240. having,
  241. table,
  242. joins,
  243. orderBy,
  244. groupBy,
  245. limit,
  246. offset,
  247. distinct,
  248. setOperators
  249. }) {
  250. const fieldsList = fieldsFlat ?? orderSelectedFields(fields);
  251. for (const f of fieldsList) {
  252. if (is(f.field, Column) && getTableName(f.field.table) !== (is(table, Subquery) ? table._.alias : is(table, SQLiteViewBase) ? table[ViewBaseConfig].name : is(table, SQL) ? void 0 : getTableName(table)) && !((table2) => joins?.some(
  253. ({ alias }) => alias === (table2[Table.Symbol.IsAlias] ? getTableName(table2) : table2[Table.Symbol.BaseName])
  254. ))(f.field.table)) {
  255. const tableName = getTableName(f.field.table);
  256. throw new Error(
  257. `Your "${f.path.join(
  258. "->"
  259. )}" field references a column "${tableName}"."${f.field.name}", but the table "${tableName}" is not part of the query! Did you forget to join it?`
  260. );
  261. }
  262. }
  263. const isSingleTable = !joins || joins.length === 0;
  264. const withSql = this.buildWithCTE(withList);
  265. const distinctSql = distinct ? sql` distinct` : void 0;
  266. const selection = this.buildSelection(fieldsList, { isSingleTable });
  267. const tableSql = this.buildFromTable(table);
  268. const joinsSql = this.buildJoins(joins);
  269. const whereSql = where ? sql` where ${where}` : void 0;
  270. const havingSql = having ? sql` having ${having}` : void 0;
  271. const groupByList = [];
  272. if (groupBy) {
  273. for (const [index, groupByValue] of groupBy.entries()) {
  274. groupByList.push(groupByValue);
  275. if (index < groupBy.length - 1) {
  276. groupByList.push(sql`, `);
  277. }
  278. }
  279. }
  280. const groupBySql = groupByList.length > 0 ? sql` group by ${sql.join(groupByList)}` : void 0;
  281. const orderBySql = this.buildOrderBy(orderBy);
  282. const limitSql = this.buildLimit(limit);
  283. const offsetSql = offset ? sql` offset ${offset}` : void 0;
  284. const finalQuery = sql`${withSql}select${distinctSql} ${selection} from ${tableSql}${joinsSql}${whereSql}${groupBySql}${havingSql}${orderBySql}${limitSql}${offsetSql}`;
  285. if (setOperators.length > 0) {
  286. return this.buildSetOperations(finalQuery, setOperators);
  287. }
  288. return finalQuery;
  289. }
  290. buildSetOperations(leftSelect, setOperators) {
  291. const [setOperator, ...rest] = setOperators;
  292. if (!setOperator) {
  293. throw new Error("Cannot pass undefined values to any set operator");
  294. }
  295. if (rest.length === 0) {
  296. return this.buildSetOperationQuery({ leftSelect, setOperator });
  297. }
  298. return this.buildSetOperations(
  299. this.buildSetOperationQuery({ leftSelect, setOperator }),
  300. rest
  301. );
  302. }
  303. buildSetOperationQuery({
  304. leftSelect,
  305. setOperator: { type, isAll, rightSelect, limit, orderBy, offset }
  306. }) {
  307. const leftChunk = sql`${leftSelect.getSQL()} `;
  308. const rightChunk = sql`${rightSelect.getSQL()}`;
  309. let orderBySql;
  310. if (orderBy && orderBy.length > 0) {
  311. const orderByValues = [];
  312. for (const singleOrderBy of orderBy) {
  313. if (is(singleOrderBy, SQLiteColumn)) {
  314. orderByValues.push(sql.identifier(singleOrderBy.name));
  315. } else if (is(singleOrderBy, SQL)) {
  316. for (let i = 0; i < singleOrderBy.queryChunks.length; i++) {
  317. const chunk = singleOrderBy.queryChunks[i];
  318. if (is(chunk, SQLiteColumn)) {
  319. singleOrderBy.queryChunks[i] = sql.identifier(
  320. this.casing.getColumnCasing(chunk)
  321. );
  322. }
  323. }
  324. orderByValues.push(sql`${singleOrderBy}`);
  325. } else {
  326. orderByValues.push(sql`${singleOrderBy}`);
  327. }
  328. }
  329. orderBySql = sql` order by ${sql.join(orderByValues, sql`, `)}`;
  330. }
  331. const limitSql = typeof limit === "object" || typeof limit === "number" && limit >= 0 ? sql` limit ${limit}` : void 0;
  332. const operatorChunk = sql.raw(`${type} ${isAll ? "all " : ""}`);
  333. const offsetSql = offset ? sql` offset ${offset}` : void 0;
  334. return sql`${leftChunk}${operatorChunk}${rightChunk}${orderBySql}${limitSql}${offsetSql}`;
  335. }
  336. buildInsertQuery({
  337. table,
  338. values: valuesOrSelect,
  339. onConflict,
  340. returning,
  341. withList,
  342. select
  343. }) {
  344. const valuesSqlList = [];
  345. const columns = table[Table.Symbol.Columns];
  346. const colEntries = Object.entries(columns).filter(
  347. ([_, col]) => !col.shouldDisableInsert()
  348. );
  349. const insertOrder = colEntries.map(([, column]) => sql.identifier(this.casing.getColumnCasing(column)));
  350. if (select) {
  351. const select2 = valuesOrSelect;
  352. if (is(select2, SQL)) {
  353. valuesSqlList.push(select2);
  354. } else {
  355. valuesSqlList.push(select2.getSQL());
  356. }
  357. } else {
  358. const values = valuesOrSelect;
  359. valuesSqlList.push(sql.raw("values "));
  360. for (const [valueIndex, value] of values.entries()) {
  361. const valueList = [];
  362. for (const [fieldName, col] of colEntries) {
  363. const colValue = value[fieldName];
  364. if (colValue === void 0 || is(colValue, Param) && colValue.value === void 0) {
  365. let defaultValue;
  366. if (col.default !== null && col.default !== void 0) {
  367. defaultValue = is(col.default, SQL) ? col.default : sql.param(col.default, col);
  368. } else if (col.defaultFn !== void 0) {
  369. const defaultFnResult = col.defaultFn();
  370. defaultValue = is(defaultFnResult, SQL) ? defaultFnResult : sql.param(defaultFnResult, col);
  371. } else if (!col.default && col.onUpdateFn !== void 0) {
  372. const onUpdateFnResult = col.onUpdateFn();
  373. defaultValue = is(onUpdateFnResult, SQL) ? onUpdateFnResult : sql.param(onUpdateFnResult, col);
  374. } else {
  375. defaultValue = sql`null`;
  376. }
  377. valueList.push(defaultValue);
  378. } else {
  379. valueList.push(colValue);
  380. }
  381. }
  382. valuesSqlList.push(valueList);
  383. if (valueIndex < values.length - 1) {
  384. valuesSqlList.push(sql`, `);
  385. }
  386. }
  387. }
  388. const withSql = this.buildWithCTE(withList);
  389. const valuesSql = sql.join(valuesSqlList);
  390. const returningSql = returning ? sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;
  391. const onConflictSql = onConflict?.length ? sql.join(onConflict) : void 0;
  392. return sql`${withSql}insert into ${table} ${insertOrder} ${valuesSql}${onConflictSql}${returningSql}`;
  393. }
  394. sqlToQuery(sql2, invokeSource) {
  395. return sql2.toQuery({
  396. casing: this.casing,
  397. escapeName: this.escapeName,
  398. escapeParam: this.escapeParam,
  399. escapeString: this.escapeString,
  400. invokeSource
  401. });
  402. }
  403. buildRelationalQuery({
  404. fullSchema,
  405. schema,
  406. tableNamesMap,
  407. table,
  408. tableConfig,
  409. queryConfig: config,
  410. tableAlias,
  411. nestedQueryRelation,
  412. joinOn
  413. }) {
  414. let selection = [];
  415. let limit, offset, orderBy = [], where;
  416. const joins = [];
  417. if (config === true) {
  418. const selectionEntries = Object.entries(tableConfig.columns);
  419. selection = selectionEntries.map(([key, value]) => ({
  420. dbKey: value.name,
  421. tsKey: key,
  422. field: aliasedTableColumn(value, tableAlias),
  423. relationTableTsKey: void 0,
  424. isJson: false,
  425. selection: []
  426. }));
  427. } else {
  428. const aliasedColumns = Object.fromEntries(
  429. Object.entries(tableConfig.columns).map(([key, value]) => [
  430. key,
  431. aliasedTableColumn(value, tableAlias)
  432. ])
  433. );
  434. if (config.where) {
  435. const whereSql = typeof config.where === "function" ? config.where(aliasedColumns, getOperators()) : config.where;
  436. where = whereSql && mapColumnsInSQLToAlias(whereSql, tableAlias);
  437. }
  438. const fieldsSelection = [];
  439. let selectedColumns = [];
  440. if (config.columns) {
  441. let isIncludeMode = false;
  442. for (const [field, value] of Object.entries(config.columns)) {
  443. if (value === void 0) {
  444. continue;
  445. }
  446. if (field in tableConfig.columns) {
  447. if (!isIncludeMode && value === true) {
  448. isIncludeMode = true;
  449. }
  450. selectedColumns.push(field);
  451. }
  452. }
  453. if (selectedColumns.length > 0) {
  454. selectedColumns = isIncludeMode ? selectedColumns.filter((c) => config.columns?.[c] === true) : Object.keys(tableConfig.columns).filter(
  455. (key) => !selectedColumns.includes(key)
  456. );
  457. }
  458. } else {
  459. selectedColumns = Object.keys(tableConfig.columns);
  460. }
  461. for (const field of selectedColumns) {
  462. const column = tableConfig.columns[field];
  463. fieldsSelection.push({ tsKey: field, value: column });
  464. }
  465. let selectedRelations = [];
  466. if (config.with) {
  467. selectedRelations = Object.entries(config.with).filter(
  468. (entry) => !!entry[1]
  469. ).map(([tsKey, queryConfig]) => ({
  470. tsKey,
  471. queryConfig,
  472. relation: tableConfig.relations[tsKey]
  473. }));
  474. }
  475. let extras;
  476. if (config.extras) {
  477. extras = typeof config.extras === "function" ? config.extras(aliasedColumns, { sql }) : config.extras;
  478. for (const [tsKey, value] of Object.entries(extras)) {
  479. fieldsSelection.push({
  480. tsKey,
  481. value: mapColumnsInAliasedSQLToAlias(value, tableAlias)
  482. });
  483. }
  484. }
  485. for (const { tsKey, value } of fieldsSelection) {
  486. selection.push({
  487. dbKey: is(value, SQL.Aliased) ? value.fieldAlias : tableConfig.columns[tsKey].name,
  488. tsKey,
  489. field: is(value, Column) ? aliasedTableColumn(value, tableAlias) : value,
  490. relationTableTsKey: void 0,
  491. isJson: false,
  492. selection: []
  493. });
  494. }
  495. let orderByOrig = typeof config.orderBy === "function" ? config.orderBy(aliasedColumns, getOrderByOperators()) : config.orderBy ?? [];
  496. if (!Array.isArray(orderByOrig)) {
  497. orderByOrig = [orderByOrig];
  498. }
  499. orderBy = orderByOrig.map((orderByValue) => {
  500. if (is(orderByValue, Column)) {
  501. return aliasedTableColumn(orderByValue, tableAlias);
  502. }
  503. return mapColumnsInSQLToAlias(orderByValue, tableAlias);
  504. });
  505. limit = config.limit;
  506. offset = config.offset;
  507. for (const {
  508. tsKey: selectedRelationTsKey,
  509. queryConfig: selectedRelationConfigValue,
  510. relation
  511. } of selectedRelations) {
  512. const normalizedRelation = normalizeRelation(
  513. schema,
  514. tableNamesMap,
  515. relation
  516. );
  517. const relationTableName = getTableUniqueName(relation.referencedTable);
  518. const relationTableTsName = tableNamesMap[relationTableName];
  519. const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`;
  520. const joinOn2 = and(
  521. ...normalizedRelation.fields.map(
  522. (field2, i) => eq(
  523. aliasedTableColumn(
  524. normalizedRelation.references[i],
  525. relationTableAlias
  526. ),
  527. aliasedTableColumn(field2, tableAlias)
  528. )
  529. )
  530. );
  531. const builtRelation = this.buildRelationalQuery({
  532. fullSchema,
  533. schema,
  534. tableNamesMap,
  535. table: fullSchema[relationTableTsName],
  536. tableConfig: schema[relationTableTsName],
  537. queryConfig: is(relation, One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue,
  538. tableAlias: relationTableAlias,
  539. joinOn: joinOn2,
  540. nestedQueryRelation: relation
  541. });
  542. const field = sql`(${builtRelation.sql})`.as(selectedRelationTsKey);
  543. selection.push({
  544. dbKey: selectedRelationTsKey,
  545. tsKey: selectedRelationTsKey,
  546. field,
  547. relationTableTsKey: relationTableTsName,
  548. isJson: true,
  549. selection: builtRelation.selection
  550. });
  551. }
  552. }
  553. if (selection.length === 0) {
  554. throw new DrizzleError({
  555. message: `No fields selected for table "${tableConfig.tsName}" ("${tableAlias}"). You need to have at least one item in "columns", "with" or "extras". If you need to select all columns, omit the "columns" key or set it to undefined.`
  556. });
  557. }
  558. let result;
  559. where = and(joinOn, where);
  560. if (nestedQueryRelation) {
  561. let field = sql`json_array(${sql.join(
  562. selection.map(
  563. ({ field: field2 }) => is(field2, SQLiteColumn) ? sql.identifier(this.casing.getColumnCasing(field2)) : is(field2, SQL.Aliased) ? field2.sql : field2
  564. ),
  565. sql`, `
  566. )})`;
  567. if (is(nestedQueryRelation, Many)) {
  568. field = sql`coalesce(json_group_array(${field}), json_array())`;
  569. }
  570. const nestedSelection = [
  571. {
  572. dbKey: "data",
  573. tsKey: "data",
  574. field: field.as("data"),
  575. isJson: true,
  576. relationTableTsKey: tableConfig.tsName,
  577. selection
  578. }
  579. ];
  580. const needsSubquery = limit !== void 0 || offset !== void 0 || orderBy.length > 0;
  581. if (needsSubquery) {
  582. result = this.buildSelectQuery({
  583. table: aliasedTable(table, tableAlias),
  584. fields: {},
  585. fieldsFlat: [
  586. {
  587. path: [],
  588. field: sql.raw("*")
  589. }
  590. ],
  591. where,
  592. limit,
  593. offset,
  594. orderBy,
  595. setOperators: []
  596. });
  597. where = void 0;
  598. limit = void 0;
  599. offset = void 0;
  600. orderBy = void 0;
  601. } else {
  602. result = aliasedTable(table, tableAlias);
  603. }
  604. result = this.buildSelectQuery({
  605. table: is(result, SQLiteTable) ? result : new Subquery(result, {}, tableAlias),
  606. fields: {},
  607. fieldsFlat: nestedSelection.map(({ field: field2 }) => ({
  608. path: [],
  609. field: is(field2, Column) ? aliasedTableColumn(field2, tableAlias) : field2
  610. })),
  611. joins,
  612. where,
  613. limit,
  614. offset,
  615. orderBy,
  616. setOperators: []
  617. });
  618. } else {
  619. result = this.buildSelectQuery({
  620. table: aliasedTable(table, tableAlias),
  621. fields: {},
  622. fieldsFlat: selection.map(({ field }) => ({
  623. path: [],
  624. field: is(field, Column) ? aliasedTableColumn(field, tableAlias) : field
  625. })),
  626. joins,
  627. where,
  628. limit,
  629. offset,
  630. orderBy,
  631. setOperators: []
  632. });
  633. }
  634. return {
  635. tableTsKey: tableConfig.tsName,
  636. sql: result,
  637. selection
  638. };
  639. }
  640. }
  641. class SQLiteSyncDialect extends SQLiteDialect {
  642. static [entityKind] = "SQLiteSyncDialect";
  643. migrate(migrations, session, config) {
  644. const migrationsTable = config === void 0 ? "__drizzle_migrations" : typeof config === "string" ? "__drizzle_migrations" : config.migrationsTable ?? "__drizzle_migrations";
  645. const migrationTableCreate = sql`
  646. CREATE TABLE IF NOT EXISTS ${sql.identifier(migrationsTable)} (
  647. id SERIAL PRIMARY KEY,
  648. hash text NOT NULL,
  649. created_at numeric
  650. )
  651. `;
  652. session.run(migrationTableCreate);
  653. const dbMigrations = session.values(
  654. sql`SELECT id, hash, created_at FROM ${sql.identifier(migrationsTable)} ORDER BY created_at DESC LIMIT 1`
  655. );
  656. const lastDbMigration = dbMigrations[0] ?? void 0;
  657. session.run(sql`BEGIN`);
  658. try {
  659. for (const migration of migrations) {
  660. if (!lastDbMigration || Number(lastDbMigration[2]) < migration.folderMillis) {
  661. for (const stmt of migration.sql) {
  662. session.run(sql.raw(stmt));
  663. }
  664. session.run(
  665. sql`INSERT INTO ${sql.identifier(
  666. migrationsTable
  667. )} ("hash", "created_at") VALUES(${migration.hash}, ${migration.folderMillis})`
  668. );
  669. }
  670. }
  671. session.run(sql`COMMIT`);
  672. } catch (e) {
  673. session.run(sql`ROLLBACK`);
  674. throw e;
  675. }
  676. }
  677. }
  678. class SQLiteAsyncDialect extends SQLiteDialect {
  679. static [entityKind] = "SQLiteAsyncDialect";
  680. async migrate(migrations, session, config) {
  681. const migrationsTable = config === void 0 ? "__drizzle_migrations" : typeof config === "string" ? "__drizzle_migrations" : config.migrationsTable ?? "__drizzle_migrations";
  682. const migrationTableCreate = sql`
  683. CREATE TABLE IF NOT EXISTS ${sql.identifier(migrationsTable)} (
  684. id SERIAL PRIMARY KEY,
  685. hash text NOT NULL,
  686. created_at numeric
  687. )
  688. `;
  689. await session.run(migrationTableCreate);
  690. const dbMigrations = await session.values(
  691. sql`SELECT id, hash, created_at FROM ${sql.identifier(migrationsTable)} ORDER BY created_at DESC LIMIT 1`
  692. );
  693. const lastDbMigration = dbMigrations[0] ?? void 0;
  694. await session.transaction(async (tx) => {
  695. for (const migration of migrations) {
  696. if (!lastDbMigration || Number(lastDbMigration[2]) < migration.folderMillis) {
  697. for (const stmt of migration.sql) {
  698. await tx.run(sql.raw(stmt));
  699. }
  700. await tx.run(
  701. sql`INSERT INTO ${sql.identifier(
  702. migrationsTable
  703. )} ("hash", "created_at") VALUES(${migration.hash}, ${migration.folderMillis})`
  704. );
  705. }
  706. }
  707. });
  708. }
  709. }
  710. export {
  711. SQLiteAsyncDialect,
  712. SQLiteDialect,
  713. SQLiteSyncDialect
  714. };
  715. //# sourceMappingURL=dialect.js.map