dialect.cjs 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964
  1. "use strict";
  2. var __defProp = Object.defineProperty;
  3. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  4. var __getOwnPropNames = Object.getOwnPropertyNames;
  5. var __hasOwnProp = Object.prototype.hasOwnProperty;
  6. var __export = (target, all) => {
  7. for (var name in all)
  8. __defProp(target, name, { get: all[name], enumerable: true });
  9. };
  10. var __copyProps = (to, from, except, desc) => {
  11. if (from && typeof from === "object" || typeof from === "function") {
  12. for (let key of __getOwnPropNames(from))
  13. if (!__hasOwnProp.call(to, key) && key !== except)
  14. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  15. }
  16. return to;
  17. };
  18. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  19. var dialect_exports = {};
  20. __export(dialect_exports, {
  21. MySqlDialect: () => MySqlDialect
  22. });
  23. module.exports = __toCommonJS(dialect_exports);
  24. var import_alias = require("../alias.cjs");
  25. var import_casing = require("../casing.cjs");
  26. var import_column = require("../column.cjs");
  27. var import_entity = require("../entity.cjs");
  28. var import_errors = require("../errors.cjs");
  29. var import_relations = require("../relations.cjs");
  30. var import_expressions = require("../sql/expressions/index.cjs");
  31. var import_sql = require("../sql/sql.cjs");
  32. var import_subquery = require("../subquery.cjs");
  33. var import_table = require("../table.cjs");
  34. var import_utils = require("../utils.cjs");
  35. var import_view_common = require("../view-common.cjs");
  36. var import_common = require("./columns/common.cjs");
  37. var import_table2 = require("./table.cjs");
  38. var import_view_base = require("./view-base.cjs");
  39. class MySqlDialect {
  40. static [import_entity.entityKind] = "MySqlDialect";
  41. /** @internal */
  42. casing;
  43. constructor(config) {
  44. this.casing = new import_casing.CasingCache(config?.casing);
  45. }
  46. async migrate(migrations, session, config) {
  47. const migrationsTable = config.migrationsTable ?? "__drizzle_migrations";
  48. const migrationTableCreate = import_sql.sql`
  49. create table if not exists ${import_sql.sql.identifier(migrationsTable)} (
  50. id serial primary key,
  51. hash text not null,
  52. created_at bigint
  53. )
  54. `;
  55. await session.execute(migrationTableCreate);
  56. const dbMigrations = await session.all(
  57. import_sql.sql`select id, hash, created_at from ${import_sql.sql.identifier(migrationsTable)} order by created_at desc limit 1`
  58. );
  59. const lastDbMigration = dbMigrations[0];
  60. await session.transaction(async (tx) => {
  61. for (const migration of migrations) {
  62. if (!lastDbMigration || Number(lastDbMigration.created_at) < migration.folderMillis) {
  63. for (const stmt of migration.sql) {
  64. await tx.execute(import_sql.sql.raw(stmt));
  65. }
  66. await tx.execute(
  67. import_sql.sql`insert into ${import_sql.sql.identifier(
  68. migrationsTable
  69. )} (\`hash\`, \`created_at\`) values(${migration.hash}, ${migration.folderMillis})`
  70. );
  71. }
  72. }
  73. });
  74. }
  75. escapeName(name) {
  76. return `\`${name.replace(/`/g, "``")}\``;
  77. }
  78. escapeParam(_num) {
  79. return `?`;
  80. }
  81. escapeString(str) {
  82. return `'${str.replace(/'/g, "''")}'`;
  83. }
  84. buildWithCTE(queries) {
  85. if (!queries?.length) return void 0;
  86. const withSqlChunks = [import_sql.sql`with `];
  87. for (const [i, w] of queries.entries()) {
  88. withSqlChunks.push(import_sql.sql`${import_sql.sql.identifier(w._.alias)} as (${w._.sql})`);
  89. if (i < queries.length - 1) {
  90. withSqlChunks.push(import_sql.sql`, `);
  91. }
  92. }
  93. withSqlChunks.push(import_sql.sql` `);
  94. return import_sql.sql.join(withSqlChunks);
  95. }
  96. buildDeleteQuery({
  97. table,
  98. where,
  99. returning,
  100. withList,
  101. limit,
  102. orderBy
  103. }) {
  104. const withSql = this.buildWithCTE(withList);
  105. const returningSql = returning ? import_sql.sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;
  106. const whereSql = where ? import_sql.sql` where ${where}` : void 0;
  107. const orderBySql = this.buildOrderBy(orderBy);
  108. const limitSql = this.buildLimit(limit);
  109. return import_sql.sql`${withSql}delete from ${table}${whereSql}${orderBySql}${limitSql}${returningSql}`;
  110. }
  111. buildUpdateSet(table, set) {
  112. const tableColumns = table[import_table.Table.Symbol.Columns];
  113. const columnNames = Object.keys(tableColumns).filter(
  114. (colName) => set[colName] !== void 0 || tableColumns[colName]?.onUpdateFn !== void 0
  115. );
  116. const setSize = columnNames.length;
  117. return import_sql.sql.join(
  118. columnNames.flatMap((colName, i) => {
  119. const col = tableColumns[colName];
  120. const onUpdateFnResult = col.onUpdateFn?.();
  121. const value = set[colName] ?? ((0, import_entity.is)(onUpdateFnResult, import_sql.SQL) ? onUpdateFnResult : import_sql.sql.param(onUpdateFnResult, col));
  122. const res = import_sql.sql`${import_sql.sql.identifier(this.casing.getColumnCasing(col))} = ${value}`;
  123. if (i < setSize - 1) {
  124. return [res, import_sql.sql.raw(", ")];
  125. }
  126. return [res];
  127. })
  128. );
  129. }
  130. buildUpdateQuery({
  131. table,
  132. set,
  133. where,
  134. returning,
  135. withList,
  136. limit,
  137. orderBy
  138. }) {
  139. const withSql = this.buildWithCTE(withList);
  140. const setSql = this.buildUpdateSet(table, set);
  141. const returningSql = returning ? import_sql.sql` returning ${this.buildSelection(returning, { isSingleTable: true })}` : void 0;
  142. const whereSql = where ? import_sql.sql` where ${where}` : void 0;
  143. const orderBySql = this.buildOrderBy(orderBy);
  144. const limitSql = this.buildLimit(limit);
  145. return import_sql.sql`${withSql}update ${table} set ${setSql}${whereSql}${orderBySql}${limitSql}${returningSql}`;
  146. }
  147. /**
  148. * Builds selection SQL with provided fields/expressions
  149. *
  150. * Examples:
  151. *
  152. * `select <selection> from`
  153. *
  154. * `insert ... returning <selection>`
  155. *
  156. * If `isSingleTable` is true, then columns won't be prefixed with table name
  157. */
  158. buildSelection(fields, { isSingleTable = false } = {}) {
  159. const columnsLen = fields.length;
  160. const chunks = fields.flatMap(({ field }, i) => {
  161. const chunk = [];
  162. if ((0, import_entity.is)(field, import_sql.SQL.Aliased) && field.isSelectionField) {
  163. chunk.push(import_sql.sql.identifier(field.fieldAlias));
  164. } else if ((0, import_entity.is)(field, import_sql.SQL.Aliased) || (0, import_entity.is)(field, import_sql.SQL)) {
  165. const query = (0, import_entity.is)(field, import_sql.SQL.Aliased) ? field.sql : field;
  166. if (isSingleTable) {
  167. chunk.push(
  168. new import_sql.SQL(
  169. query.queryChunks.map((c) => {
  170. if ((0, import_entity.is)(c, import_common.MySqlColumn)) {
  171. return import_sql.sql.identifier(this.casing.getColumnCasing(c));
  172. }
  173. return c;
  174. })
  175. )
  176. );
  177. } else {
  178. chunk.push(query);
  179. }
  180. if ((0, import_entity.is)(field, import_sql.SQL.Aliased)) {
  181. chunk.push(import_sql.sql` as ${import_sql.sql.identifier(field.fieldAlias)}`);
  182. }
  183. } else if ((0, import_entity.is)(field, import_column.Column)) {
  184. if (isSingleTable) {
  185. chunk.push(import_sql.sql.identifier(this.casing.getColumnCasing(field)));
  186. } else {
  187. chunk.push(field);
  188. }
  189. } else if ((0, import_entity.is)(field, import_subquery.Subquery)) {
  190. const entries = Object.entries(field._.selectedFields);
  191. if (entries.length === 1) {
  192. const entry = entries[0][1];
  193. const fieldDecoder = (0, import_entity.is)(entry, import_sql.SQL) ? entry.decoder : (0, import_entity.is)(entry, import_column.Column) ? { mapFromDriverValue: (v) => entry.mapFromDriverValue(v) } : entry.sql.decoder;
  194. if (fieldDecoder) {
  195. field._.sql.decoder = fieldDecoder;
  196. }
  197. }
  198. chunk.push(field);
  199. }
  200. if (i < columnsLen - 1) {
  201. chunk.push(import_sql.sql`, `);
  202. }
  203. return chunk;
  204. });
  205. return import_sql.sql.join(chunks);
  206. }
  207. buildLimit(limit) {
  208. return typeof limit === "object" || typeof limit === "number" && limit >= 0 ? import_sql.sql` limit ${limit}` : void 0;
  209. }
  210. buildOrderBy(orderBy) {
  211. return orderBy && orderBy.length > 0 ? import_sql.sql` order by ${import_sql.sql.join(orderBy, import_sql.sql`, `)}` : void 0;
  212. }
  213. buildIndex({
  214. indexes,
  215. indexFor
  216. }) {
  217. return indexes && indexes.length > 0 ? import_sql.sql` ${import_sql.sql.raw(indexFor)} INDEX (${import_sql.sql.raw(indexes.join(`, `))})` : void 0;
  218. }
  219. buildSelectQuery({
  220. withList,
  221. fields,
  222. fieldsFlat,
  223. where,
  224. having,
  225. table,
  226. joins,
  227. orderBy,
  228. groupBy,
  229. limit,
  230. offset,
  231. lockingClause,
  232. distinct,
  233. setOperators,
  234. useIndex,
  235. forceIndex,
  236. ignoreIndex
  237. }) {
  238. const fieldsList = fieldsFlat ?? (0, import_utils.orderSelectedFields)(fields);
  239. for (const f of fieldsList) {
  240. if ((0, import_entity.is)(f.field, import_column.Column) && (0, import_table.getTableName)(f.field.table) !== ((0, import_entity.is)(table, import_subquery.Subquery) ? table._.alias : (0, import_entity.is)(table, import_view_base.MySqlViewBase) ? table[import_view_common.ViewBaseConfig].name : (0, import_entity.is)(table, import_sql.SQL) ? void 0 : (0, import_table.getTableName)(table)) && !((table2) => joins?.some(
  241. ({ alias }) => alias === (table2[import_table.Table.Symbol.IsAlias] ? (0, import_table.getTableName)(table2) : table2[import_table.Table.Symbol.BaseName])
  242. ))(f.field.table)) {
  243. const tableName = (0, import_table.getTableName)(f.field.table);
  244. throw new Error(
  245. `Your "${f.path.join(
  246. "->"
  247. )}" 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. const distinctSql = distinct ? import_sql.sql` distinct` : void 0;
  254. const selection = this.buildSelection(fieldsList, { isSingleTable });
  255. const tableSql = (() => {
  256. if ((0, import_entity.is)(table, import_table.Table) && table[import_table.Table.Symbol.IsAlias]) {
  257. return import_sql.sql`${import_sql.sql`${import_sql.sql.identifier(table[import_table.Table.Symbol.Schema] ?? "")}.`.if(table[import_table.Table.Symbol.Schema])}${import_sql.sql.identifier(
  258. table[import_table.Table.Symbol.OriginalName]
  259. )} ${import_sql.sql.identifier(table[import_table.Table.Symbol.Name])}`;
  260. }
  261. return table;
  262. })();
  263. const joinsArray = [];
  264. if (joins) {
  265. for (const [index, joinMeta] of joins.entries()) {
  266. if (index === 0) {
  267. joinsArray.push(import_sql.sql` `);
  268. }
  269. const table2 = joinMeta.table;
  270. const lateralSql = joinMeta.lateral ? import_sql.sql` lateral` : void 0;
  271. const onSql = joinMeta.on ? import_sql.sql` on ${joinMeta.on}` : void 0;
  272. if ((0, import_entity.is)(table2, import_table2.MySqlTable)) {
  273. const tableName = table2[import_table2.MySqlTable.Symbol.Name];
  274. const tableSchema = table2[import_table2.MySqlTable.Symbol.Schema];
  275. const origTableName = table2[import_table2.MySqlTable.Symbol.OriginalName];
  276. const alias = tableName === origTableName ? void 0 : joinMeta.alias;
  277. const useIndexSql2 = this.buildIndex({
  278. indexes: joinMeta.useIndex,
  279. indexFor: "USE"
  280. });
  281. const forceIndexSql2 = this.buildIndex({
  282. indexes: joinMeta.forceIndex,
  283. indexFor: "FORCE"
  284. });
  285. const ignoreIndexSql2 = this.buildIndex({
  286. indexes: joinMeta.ignoreIndex,
  287. indexFor: "IGNORE"
  288. });
  289. joinsArray.push(
  290. import_sql.sql`${import_sql.sql.raw(joinMeta.joinType)} join${lateralSql} ${tableSchema ? import_sql.sql`${import_sql.sql.identifier(tableSchema)}.` : void 0}${import_sql.sql.identifier(origTableName)}${useIndexSql2}${forceIndexSql2}${ignoreIndexSql2}${alias && import_sql.sql` ${import_sql.sql.identifier(alias)}`}${onSql}`
  291. );
  292. } else if ((0, import_entity.is)(table2, import_sql.View)) {
  293. const viewName = table2[import_view_common.ViewBaseConfig].name;
  294. const viewSchema = table2[import_view_common.ViewBaseConfig].schema;
  295. const origViewName = table2[import_view_common.ViewBaseConfig].originalName;
  296. const alias = viewName === origViewName ? void 0 : joinMeta.alias;
  297. joinsArray.push(
  298. import_sql.sql`${import_sql.sql.raw(joinMeta.joinType)} join${lateralSql} ${viewSchema ? import_sql.sql`${import_sql.sql.identifier(viewSchema)}.` : void 0}${import_sql.sql.identifier(origViewName)}${alias && import_sql.sql` ${import_sql.sql.identifier(alias)}`}${onSql}`
  299. );
  300. } else {
  301. joinsArray.push(
  302. import_sql.sql`${import_sql.sql.raw(joinMeta.joinType)} join${lateralSql} ${table2}${onSql}`
  303. );
  304. }
  305. if (index < joins.length - 1) {
  306. joinsArray.push(import_sql.sql` `);
  307. }
  308. }
  309. }
  310. const joinsSql = import_sql.sql.join(joinsArray);
  311. const whereSql = where ? import_sql.sql` where ${where}` : void 0;
  312. const havingSql = having ? import_sql.sql` having ${having}` : void 0;
  313. const orderBySql = this.buildOrderBy(orderBy);
  314. const groupBySql = groupBy && groupBy.length > 0 ? import_sql.sql` group by ${import_sql.sql.join(groupBy, import_sql.sql`, `)}` : void 0;
  315. const limitSql = this.buildLimit(limit);
  316. const offsetSql = offset ? import_sql.sql` offset ${offset}` : void 0;
  317. const useIndexSql = this.buildIndex({ indexes: useIndex, indexFor: "USE" });
  318. const forceIndexSql = this.buildIndex({
  319. indexes: forceIndex,
  320. indexFor: "FORCE"
  321. });
  322. const ignoreIndexSql = this.buildIndex({
  323. indexes: ignoreIndex,
  324. indexFor: "IGNORE"
  325. });
  326. let lockingClausesSql;
  327. if (lockingClause) {
  328. const { config, strength } = lockingClause;
  329. lockingClausesSql = import_sql.sql` for ${import_sql.sql.raw(strength)}`;
  330. if (config.noWait) {
  331. lockingClausesSql.append(import_sql.sql` nowait`);
  332. } else if (config.skipLocked) {
  333. lockingClausesSql.append(import_sql.sql` skip locked`);
  334. }
  335. }
  336. const finalQuery = import_sql.sql`${withSql}select${distinctSql} ${selection} from ${tableSql}${useIndexSql}${forceIndexSql}${ignoreIndexSql}${joinsSql}${whereSql}${groupBySql}${havingSql}${orderBySql}${limitSql}${offsetSql}${lockingClausesSql}`;
  337. if (setOperators.length > 0) {
  338. return this.buildSetOperations(finalQuery, setOperators);
  339. }
  340. return finalQuery;
  341. }
  342. buildSetOperations(leftSelect, setOperators) {
  343. const [setOperator, ...rest] = setOperators;
  344. if (!setOperator) {
  345. throw new Error("Cannot pass undefined values to any set operator");
  346. }
  347. if (rest.length === 0) {
  348. return this.buildSetOperationQuery({ leftSelect, setOperator });
  349. }
  350. return this.buildSetOperations(
  351. this.buildSetOperationQuery({ leftSelect, setOperator }),
  352. rest
  353. );
  354. }
  355. buildSetOperationQuery({
  356. leftSelect,
  357. setOperator: { type, isAll, rightSelect, limit, orderBy, offset }
  358. }) {
  359. const leftChunk = import_sql.sql`(${leftSelect.getSQL()}) `;
  360. const rightChunk = import_sql.sql`(${rightSelect.getSQL()})`;
  361. let orderBySql;
  362. if (orderBy && orderBy.length > 0) {
  363. const orderByValues = [];
  364. for (const orderByUnit of orderBy) {
  365. if ((0, import_entity.is)(orderByUnit, import_common.MySqlColumn)) {
  366. orderByValues.push(
  367. import_sql.sql.identifier(this.casing.getColumnCasing(orderByUnit))
  368. );
  369. } else if ((0, import_entity.is)(orderByUnit, import_sql.SQL)) {
  370. for (let i = 0; i < orderByUnit.queryChunks.length; i++) {
  371. const chunk = orderByUnit.queryChunks[i];
  372. if ((0, import_entity.is)(chunk, import_common.MySqlColumn)) {
  373. orderByUnit.queryChunks[i] = import_sql.sql.identifier(
  374. this.casing.getColumnCasing(chunk)
  375. );
  376. }
  377. }
  378. orderByValues.push(import_sql.sql`${orderByUnit}`);
  379. } else {
  380. orderByValues.push(import_sql.sql`${orderByUnit}`);
  381. }
  382. }
  383. orderBySql = import_sql.sql` order by ${import_sql.sql.join(orderByValues, import_sql.sql`, `)} `;
  384. }
  385. const limitSql = typeof limit === "object" || typeof limit === "number" && limit >= 0 ? import_sql.sql` limit ${limit}` : void 0;
  386. const operatorChunk = import_sql.sql.raw(`${type} ${isAll ? "all " : ""}`);
  387. const offsetSql = offset ? import_sql.sql` offset ${offset}` : void 0;
  388. return import_sql.sql`${leftChunk}${operatorChunk}${rightChunk}${orderBySql}${limitSql}${offsetSql}`;
  389. }
  390. buildInsertQuery({
  391. table,
  392. values: valuesOrSelect,
  393. ignore,
  394. onConflict,
  395. select
  396. }) {
  397. const valuesSqlList = [];
  398. const columns = table[import_table.Table.Symbol.Columns];
  399. const colEntries = Object.entries(columns).filter(
  400. ([_, col]) => !col.shouldDisableInsert()
  401. );
  402. const insertOrder = colEntries.map(([, column]) => import_sql.sql.identifier(this.casing.getColumnCasing(column)));
  403. const generatedIdsResponse = [];
  404. if (select) {
  405. const select2 = valuesOrSelect;
  406. if ((0, import_entity.is)(select2, import_sql.SQL)) {
  407. valuesSqlList.push(select2);
  408. } else {
  409. valuesSqlList.push(select2.getSQL());
  410. }
  411. } else {
  412. const values = valuesOrSelect;
  413. valuesSqlList.push(import_sql.sql.raw("values "));
  414. for (const [valueIndex, value] of values.entries()) {
  415. const generatedIds = {};
  416. const valueList = [];
  417. for (const [fieldName, col] of colEntries) {
  418. const colValue = value[fieldName];
  419. if (colValue === void 0 || (0, import_entity.is)(colValue, import_sql.Param) && colValue.value === void 0) {
  420. if (col.defaultFn !== void 0) {
  421. const defaultFnResult = col.defaultFn();
  422. generatedIds[fieldName] = defaultFnResult;
  423. const defaultValue = (0, import_entity.is)(defaultFnResult, import_sql.SQL) ? defaultFnResult : import_sql.sql.param(defaultFnResult, col);
  424. valueList.push(defaultValue);
  425. } else if (!col.default && col.onUpdateFn !== void 0) {
  426. const onUpdateFnResult = col.onUpdateFn();
  427. const newValue = (0, import_entity.is)(onUpdateFnResult, import_sql.SQL) ? onUpdateFnResult : import_sql.sql.param(onUpdateFnResult, col);
  428. valueList.push(newValue);
  429. } else {
  430. valueList.push(import_sql.sql`default`);
  431. }
  432. } else {
  433. if (col.defaultFn && (0, import_entity.is)(colValue, import_sql.Param)) {
  434. generatedIds[fieldName] = colValue.value;
  435. }
  436. valueList.push(colValue);
  437. }
  438. }
  439. generatedIdsResponse.push(generatedIds);
  440. valuesSqlList.push(valueList);
  441. if (valueIndex < values.length - 1) {
  442. valuesSqlList.push(import_sql.sql`, `);
  443. }
  444. }
  445. }
  446. const valuesSql = import_sql.sql.join(valuesSqlList);
  447. const ignoreSql = ignore ? import_sql.sql` ignore` : void 0;
  448. const onConflictSql = onConflict ? import_sql.sql` on duplicate key ${onConflict}` : void 0;
  449. return {
  450. sql: import_sql.sql`insert${ignoreSql} into ${table} ${insertOrder} ${valuesSql}${onConflictSql}`,
  451. generatedIds: generatedIdsResponse
  452. };
  453. }
  454. sqlToQuery(sql2, invokeSource) {
  455. return sql2.toQuery({
  456. casing: this.casing,
  457. escapeName: this.escapeName,
  458. escapeParam: this.escapeParam,
  459. escapeString: this.escapeString,
  460. invokeSource
  461. });
  462. }
  463. buildRelationalQuery({
  464. fullSchema,
  465. schema,
  466. tableNamesMap,
  467. table,
  468. tableConfig,
  469. queryConfig: config,
  470. tableAlias,
  471. nestedQueryRelation,
  472. joinOn
  473. }) {
  474. let selection = [];
  475. let limit, offset, orderBy, where;
  476. const joins = [];
  477. if (config === true) {
  478. const selectionEntries = Object.entries(tableConfig.columns);
  479. selection = selectionEntries.map(([key, value]) => ({
  480. dbKey: value.name,
  481. tsKey: key,
  482. field: (0, import_alias.aliasedTableColumn)(value, tableAlias),
  483. relationTableTsKey: void 0,
  484. isJson: false,
  485. selection: []
  486. }));
  487. } else {
  488. const aliasedColumns = Object.fromEntries(
  489. Object.entries(tableConfig.columns).map(([key, value]) => [
  490. key,
  491. (0, import_alias.aliasedTableColumn)(value, tableAlias)
  492. ])
  493. );
  494. if (config.where) {
  495. const whereSql = typeof config.where === "function" ? config.where(aliasedColumns, (0, import_relations.getOperators)()) : config.where;
  496. where = whereSql && (0, import_alias.mapColumnsInSQLToAlias)(whereSql, tableAlias);
  497. }
  498. const fieldsSelection = [];
  499. let selectedColumns = [];
  500. if (config.columns) {
  501. let isIncludeMode = false;
  502. for (const [field, value] of Object.entries(config.columns)) {
  503. if (value === void 0) {
  504. continue;
  505. }
  506. if (field in tableConfig.columns) {
  507. if (!isIncludeMode && value === true) {
  508. isIncludeMode = true;
  509. }
  510. selectedColumns.push(field);
  511. }
  512. }
  513. if (selectedColumns.length > 0) {
  514. selectedColumns = isIncludeMode ? selectedColumns.filter((c) => config.columns?.[c] === true) : Object.keys(tableConfig.columns).filter(
  515. (key) => !selectedColumns.includes(key)
  516. );
  517. }
  518. } else {
  519. selectedColumns = Object.keys(tableConfig.columns);
  520. }
  521. for (const field of selectedColumns) {
  522. const column = tableConfig.columns[field];
  523. fieldsSelection.push({ tsKey: field, value: column });
  524. }
  525. let selectedRelations = [];
  526. if (config.with) {
  527. selectedRelations = Object.entries(config.with).filter(
  528. (entry) => !!entry[1]
  529. ).map(([tsKey, queryConfig]) => ({
  530. tsKey,
  531. queryConfig,
  532. relation: tableConfig.relations[tsKey]
  533. }));
  534. }
  535. let extras;
  536. if (config.extras) {
  537. extras = typeof config.extras === "function" ? config.extras(aliasedColumns, { sql: import_sql.sql }) : config.extras;
  538. for (const [tsKey, value] of Object.entries(extras)) {
  539. fieldsSelection.push({
  540. tsKey,
  541. value: (0, import_alias.mapColumnsInAliasedSQLToAlias)(value, tableAlias)
  542. });
  543. }
  544. }
  545. for (const { tsKey, value } of fieldsSelection) {
  546. selection.push({
  547. dbKey: (0, import_entity.is)(value, import_sql.SQL.Aliased) ? value.fieldAlias : tableConfig.columns[tsKey].name,
  548. tsKey,
  549. field: (0, import_entity.is)(value, import_column.Column) ? (0, import_alias.aliasedTableColumn)(value, tableAlias) : value,
  550. relationTableTsKey: void 0,
  551. isJson: false,
  552. selection: []
  553. });
  554. }
  555. let orderByOrig = typeof config.orderBy === "function" ? config.orderBy(aliasedColumns, (0, import_relations.getOrderByOperators)()) : config.orderBy ?? [];
  556. if (!Array.isArray(orderByOrig)) {
  557. orderByOrig = [orderByOrig];
  558. }
  559. orderBy = orderByOrig.map((orderByValue) => {
  560. if ((0, import_entity.is)(orderByValue, import_column.Column)) {
  561. return (0, import_alias.aliasedTableColumn)(orderByValue, tableAlias);
  562. }
  563. return (0, import_alias.mapColumnsInSQLToAlias)(orderByValue, tableAlias);
  564. });
  565. limit = config.limit;
  566. offset = config.offset;
  567. for (const {
  568. tsKey: selectedRelationTsKey,
  569. queryConfig: selectedRelationConfigValue,
  570. relation
  571. } of selectedRelations) {
  572. const normalizedRelation = (0, import_relations.normalizeRelation)(
  573. schema,
  574. tableNamesMap,
  575. relation
  576. );
  577. const relationTableName = (0, import_table.getTableUniqueName)(relation.referencedTable);
  578. const relationTableTsName = tableNamesMap[relationTableName];
  579. const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`;
  580. const joinOn2 = (0, import_expressions.and)(
  581. ...normalizedRelation.fields.map(
  582. (field2, i) => (0, import_expressions.eq)(
  583. (0, import_alias.aliasedTableColumn)(
  584. normalizedRelation.references[i],
  585. relationTableAlias
  586. ),
  587. (0, import_alias.aliasedTableColumn)(field2, tableAlias)
  588. )
  589. )
  590. );
  591. const builtRelation = this.buildRelationalQuery({
  592. fullSchema,
  593. schema,
  594. tableNamesMap,
  595. table: fullSchema[relationTableTsName],
  596. tableConfig: schema[relationTableTsName],
  597. queryConfig: (0, import_entity.is)(relation, import_relations.One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue,
  598. tableAlias: relationTableAlias,
  599. joinOn: joinOn2,
  600. nestedQueryRelation: relation
  601. });
  602. const field = import_sql.sql`${import_sql.sql.identifier(relationTableAlias)}.${import_sql.sql.identifier("data")}`.as(
  603. selectedRelationTsKey
  604. );
  605. joins.push({
  606. on: import_sql.sql`true`,
  607. table: new import_subquery.Subquery(builtRelation.sql, {}, relationTableAlias),
  608. alias: relationTableAlias,
  609. joinType: "left",
  610. lateral: true
  611. });
  612. selection.push({
  613. dbKey: selectedRelationTsKey,
  614. tsKey: selectedRelationTsKey,
  615. field,
  616. relationTableTsKey: relationTableTsName,
  617. isJson: true,
  618. selection: builtRelation.selection
  619. });
  620. }
  621. }
  622. if (selection.length === 0) {
  623. throw new import_errors.DrizzleError({
  624. message: `No fields selected for table "${tableConfig.tsName}" ("${tableAlias}")`
  625. });
  626. }
  627. let result;
  628. where = (0, import_expressions.and)(joinOn, where);
  629. if (nestedQueryRelation) {
  630. let field = import_sql.sql`json_array(${import_sql.sql.join(
  631. selection.map(
  632. ({ field: field2, tsKey, isJson }) => isJson ? import_sql.sql`${import_sql.sql.identifier(`${tableAlias}_${tsKey}`)}.${import_sql.sql.identifier("data")}` : (0, import_entity.is)(field2, import_sql.SQL.Aliased) ? field2.sql : field2
  633. ),
  634. import_sql.sql`, `
  635. )})`;
  636. if ((0, import_entity.is)(nestedQueryRelation, import_relations.Many)) {
  637. field = import_sql.sql`coalesce(json_arrayagg(${field}), json_array())`;
  638. }
  639. const nestedSelection = [
  640. {
  641. dbKey: "data",
  642. tsKey: "data",
  643. field: field.as("data"),
  644. isJson: true,
  645. relationTableTsKey: tableConfig.tsName,
  646. selection
  647. }
  648. ];
  649. const needsSubquery = limit !== void 0 || offset !== void 0 || (orderBy?.length ?? 0) > 0;
  650. if (needsSubquery) {
  651. result = this.buildSelectQuery({
  652. table: (0, import_alias.aliasedTable)(table, tableAlias),
  653. fields: {},
  654. fieldsFlat: [
  655. {
  656. path: [],
  657. field: import_sql.sql.raw("*")
  658. },
  659. ...((orderBy?.length ?? 0) > 0 ? [
  660. {
  661. path: [],
  662. field: import_sql.sql`row_number() over (order by ${import_sql.sql.join(orderBy, import_sql.sql`, `)})`
  663. }
  664. ] : [])
  665. ],
  666. where,
  667. limit,
  668. offset,
  669. setOperators: []
  670. });
  671. where = void 0;
  672. limit = void 0;
  673. offset = void 0;
  674. orderBy = void 0;
  675. } else {
  676. result = (0, import_alias.aliasedTable)(table, tableAlias);
  677. }
  678. result = this.buildSelectQuery({
  679. table: (0, import_entity.is)(result, import_table2.MySqlTable) ? result : new import_subquery.Subquery(result, {}, tableAlias),
  680. fields: {},
  681. fieldsFlat: nestedSelection.map(({ field: field2 }) => ({
  682. path: [],
  683. field: (0, import_entity.is)(field2, import_column.Column) ? (0, import_alias.aliasedTableColumn)(field2, tableAlias) : field2
  684. })),
  685. joins,
  686. where,
  687. limit,
  688. offset,
  689. orderBy,
  690. setOperators: []
  691. });
  692. } else {
  693. result = this.buildSelectQuery({
  694. table: (0, import_alias.aliasedTable)(table, tableAlias),
  695. fields: {},
  696. fieldsFlat: selection.map(({ field }) => ({
  697. path: [],
  698. field: (0, import_entity.is)(field, import_column.Column) ? (0, import_alias.aliasedTableColumn)(field, tableAlias) : field
  699. })),
  700. joins,
  701. where,
  702. limit,
  703. offset,
  704. orderBy,
  705. setOperators: []
  706. });
  707. }
  708. return {
  709. tableTsKey: tableConfig.tsName,
  710. sql: result,
  711. selection
  712. };
  713. }
  714. buildRelationalQueryWithoutLateralSubqueries({
  715. fullSchema,
  716. schema,
  717. tableNamesMap,
  718. table,
  719. tableConfig,
  720. queryConfig: config,
  721. tableAlias,
  722. nestedQueryRelation,
  723. joinOn
  724. }) {
  725. let selection = [];
  726. let limit, offset, orderBy = [], where;
  727. if (config === true) {
  728. const selectionEntries = Object.entries(tableConfig.columns);
  729. selection = selectionEntries.map(([key, value]) => ({
  730. dbKey: value.name,
  731. tsKey: key,
  732. field: (0, import_alias.aliasedTableColumn)(value, tableAlias),
  733. relationTableTsKey: void 0,
  734. isJson: false,
  735. selection: []
  736. }));
  737. } else {
  738. const aliasedColumns = Object.fromEntries(
  739. Object.entries(tableConfig.columns).map(([key, value]) => [
  740. key,
  741. (0, import_alias.aliasedTableColumn)(value, tableAlias)
  742. ])
  743. );
  744. if (config.where) {
  745. const whereSql = typeof config.where === "function" ? config.where(aliasedColumns, (0, import_relations.getOperators)()) : config.where;
  746. where = whereSql && (0, import_alias.mapColumnsInSQLToAlias)(whereSql, tableAlias);
  747. }
  748. const fieldsSelection = [];
  749. let selectedColumns = [];
  750. if (config.columns) {
  751. let isIncludeMode = false;
  752. for (const [field, value] of Object.entries(config.columns)) {
  753. if (value === void 0) {
  754. continue;
  755. }
  756. if (field in tableConfig.columns) {
  757. if (!isIncludeMode && value === true) {
  758. isIncludeMode = true;
  759. }
  760. selectedColumns.push(field);
  761. }
  762. }
  763. if (selectedColumns.length > 0) {
  764. selectedColumns = isIncludeMode ? selectedColumns.filter((c) => config.columns?.[c] === true) : Object.keys(tableConfig.columns).filter(
  765. (key) => !selectedColumns.includes(key)
  766. );
  767. }
  768. } else {
  769. selectedColumns = Object.keys(tableConfig.columns);
  770. }
  771. for (const field of selectedColumns) {
  772. const column = tableConfig.columns[field];
  773. fieldsSelection.push({ tsKey: field, value: column });
  774. }
  775. let selectedRelations = [];
  776. if (config.with) {
  777. selectedRelations = Object.entries(config.with).filter(
  778. (entry) => !!entry[1]
  779. ).map(([tsKey, queryConfig]) => ({
  780. tsKey,
  781. queryConfig,
  782. relation: tableConfig.relations[tsKey]
  783. }));
  784. }
  785. let extras;
  786. if (config.extras) {
  787. extras = typeof config.extras === "function" ? config.extras(aliasedColumns, { sql: import_sql.sql }) : config.extras;
  788. for (const [tsKey, value] of Object.entries(extras)) {
  789. fieldsSelection.push({
  790. tsKey,
  791. value: (0, import_alias.mapColumnsInAliasedSQLToAlias)(value, tableAlias)
  792. });
  793. }
  794. }
  795. for (const { tsKey, value } of fieldsSelection) {
  796. selection.push({
  797. dbKey: (0, import_entity.is)(value, import_sql.SQL.Aliased) ? value.fieldAlias : tableConfig.columns[tsKey].name,
  798. tsKey,
  799. field: (0, import_entity.is)(value, import_column.Column) ? (0, import_alias.aliasedTableColumn)(value, tableAlias) : value,
  800. relationTableTsKey: void 0,
  801. isJson: false,
  802. selection: []
  803. });
  804. }
  805. let orderByOrig = typeof config.orderBy === "function" ? config.orderBy(aliasedColumns, (0, import_relations.getOrderByOperators)()) : config.orderBy ?? [];
  806. if (!Array.isArray(orderByOrig)) {
  807. orderByOrig = [orderByOrig];
  808. }
  809. orderBy = orderByOrig.map((orderByValue) => {
  810. if ((0, import_entity.is)(orderByValue, import_column.Column)) {
  811. return (0, import_alias.aliasedTableColumn)(orderByValue, tableAlias);
  812. }
  813. return (0, import_alias.mapColumnsInSQLToAlias)(orderByValue, tableAlias);
  814. });
  815. limit = config.limit;
  816. offset = config.offset;
  817. for (const {
  818. tsKey: selectedRelationTsKey,
  819. queryConfig: selectedRelationConfigValue,
  820. relation
  821. } of selectedRelations) {
  822. const normalizedRelation = (0, import_relations.normalizeRelation)(
  823. schema,
  824. tableNamesMap,
  825. relation
  826. );
  827. const relationTableName = (0, import_table.getTableUniqueName)(relation.referencedTable);
  828. const relationTableTsName = tableNamesMap[relationTableName];
  829. const relationTableAlias = `${tableAlias}_${selectedRelationTsKey}`;
  830. const joinOn2 = (0, import_expressions.and)(
  831. ...normalizedRelation.fields.map(
  832. (field2, i) => (0, import_expressions.eq)(
  833. (0, import_alias.aliasedTableColumn)(
  834. normalizedRelation.references[i],
  835. relationTableAlias
  836. ),
  837. (0, import_alias.aliasedTableColumn)(field2, tableAlias)
  838. )
  839. )
  840. );
  841. const builtRelation = this.buildRelationalQueryWithoutLateralSubqueries(
  842. {
  843. fullSchema,
  844. schema,
  845. tableNamesMap,
  846. table: fullSchema[relationTableTsName],
  847. tableConfig: schema[relationTableTsName],
  848. queryConfig: (0, import_entity.is)(relation, import_relations.One) ? selectedRelationConfigValue === true ? { limit: 1 } : { ...selectedRelationConfigValue, limit: 1 } : selectedRelationConfigValue,
  849. tableAlias: relationTableAlias,
  850. joinOn: joinOn2,
  851. nestedQueryRelation: relation
  852. }
  853. );
  854. let fieldSql = import_sql.sql`(${builtRelation.sql})`;
  855. if ((0, import_entity.is)(relation, import_relations.Many)) {
  856. fieldSql = import_sql.sql`coalesce(${fieldSql}, json_array())`;
  857. }
  858. const field = fieldSql.as(selectedRelationTsKey);
  859. selection.push({
  860. dbKey: selectedRelationTsKey,
  861. tsKey: selectedRelationTsKey,
  862. field,
  863. relationTableTsKey: relationTableTsName,
  864. isJson: true,
  865. selection: builtRelation.selection
  866. });
  867. }
  868. }
  869. if (selection.length === 0) {
  870. throw new import_errors.DrizzleError({
  871. 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.`
  872. });
  873. }
  874. let result;
  875. where = (0, import_expressions.and)(joinOn, where);
  876. if (nestedQueryRelation) {
  877. let field = import_sql.sql`json_array(${import_sql.sql.join(
  878. selection.map(
  879. ({ field: field2 }) => (0, import_entity.is)(field2, import_common.MySqlColumn) ? import_sql.sql.identifier(this.casing.getColumnCasing(field2)) : (0, import_entity.is)(field2, import_sql.SQL.Aliased) ? field2.sql : field2
  880. ),
  881. import_sql.sql`, `
  882. )})`;
  883. if ((0, import_entity.is)(nestedQueryRelation, import_relations.Many)) {
  884. field = import_sql.sql`json_arrayagg(${field})`;
  885. }
  886. const nestedSelection = [
  887. {
  888. dbKey: "data",
  889. tsKey: "data",
  890. field,
  891. isJson: true,
  892. relationTableTsKey: tableConfig.tsName,
  893. selection
  894. }
  895. ];
  896. const needsSubquery = limit !== void 0 || offset !== void 0 || orderBy.length > 0;
  897. if (needsSubquery) {
  898. result = this.buildSelectQuery({
  899. table: (0, import_alias.aliasedTable)(table, tableAlias),
  900. fields: {},
  901. fieldsFlat: [
  902. {
  903. path: [],
  904. field: import_sql.sql.raw("*")
  905. },
  906. ...(orderBy.length > 0 ? [
  907. {
  908. path: [],
  909. field: import_sql.sql`row_number() over (order by ${import_sql.sql.join(orderBy, import_sql.sql`, `)})`
  910. }
  911. ] : [])
  912. ],
  913. where,
  914. limit,
  915. offset,
  916. setOperators: []
  917. });
  918. where = void 0;
  919. limit = void 0;
  920. offset = void 0;
  921. orderBy = void 0;
  922. } else {
  923. result = (0, import_alias.aliasedTable)(table, tableAlias);
  924. }
  925. result = this.buildSelectQuery({
  926. table: (0, import_entity.is)(result, import_table2.MySqlTable) ? result : new import_subquery.Subquery(result, {}, tableAlias),
  927. fields: {},
  928. fieldsFlat: nestedSelection.map(({ field: field2 }) => ({
  929. path: [],
  930. field: (0, import_entity.is)(field2, import_column.Column) ? (0, import_alias.aliasedTableColumn)(field2, tableAlias) : field2
  931. })),
  932. where,
  933. limit,
  934. offset,
  935. orderBy,
  936. setOperators: []
  937. });
  938. } else {
  939. result = this.buildSelectQuery({
  940. table: (0, import_alias.aliasedTable)(table, tableAlias),
  941. fields: {},
  942. fieldsFlat: selection.map(({ field }) => ({
  943. path: [],
  944. field: (0, import_entity.is)(field, import_column.Column) ? (0, import_alias.aliasedTableColumn)(field, tableAlias) : field
  945. })),
  946. where,
  947. limit,
  948. offset,
  949. orderBy,
  950. setOperators: []
  951. });
  952. }
  953. return {
  954. tableTsKey: tableConfig.tsName,
  955. sql: result,
  956. selection
  957. };
  958. }
  959. }
  960. // Annotate the CommonJS export names for ESM import in node:
  961. 0 && (module.exports = {
  962. MySqlDialect
  963. });
  964. //# sourceMappingURL=dialect.cjs.map