kysely 0.27.5 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/CODE_OF_CONDUCT.md +183 -0
  2. package/FUNDING.md +25 -0
  3. package/README.md +182 -3
  4. package/deno.check.d.ts +7 -0
  5. package/dist/cjs/dialect/mssql/mssql-dialect-config.d.ts +26 -16
  6. package/dist/cjs/dialect/mssql/mssql-driver.d.ts +6 -3
  7. package/dist/cjs/dialect/mssql/mssql-driver.js +33 -19
  8. package/dist/cjs/dialect/mssql/mssql-query-compiler.d.ts +2 -0
  9. package/dist/cjs/dialect/mssql/mssql-query-compiler.js +11 -0
  10. package/dist/cjs/dialect/mysql/mysql-driver.d.ts +4 -0
  11. package/dist/cjs/dialect/mysql/mysql-driver.js +27 -12
  12. package/dist/cjs/dialect/postgres/postgres-driver.d.ts +4 -0
  13. package/dist/cjs/dialect/postgres/postgres-driver.js +28 -18
  14. package/dist/cjs/dialect/postgres/postgres-introspector.js +7 -17
  15. package/dist/cjs/dialect/sqlite/sqlite-driver.d.ts +4 -0
  16. package/dist/cjs/dialect/sqlite/sqlite-driver.js +19 -13
  17. package/dist/cjs/dialect/sqlite/sqlite-introspector.js +66 -44
  18. package/dist/cjs/dialect/sqlite/sqlite-query-compiler.d.ts +2 -0
  19. package/dist/cjs/dialect/sqlite/sqlite-query-compiler.js +4 -0
  20. package/dist/cjs/driver/database-connection.d.ts +0 -4
  21. package/dist/cjs/driver/driver.d.ts +17 -0
  22. package/dist/cjs/driver/driver.js +13 -1
  23. package/dist/cjs/driver/dummy-driver.d.ts +3 -0
  24. package/dist/cjs/driver/dummy-driver.js +9 -0
  25. package/dist/cjs/driver/runtime-driver.d.ts +4 -0
  26. package/dist/cjs/driver/runtime-driver.js +43 -3
  27. package/dist/cjs/expression/expression-builder.d.ts +9 -10
  28. package/dist/cjs/helpers/postgres.d.ts +48 -0
  29. package/dist/cjs/helpers/postgres.js +50 -0
  30. package/dist/cjs/index.d.ts +13 -2
  31. package/dist/cjs/index.js +13 -2
  32. package/dist/cjs/kysely.d.ts +339 -2
  33. package/dist/cjs/kysely.js +465 -11
  34. package/dist/cjs/migration/migrator.d.ts +16 -1
  35. package/dist/cjs/migration/migrator.js +14 -4
  36. package/dist/cjs/operation-node/aggregate-function-node.d.ts +2 -1
  37. package/dist/cjs/operation-node/aggregate-function-node.js +4 -3
  38. package/dist/cjs/operation-node/alter-table-node.d.ts +3 -1
  39. package/dist/cjs/operation-node/collate-node.d.ts +13 -0
  40. package/dist/cjs/operation-node/collate-node.js +19 -0
  41. package/dist/cjs/operation-node/constraint-node.d.ts +1 -1
  42. package/dist/cjs/operation-node/create-type-node.d.ts +1 -1
  43. package/dist/cjs/operation-node/create-type-node.js +1 -1
  44. package/dist/cjs/operation-node/delete-query-node.d.ts +8 -2
  45. package/dist/cjs/operation-node/delete-query-node.js +11 -15
  46. package/dist/cjs/operation-node/foreign-key-constraint-node.d.ts +4 -0
  47. package/dist/cjs/operation-node/insert-query-node.d.ts +3 -0
  48. package/dist/cjs/operation-node/join-node.d.ts +1 -1
  49. package/dist/cjs/operation-node/merge-query-node.d.ts +2 -0
  50. package/dist/cjs/operation-node/operation-node-transformer.d.ts +106 -97
  51. package/dist/cjs/operation-node/operation-node-transformer.js +352 -312
  52. package/dist/cjs/operation-node/operation-node-visitor.d.ts +9 -1
  53. package/dist/cjs/operation-node/operation-node-visitor.js +4 -0
  54. package/dist/cjs/operation-node/operation-node.d.ts +1 -1
  55. package/dist/cjs/operation-node/or-action-node.d.ts +12 -0
  56. package/dist/cjs/operation-node/or-action-node.js +18 -0
  57. package/dist/cjs/operation-node/order-by-item-node.d.ts +5 -0
  58. package/dist/cjs/operation-node/order-by-item-node.js +6 -0
  59. package/dist/cjs/operation-node/primary-key-constraint-node.d.ts +29 -0
  60. package/dist/cjs/operation-node/{primary-constraint-node.js → primary-key-constraint-node.js} +11 -2
  61. package/dist/cjs/operation-node/query-node.d.ts +7 -0
  62. package/dist/cjs/operation-node/query-node.js +15 -0
  63. package/dist/cjs/operation-node/refresh-materialized-view-node.d.ts +17 -0
  64. package/dist/cjs/operation-node/refresh-materialized-view-node.js +25 -0
  65. package/dist/cjs/operation-node/rename-constraint-node.d.ts +14 -0
  66. package/dist/cjs/operation-node/rename-constraint-node.js +20 -0
  67. package/dist/cjs/operation-node/select-query-node.d.ts +8 -2
  68. package/dist/cjs/operation-node/select-query-node.js +11 -15
  69. package/dist/cjs/operation-node/unique-constraint-node.d.ts +2 -0
  70. package/dist/cjs/operation-node/update-query-node.d.ts +3 -4
  71. package/dist/cjs/operation-node/update-query-node.js +5 -2
  72. package/dist/cjs/parser/collate-parser.d.ts +1 -0
  73. package/dist/cjs/parser/collate-parser.js +2 -0
  74. package/dist/cjs/parser/delete-from-parser.d.ts +5 -0
  75. package/dist/cjs/parser/delete-from-parser.js +2 -0
  76. package/dist/cjs/parser/insert-values-parser.js +3 -1
  77. package/dist/cjs/parser/join-parser.d.ts +1 -1
  78. package/dist/cjs/parser/join-parser.js +7 -1
  79. package/dist/cjs/parser/merge-into-parser.d.ts +5 -0
  80. package/dist/cjs/parser/merge-into-parser.js +2 -0
  81. package/dist/cjs/parser/order-by-parser.d.ts +18 -5
  82. package/dist/cjs/parser/order-by-parser.js +24 -14
  83. package/dist/cjs/parser/savepoint-parser.d.ts +4 -0
  84. package/dist/cjs/parser/savepoint-parser.js +11 -0
  85. package/dist/cjs/parser/select-from-parser.d.ts +4 -0
  86. package/dist/cjs/parser/select-from-parser.js +2 -0
  87. package/dist/cjs/parser/table-parser.d.ts +2 -5
  88. package/dist/cjs/parser/update-parser.d.ts +5 -0
  89. package/dist/cjs/parser/update-parser.js +2 -0
  90. package/dist/cjs/parser/update-set-parser.d.ts +7 -4
  91. package/dist/cjs/plugin/camel-case/camel-case-plugin.js +1 -1
  92. package/dist/cjs/plugin/camel-case/camel-case-transformer.d.ts +2 -1
  93. package/dist/cjs/plugin/camel-case/camel-case-transformer.js +2 -2
  94. package/dist/cjs/plugin/camel-case/camel-case.js +4 -1
  95. package/dist/cjs/plugin/deduplicate-joins/deduplicate-joins-plugin.js +1 -1
  96. package/dist/cjs/plugin/deduplicate-joins/deduplicate-joins-transformer.d.ts +4 -3
  97. package/dist/cjs/plugin/deduplicate-joins/deduplicate-joins-transformer.js +6 -6
  98. package/dist/cjs/plugin/handle-empty-in-lists/handle-empty-in-lists-plugin.d.ts +211 -0
  99. package/dist/cjs/plugin/handle-empty-in-lists/handle-empty-in-lists-plugin.js +162 -0
  100. package/dist/cjs/plugin/handle-empty-in-lists/handle-empty-in-lists-transformer.d.ts +8 -0
  101. package/dist/cjs/plugin/handle-empty-in-lists/handle-empty-in-lists-transformer.js +29 -0
  102. package/dist/cjs/plugin/handle-empty-in-lists/handle-empty-in-lists.d.ts +44 -0
  103. package/dist/cjs/plugin/handle-empty-in-lists/handle-empty-in-lists.js +66 -0
  104. package/dist/cjs/plugin/immediate-value/immediate-value-plugin.js +1 -1
  105. package/dist/cjs/plugin/immediate-value/immediate-value-transformer.d.ts +2 -0
  106. package/dist/cjs/plugin/immediate-value/immediate-value-transformer.js +6 -4
  107. package/dist/cjs/plugin/with-schema/with-schema-plugin.js +1 -1
  108. package/dist/cjs/plugin/with-schema/with-schema-transformer.d.ts +8 -3
  109. package/dist/cjs/plugin/with-schema/with-schema-transformer.js +45 -14
  110. package/dist/cjs/query-builder/aggregate-function-builder.d.ts +83 -5
  111. package/dist/cjs/query-builder/aggregate-function-builder.js +15 -27
  112. package/dist/cjs/query-builder/cte-builder.js +0 -2
  113. package/dist/cjs/query-builder/delete-query-builder.d.ts +36 -47
  114. package/dist/cjs/query-builder/delete-query-builder.js +12 -78
  115. package/dist/cjs/query-builder/function-module.d.ts +31 -4
  116. package/dist/cjs/query-builder/insert-query-builder.d.ts +161 -6
  117. package/dist/cjs/query-builder/insert-query-builder.js +197 -10
  118. package/dist/cjs/query-builder/join-builder.js +0 -2
  119. package/dist/cjs/query-builder/merge-query-builder.d.ts +145 -3
  120. package/dist/cjs/query-builder/merge-query-builder.js +28 -7
  121. package/dist/cjs/query-builder/on-conflict-builder.js +0 -4
  122. package/dist/cjs/query-builder/order-by-interface.d.ts +176 -0
  123. package/dist/cjs/query-builder/order-by-interface.js +2 -0
  124. package/dist/cjs/query-builder/order-by-item-builder.d.ts +43 -0
  125. package/dist/cjs/query-builder/order-by-item-builder.js +75 -0
  126. package/dist/cjs/query-builder/over-builder.d.ts +43 -6
  127. package/dist/cjs/query-builder/over-builder.js +8 -25
  128. package/dist/cjs/query-builder/returning-interface.d.ts +20 -3
  129. package/dist/cjs/query-builder/select-query-builder.d.ts +279 -98
  130. package/dist/cjs/query-builder/select-query-builder.js +26 -26
  131. package/dist/cjs/query-builder/update-query-builder.d.ts +88 -9
  132. package/dist/cjs/query-builder/update-query-builder.js +17 -15
  133. package/dist/cjs/query-compiler/compiled-query.d.ts +2 -0
  134. package/dist/cjs/query-compiler/compiled-query.js +2 -0
  135. package/dist/cjs/query-compiler/default-query-compiler.d.ts +17 -2
  136. package/dist/cjs/query-compiler/default-query-compiler.js +97 -2
  137. package/dist/cjs/query-compiler/query-compiler.d.ts +4 -2
  138. package/dist/cjs/query-creator.d.ts +23 -25
  139. package/dist/cjs/query-creator.js +280 -8
  140. package/dist/cjs/query-executor/default-query-executor.d.ts +2 -1
  141. package/dist/cjs/query-executor/default-query-executor.js +2 -2
  142. package/dist/cjs/query-executor/query-executor-base.js +7 -25
  143. package/dist/cjs/raw-builder/raw-builder.js +0 -3
  144. package/dist/cjs/raw-builder/sql.d.ts +4 -4
  145. package/dist/cjs/raw-builder/sql.js +1 -1
  146. package/dist/cjs/schema/alter-column-builder.js +0 -3
  147. package/dist/cjs/schema/alter-table-add-foreign-key-constraint-builder.d.ts +4 -0
  148. package/dist/cjs/schema/alter-table-add-foreign-key-constraint-builder.js +24 -2
  149. package/dist/cjs/schema/alter-table-add-index-builder.js +0 -2
  150. package/dist/cjs/schema/alter-table-builder.d.ts +7 -3
  151. package/dist/cjs/schema/alter-table-builder.js +21 -10
  152. package/dist/cjs/schema/alter-table-drop-constraint-builder.js +0 -2
  153. package/dist/cjs/schema/alter-table-executor.js +0 -2
  154. package/dist/cjs/schema/check-constraint-builder.d.ts +13 -0
  155. package/dist/cjs/schema/check-constraint-builder.js +20 -0
  156. package/dist/cjs/schema/column-definition-builder.js +0 -2
  157. package/dist/cjs/schema/create-index-builder.js +1 -3
  158. package/dist/cjs/schema/create-schema-builder.js +0 -2
  159. package/dist/cjs/schema/create-table-builder.d.ts +5 -4
  160. package/dist/cjs/schema/create-table-builder.js +9 -7
  161. package/dist/cjs/schema/create-type-builder.d.ts +1 -1
  162. package/dist/cjs/schema/create-type-builder.js +0 -2
  163. package/dist/cjs/schema/create-view-builder.js +0 -2
  164. package/dist/cjs/schema/drop-index-builder.js +0 -2
  165. package/dist/cjs/schema/drop-schema-builder.js +0 -2
  166. package/dist/cjs/schema/drop-table-builder.js +0 -2
  167. package/dist/cjs/schema/drop-type-builder.js +0 -2
  168. package/dist/cjs/schema/drop-view-builder.js +0 -2
  169. package/dist/cjs/schema/foreign-key-constraint-builder.d.ts +9 -0
  170. package/dist/cjs/schema/foreign-key-constraint-builder.js +16 -2
  171. package/dist/cjs/schema/primary-key-constraint-builder.d.ts +17 -0
  172. package/dist/cjs/schema/primary-key-constraint-builder.js +37 -0
  173. package/dist/cjs/schema/refresh-materialized-view-builder.d.ts +47 -0
  174. package/dist/cjs/schema/refresh-materialized-view-builder.js +75 -0
  175. package/dist/cjs/schema/schema.d.ts +14 -0
  176. package/dist/cjs/schema/schema.js +21 -0
  177. package/dist/cjs/schema/unique-constraint-builder.d.ts +10 -1
  178. package/dist/cjs/schema/unique-constraint-builder.js +26 -5
  179. package/dist/cjs/util/infer-result.d.ts +1 -1
  180. package/dist/cjs/util/log.d.ts +1 -0
  181. package/dist/cjs/util/log.js +3 -2
  182. package/dist/cjs/util/provide-controlled-connection.d.ts +7 -0
  183. package/dist/cjs/util/provide-controlled-connection.js +24 -0
  184. package/dist/esm/dialect/mssql/mssql-dialect-config.d.ts +26 -16
  185. package/dist/esm/dialect/mssql/mssql-driver.d.ts +6 -3
  186. package/dist/esm/dialect/mssql/mssql-driver.js +33 -19
  187. package/dist/esm/dialect/mssql/mssql-query-compiler.d.ts +2 -0
  188. package/dist/esm/dialect/mssql/mssql-query-compiler.js +11 -0
  189. package/dist/esm/dialect/mysql/mysql-driver.d.ts +4 -0
  190. package/dist/esm/dialect/mysql/mysql-driver.js +27 -12
  191. package/dist/esm/dialect/postgres/postgres-driver.d.ts +4 -0
  192. package/dist/esm/dialect/postgres/postgres-driver.js +28 -18
  193. package/dist/esm/dialect/postgres/postgres-introspector.js +7 -17
  194. package/dist/esm/dialect/sqlite/sqlite-driver.d.ts +4 -0
  195. package/dist/esm/dialect/sqlite/sqlite-driver.js +19 -13
  196. package/dist/esm/dialect/sqlite/sqlite-introspector.js +66 -44
  197. package/dist/esm/dialect/sqlite/sqlite-query-compiler.d.ts +2 -0
  198. package/dist/esm/dialect/sqlite/sqlite-query-compiler.js +4 -0
  199. package/dist/esm/driver/database-connection.d.ts +0 -4
  200. package/dist/esm/driver/driver.d.ts +17 -0
  201. package/dist/esm/driver/driver.js +11 -0
  202. package/dist/esm/driver/dummy-driver.d.ts +3 -0
  203. package/dist/esm/driver/dummy-driver.js +9 -0
  204. package/dist/esm/driver/runtime-driver.d.ts +4 -0
  205. package/dist/esm/driver/runtime-driver.js +43 -3
  206. package/dist/esm/expression/expression-builder.d.ts +9 -10
  207. package/dist/esm/helpers/postgres.d.ts +48 -0
  208. package/dist/esm/helpers/postgres.js +49 -0
  209. package/dist/esm/index.d.ts +13 -2
  210. package/dist/esm/index.js +11 -1
  211. package/dist/esm/kysely.d.ts +339 -2
  212. package/dist/esm/kysely.js +461 -10
  213. package/dist/esm/migration/migrator.d.ts +16 -1
  214. package/dist/esm/migration/migrator.js +14 -4
  215. package/dist/esm/operation-node/aggregate-function-node.d.ts +2 -1
  216. package/dist/esm/operation-node/aggregate-function-node.js +4 -3
  217. package/dist/esm/operation-node/alter-table-node.d.ts +3 -1
  218. package/dist/esm/operation-node/collate-node.d.ts +13 -0
  219. package/dist/esm/operation-node/collate-node.js +17 -0
  220. package/dist/esm/operation-node/constraint-node.d.ts +1 -1
  221. package/dist/esm/operation-node/create-type-node.d.ts +1 -1
  222. package/dist/esm/operation-node/create-type-node.js +1 -1
  223. package/dist/esm/operation-node/delete-query-node.d.ts +8 -2
  224. package/dist/esm/operation-node/delete-query-node.js +11 -15
  225. package/dist/esm/operation-node/foreign-key-constraint-node.d.ts +4 -0
  226. package/dist/esm/operation-node/insert-query-node.d.ts +3 -0
  227. package/dist/esm/operation-node/join-node.d.ts +1 -1
  228. package/dist/esm/operation-node/merge-query-node.d.ts +2 -0
  229. package/dist/esm/operation-node/operation-node-transformer.d.ts +106 -97
  230. package/dist/esm/operation-node/operation-node-transformer.js +352 -312
  231. package/dist/esm/operation-node/operation-node-visitor.d.ts +9 -1
  232. package/dist/esm/operation-node/operation-node-visitor.js +4 -0
  233. package/dist/esm/operation-node/operation-node.d.ts +1 -1
  234. package/dist/esm/operation-node/or-action-node.d.ts +12 -0
  235. package/dist/esm/operation-node/or-action-node.js +16 -0
  236. package/dist/esm/operation-node/order-by-item-node.d.ts +5 -0
  237. package/dist/esm/operation-node/order-by-item-node.js +6 -0
  238. package/dist/esm/operation-node/primary-key-constraint-node.d.ts +29 -0
  239. package/dist/esm/operation-node/{primary-constraint-node.js → primary-key-constraint-node.js} +11 -2
  240. package/dist/esm/operation-node/query-node.d.ts +7 -0
  241. package/dist/esm/operation-node/query-node.js +15 -0
  242. package/dist/esm/operation-node/refresh-materialized-view-node.d.ts +17 -0
  243. package/dist/esm/operation-node/refresh-materialized-view-node.js +23 -0
  244. package/dist/esm/operation-node/rename-constraint-node.d.ts +14 -0
  245. package/dist/esm/operation-node/rename-constraint-node.js +18 -0
  246. package/dist/esm/operation-node/select-query-node.d.ts +8 -2
  247. package/dist/esm/operation-node/select-query-node.js +11 -15
  248. package/dist/esm/operation-node/unique-constraint-node.d.ts +2 -0
  249. package/dist/esm/operation-node/update-query-node.d.ts +3 -4
  250. package/dist/esm/operation-node/update-query-node.js +5 -2
  251. package/dist/esm/parser/collate-parser.d.ts +1 -0
  252. package/dist/esm/parser/collate-parser.js +2 -0
  253. package/dist/esm/parser/delete-from-parser.d.ts +5 -0
  254. package/dist/esm/parser/delete-from-parser.js +2 -0
  255. package/dist/esm/parser/insert-values-parser.js +3 -1
  256. package/dist/esm/parser/join-parser.d.ts +1 -1
  257. package/dist/esm/parser/join-parser.js +7 -1
  258. package/dist/esm/parser/merge-into-parser.d.ts +5 -0
  259. package/dist/esm/parser/merge-into-parser.js +2 -0
  260. package/dist/esm/parser/order-by-parser.d.ts +18 -5
  261. package/dist/esm/parser/order-by-parser.js +27 -17
  262. package/dist/esm/parser/savepoint-parser.d.ts +4 -0
  263. package/dist/esm/parser/savepoint-parser.js +9 -0
  264. package/dist/esm/parser/select-from-parser.d.ts +4 -0
  265. package/dist/esm/parser/select-from-parser.js +2 -0
  266. package/dist/esm/parser/table-parser.d.ts +2 -5
  267. package/dist/esm/parser/update-parser.d.ts +5 -0
  268. package/dist/esm/parser/update-parser.js +2 -0
  269. package/dist/esm/parser/update-set-parser.d.ts +7 -4
  270. package/dist/esm/plugin/camel-case/camel-case-plugin.js +1 -1
  271. package/dist/esm/plugin/camel-case/camel-case-transformer.d.ts +2 -1
  272. package/dist/esm/plugin/camel-case/camel-case-transformer.js +2 -2
  273. package/dist/esm/plugin/camel-case/camel-case.js +4 -1
  274. package/dist/esm/plugin/deduplicate-joins/deduplicate-joins-plugin.js +1 -1
  275. package/dist/esm/plugin/deduplicate-joins/deduplicate-joins-transformer.d.ts +4 -3
  276. package/dist/esm/plugin/deduplicate-joins/deduplicate-joins-transformer.js +6 -6
  277. package/dist/esm/plugin/handle-empty-in-lists/handle-empty-in-lists-plugin.d.ts +211 -0
  278. package/dist/esm/plugin/handle-empty-in-lists/handle-empty-in-lists-plugin.js +159 -0
  279. package/dist/esm/plugin/handle-empty-in-lists/handle-empty-in-lists-transformer.d.ts +8 -0
  280. package/dist/esm/plugin/handle-empty-in-lists/handle-empty-in-lists-transformer.js +26 -0
  281. package/dist/esm/plugin/handle-empty-in-lists/handle-empty-in-lists.d.ts +44 -0
  282. package/dist/esm/plugin/handle-empty-in-lists/handle-empty-in-lists.js +63 -0
  283. package/dist/esm/plugin/immediate-value/immediate-value-plugin.js +1 -1
  284. package/dist/esm/plugin/immediate-value/immediate-value-transformer.d.ts +2 -0
  285. package/dist/esm/plugin/immediate-value/immediate-value-transformer.js +6 -4
  286. package/dist/esm/plugin/with-schema/with-schema-plugin.js +1 -1
  287. package/dist/esm/plugin/with-schema/with-schema-transformer.d.ts +8 -3
  288. package/dist/esm/plugin/with-schema/with-schema-transformer.js +45 -14
  289. package/dist/esm/query-builder/aggregate-function-builder.d.ts +83 -5
  290. package/dist/esm/query-builder/aggregate-function-builder.js +15 -27
  291. package/dist/esm/query-builder/cte-builder.js +0 -2
  292. package/dist/esm/query-builder/delete-query-builder.d.ts +36 -47
  293. package/dist/esm/query-builder/delete-query-builder.js +12 -78
  294. package/dist/esm/query-builder/function-module.d.ts +31 -4
  295. package/dist/esm/query-builder/insert-query-builder.d.ts +161 -6
  296. package/dist/esm/query-builder/insert-query-builder.js +197 -10
  297. package/dist/esm/query-builder/join-builder.js +0 -2
  298. package/dist/esm/query-builder/merge-query-builder.d.ts +145 -3
  299. package/dist/esm/query-builder/merge-query-builder.js +29 -8
  300. package/dist/esm/query-builder/on-conflict-builder.js +0 -4
  301. package/dist/esm/query-builder/order-by-interface.d.ts +176 -0
  302. package/dist/esm/query-builder/order-by-interface.js +2 -0
  303. package/dist/esm/query-builder/order-by-item-builder.d.ts +43 -0
  304. package/dist/esm/query-builder/order-by-item-builder.js +72 -0
  305. package/dist/esm/query-builder/over-builder.d.ts +43 -6
  306. package/dist/esm/query-builder/over-builder.js +8 -25
  307. package/dist/esm/query-builder/returning-interface.d.ts +20 -3
  308. package/dist/esm/query-builder/select-query-builder.d.ts +279 -98
  309. package/dist/esm/query-builder/select-query-builder.js +26 -26
  310. package/dist/esm/query-builder/update-query-builder.d.ts +88 -9
  311. package/dist/esm/query-builder/update-query-builder.js +17 -15
  312. package/dist/esm/query-compiler/compiled-query.d.ts +2 -0
  313. package/dist/esm/query-compiler/compiled-query.js +2 -0
  314. package/dist/esm/query-compiler/default-query-compiler.d.ts +17 -2
  315. package/dist/esm/query-compiler/default-query-compiler.js +97 -2
  316. package/dist/esm/query-compiler/query-compiler.d.ts +4 -2
  317. package/dist/esm/query-creator.d.ts +23 -25
  318. package/dist/esm/query-creator.js +281 -9
  319. package/dist/esm/query-executor/default-query-executor.d.ts +2 -1
  320. package/dist/esm/query-executor/default-query-executor.js +2 -2
  321. package/dist/esm/query-executor/query-executor-base.js +7 -25
  322. package/dist/esm/raw-builder/raw-builder.js +0 -3
  323. package/dist/esm/raw-builder/sql.d.ts +4 -4
  324. package/dist/esm/raw-builder/sql.js +1 -1
  325. package/dist/esm/schema/alter-column-builder.js +0 -3
  326. package/dist/esm/schema/alter-table-add-foreign-key-constraint-builder.d.ts +4 -0
  327. package/dist/esm/schema/alter-table-add-foreign-key-constraint-builder.js +24 -2
  328. package/dist/esm/schema/alter-table-add-index-builder.js +0 -2
  329. package/dist/esm/schema/alter-table-builder.d.ts +7 -3
  330. package/dist/esm/schema/alter-table-builder.js +22 -11
  331. package/dist/esm/schema/alter-table-drop-constraint-builder.js +0 -2
  332. package/dist/esm/schema/alter-table-executor.js +0 -2
  333. package/dist/esm/schema/check-constraint-builder.d.ts +13 -0
  334. package/dist/esm/schema/check-constraint-builder.js +17 -0
  335. package/dist/esm/schema/column-definition-builder.js +0 -2
  336. package/dist/esm/schema/create-index-builder.js +1 -3
  337. package/dist/esm/schema/create-schema-builder.js +0 -2
  338. package/dist/esm/schema/create-table-builder.d.ts +5 -4
  339. package/dist/esm/schema/create-table-builder.js +10 -8
  340. package/dist/esm/schema/create-type-builder.d.ts +1 -1
  341. package/dist/esm/schema/create-type-builder.js +0 -2
  342. package/dist/esm/schema/create-view-builder.js +0 -2
  343. package/dist/esm/schema/drop-index-builder.js +0 -2
  344. package/dist/esm/schema/drop-schema-builder.js +0 -2
  345. package/dist/esm/schema/drop-table-builder.js +0 -2
  346. package/dist/esm/schema/drop-type-builder.js +0 -2
  347. package/dist/esm/schema/drop-view-builder.js +0 -2
  348. package/dist/esm/schema/foreign-key-constraint-builder.d.ts +9 -0
  349. package/dist/esm/schema/foreign-key-constraint-builder.js +16 -2
  350. package/dist/esm/schema/primary-key-constraint-builder.d.ts +17 -0
  351. package/dist/esm/schema/primary-key-constraint-builder.js +34 -0
  352. package/dist/esm/schema/refresh-materialized-view-builder.d.ts +47 -0
  353. package/dist/esm/schema/refresh-materialized-view-builder.js +72 -0
  354. package/dist/esm/schema/schema.d.ts +14 -0
  355. package/dist/esm/schema/schema.js +21 -0
  356. package/dist/esm/schema/unique-constraint-builder.d.ts +10 -1
  357. package/dist/esm/schema/unique-constraint-builder.js +26 -5
  358. package/dist/esm/util/infer-result.d.ts +1 -1
  359. package/dist/esm/util/log.d.ts +1 -0
  360. package/dist/esm/util/log.js +3 -2
  361. package/dist/esm/util/provide-controlled-connection.d.ts +7 -0
  362. package/dist/esm/util/provide-controlled-connection.js +22 -0
  363. package/outdated-typescript.d.ts +5 -0
  364. package/package.json +16 -2
  365. package/CONTRIBUTING.md +0 -70
  366. package/dist/cjs/operation-node/primary-constraint-node.d.ts +0 -15
  367. package/dist/cjs/util/prevent-await.d.ts +0 -1
  368. package/dist/cjs/util/prevent-await.js +0 -13
  369. package/dist/esm/operation-node/primary-constraint-node.d.ts +0 -15
  370. package/dist/esm/util/prevent-await.d.ts +0 -1
  371. package/dist/esm/util/prevent-await.js +0 -11
@@ -1,9 +1,12 @@
1
1
  /// <reference types="./order-by-parser.d.ts" />
2
- import { isDynamicReferenceBuilder } from '../dynamic/dynamic-reference-builder.js';
2
+ import { isDynamicReferenceBuilder, } from '../dynamic/dynamic-reference-builder.js';
3
+ import { isExpression } from '../expression/expression.js';
3
4
  import { OrderByItemNode } from '../operation-node/order-by-item-node.js';
4
5
  import { RawNode } from '../operation-node/raw-node.js';
5
- import { isExpressionOrFactory, parseExpression } from './expression-parser.js';
6
- import { parseStringReference } from './reference-parser.js';
6
+ import { OrderByItemBuilder } from '../query-builder/order-by-item-builder.js';
7
+ import { logOnce } from '../util/log-once.js';
8
+ import { isExpressionOrFactory, parseExpression, } from './expression-parser.js';
9
+ import { parseStringReference, } from './reference-parser.js';
7
10
  export function isOrderByDirection(thing) {
8
11
  return thing === 'asc' || thing === 'desc';
9
12
  }
@@ -14,21 +17,22 @@ export function parseOrderBy(args) {
14
17
  if (args.length === 1) {
15
18
  const [orderBy] = args;
16
19
  if (Array.isArray(orderBy)) {
20
+ logOnce('orderBy(array) is deprecated, use multiple orderBy calls instead.');
17
21
  return orderBy.map((item) => parseOrderByItem(item));
18
22
  }
19
23
  return [parseOrderByItem(orderBy)];
20
24
  }
21
25
  throw new Error(`Invalid number of arguments at order by! expected 1-2, received ${args.length}`);
22
26
  }
23
- export function parseOrderByItem(ref, direction) {
24
- const parsedRef = parseOrderByExpression(ref);
27
+ export function parseOrderByItem(expr, modifiers) {
28
+ const parsedRef = parseOrderByExpression(expr);
25
29
  if (OrderByItemNode.is(parsedRef)) {
26
- if (direction) {
30
+ if (modifiers) {
27
31
  throw new Error('Cannot specify direction twice!');
28
32
  }
29
33
  return parsedRef;
30
34
  }
31
- return OrderByItemNode.create(parsedRef, parseOrderByDirectionExpression(direction));
35
+ return parseOrderByWithModifiers(parsedRef, modifiers);
32
36
  }
33
37
  function parseOrderByExpression(expr) {
34
38
  if (isExpressionOrFactory(expr)) {
@@ -39,19 +43,25 @@ function parseOrderByExpression(expr) {
39
43
  }
40
44
  const [ref, direction] = expr.split(' ');
41
45
  if (direction) {
42
- if (!isOrderByDirection(direction)) {
43
- throw new Error(`Invalid order by direction: ${direction}`);
44
- }
45
- return OrderByItemNode.create(parseStringReference(ref), parseOrderByDirectionExpression(direction));
46
+ logOnce("`orderBy('column asc')` is deprecated. Use `orderBy('column', 'asc')` instead.");
47
+ return parseOrderByWithModifiers(parseStringReference(ref), direction);
46
48
  }
47
49
  return parseStringReference(expr);
48
50
  }
49
- function parseOrderByDirectionExpression(expr) {
50
- if (!expr) {
51
- return undefined;
51
+ function parseOrderByWithModifiers(expr, modifiers) {
52
+ if (typeof modifiers === 'string') {
53
+ if (!isOrderByDirection(modifiers)) {
54
+ throw new Error(`Invalid order by direction: ${modifiers}`);
55
+ }
56
+ return OrderByItemNode.create(expr, RawNode.createWithSql(modifiers));
57
+ }
58
+ if (isExpression(modifiers)) {
59
+ logOnce("`orderBy(..., expr)` is deprecated. Use `orderBy(..., 'asc')` or `orderBy(..., (ob) => ...)` instead.");
60
+ return OrderByItemNode.create(expr, modifiers.toOperationNode());
52
61
  }
53
- if (expr === 'asc' || expr === 'desc') {
54
- return RawNode.createWithSql(expr);
62
+ const node = OrderByItemNode.create(expr);
63
+ if (!modifiers) {
64
+ return node;
55
65
  }
56
- return expr.toOperationNode();
66
+ return modifiers(new OrderByItemBuilder({ node })).toOperationNode();
57
67
  }
@@ -0,0 +1,4 @@
1
+ import { RawNode } from '../operation-node/raw-node.js';
2
+ export type RollbackToSavepoint<S extends string[], SN extends S[number]> = S extends [...infer L, infer R] ? R extends SN ? S : RollbackToSavepoint<L extends string[] ? L : never, SN> : never;
3
+ export type ReleaseSavepoint<S extends string[], SN extends S[number]> = S extends [...infer L, infer R] ? R extends SN ? L : ReleaseSavepoint<L extends string[] ? L : never, SN> : never;
4
+ export declare function parseSavepointCommand(command: string, savepointName: string): RawNode;
@@ -0,0 +1,9 @@
1
+ /// <reference types="./savepoint-parser.d.ts" />
2
+ import { IdentifierNode } from '../operation-node/identifier-node.js';
3
+ import { RawNode } from '../operation-node/raw-node.js';
4
+ export function parseSavepointCommand(command, savepointName) {
5
+ return RawNode.createWithChildren([
6
+ RawNode.createWithSql(`${command} `),
7
+ IdentifierNode.create(savepointName), // ensures savepointName gets sanitized
8
+ ]);
9
+ }
@@ -0,0 +1,4 @@
1
+ import type { SelectQueryBuilder } from '../query-builder/select-query-builder.js';
2
+ import type { ShallowRecord } from '../util/type-utils.js';
3
+ import type { ExtractTableAlias, From, FromTables, TableExpressionOrList } from './table-parser.js';
4
+ export type SelectFrom<DB, TB extends keyof DB, TE extends TableExpressionOrList<DB, TB>> = TE extends keyof DB & string ? SelectQueryBuilder<DB, TB | ExtractTableAlias<DB, TE>, {}> : TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? SelectQueryBuilder<DB & ShallowRecord<A, DB[T]>, TB | A, {}> : never : TE extends ReadonlyArray<infer T> ? SelectQueryBuilder<From<DB, T>, FromTables<DB, TB, T>, {}> : SelectQueryBuilder<From<DB, TE>, FromTables<DB, TB, TE>, {}>;
@@ -0,0 +1,2 @@
1
+ /// <reference types="./select-from-parser.d.ts" />
2
+ export {};
@@ -3,22 +3,19 @@ import { TableNode } from '../operation-node/table-node.js';
3
3
  import { AliasedExpressionOrFactory } from './expression-parser.js';
4
4
  import { OperationNode } from '../operation-node/operation-node.js';
5
5
  import { AliasedExpression } from '../expression/expression.js';
6
- import { DrainOuterGeneric, ShallowRecord } from '../util/type-utils.js';
6
+ import { DrainOuterGeneric } from '../util/type-utils.js';
7
7
  export type TableExpression<DB, TB extends keyof DB> = AnyAliasedTable<DB> | AnyTable<DB> | AliasedExpressionOrFactory<DB, TB>;
8
8
  export type TableExpressionOrList<DB, TB extends keyof DB> = TableExpression<DB, TB> | ReadonlyArray<TableExpression<DB, TB>>;
9
- export type TableReference<DB> = SimpleTableReference<DB> | AliasedExpression<any, any>;
10
9
  export type SimpleTableReference<DB> = AnyAliasedTable<DB> | AnyTable<DB>;
11
10
  export type AnyAliasedTable<DB> = `${AnyTable<DB>} as ${string}`;
12
- export type TableReferenceOrList<DB> = TableReference<DB> | ReadonlyArray<TableReference<DB>>;
11
+ export type AnyTable<DB> = keyof DB & string;
13
12
  export type From<DB, TE> = DrainOuterGeneric<{
14
13
  [C in keyof DB | ExtractAliasFromTableExpression<DB, TE>]: C extends ExtractAliasFromTableExpression<DB, TE> ? ExtractRowTypeFromTableExpression<DB, TE, C> : C extends keyof DB ? DB[C] : never;
15
14
  }>;
16
15
  export type FromTables<DB, TB extends keyof DB, TE> = DrainOuterGeneric<TB | ExtractAliasFromTableExpression<DB, TE>>;
17
16
  export type ExtractTableAlias<DB, TE> = TE extends `${string} as ${infer TA}` ? TA extends keyof DB ? TA : never : TE extends keyof DB ? TE : never;
18
- export type PickTableWithAlias<DB, T extends AnyAliasedTable<DB>> = T extends `${infer TB} as ${infer A}` ? TB extends keyof DB ? ShallowRecord<A, DB[TB]> : never : never;
19
17
  type ExtractAliasFromTableExpression<DB, TE> = TE extends string ? TE extends `${string} as ${infer TA}` ? TA : TE extends keyof DB ? TE : never : TE extends AliasedExpression<any, infer QA> ? QA : TE extends (qb: any) => AliasedExpression<any, infer QA> ? QA : never;
20
18
  type ExtractRowTypeFromTableExpression<DB, TE, A extends keyof any> = TE extends `${infer T} as ${infer TA}` ? TA extends A ? T extends keyof DB ? DB[T] : never : never : TE extends A ? TE extends keyof DB ? DB[TE] : never : TE extends AliasedExpression<infer O, infer QA> ? QA extends A ? O : never : TE extends (qb: any) => AliasedExpression<infer O, infer QA> ? QA extends A ? O : never : never;
21
- type AnyTable<DB> = keyof DB & string;
22
19
  export declare function parseTableExpressionOrList(table: TableExpressionOrList<any, any>): OperationNode[];
23
20
  export declare function parseTableExpression(table: TableExpression<any, any>): OperationNode;
24
21
  export declare function parseAliasedTable(from: string): TableNode | AliasNode;
@@ -0,0 +1,5 @@
1
+ import type { UpdateQueryBuilder } from '../query-builder/update-query-builder.js';
2
+ import type { UpdateResult } from '../query-builder/update-result.js';
3
+ import type { ShallowRecord } from '../util/type-utils.js';
4
+ import type { ExtractTableAlias, From, FromTables, TableExpressionOrList } from './table-parser.js';
5
+ export type UpdateTable<DB, TE extends TableExpressionOrList<DB, never>> = TE extends ReadonlyArray<infer T> ? UpdateQueryBuilder<From<DB, T>, FromTables<DB, never, T>, FromTables<DB, never, T>, UpdateResult> : TE extends keyof DB & string ? UpdateQueryBuilder<DB, ExtractTableAlias<DB, TE>, ExtractTableAlias<DB, TE>, UpdateResult> : TE extends `${infer T} as ${infer A}` ? T extends keyof DB ? UpdateQueryBuilder<DB & ShallowRecord<A, DB[T]>, A, A, UpdateResult> : never : UpdateQueryBuilder<From<DB, TE>, FromTables<DB, never, TE>, FromTables<DB, never, TE>, UpdateResult>;
@@ -0,0 +1,2 @@
1
+ /// <reference types="./update-parser.d.ts" />
2
+ export {};
@@ -1,11 +1,14 @@
1
1
  import { ColumnUpdateNode } from '../operation-node/column-update-node.js';
2
2
  import { ExpressionBuilder } from '../expression/expression-builder.js';
3
- import { UpdateKeys, UpdateType } from '../util/column-type.js';
3
+ import { UpdateType } from '../util/column-type.js';
4
4
  import { ValueExpression } from './value-parser.js';
5
5
  import { ExtractRawTypeFromReferenceExpression, ReferenceExpression } from './reference-parser.js';
6
- export type UpdateObject<DB, TB extends keyof DB, UT extends keyof DB = TB> = {
7
- [C in UpdateKeys<DB[UT]>]?: ValueExpression<DB, TB, UpdateType<DB[UT][C]>> | undefined;
8
- };
6
+ import { AnyColumn, DrainOuterGeneric } from '../util/type-utils.js';
7
+ export type UpdateObject<DB, TB extends keyof DB, UT extends keyof DB = TB> = DrainOuterGeneric<{
8
+ [C in AnyColumn<DB, UT>]?: {
9
+ [T in UT]: C extends keyof DB[T] ? ValueExpression<DB, TB, UpdateType<DB[T][C]>> | undefined : never;
10
+ }[UT];
11
+ }>;
9
12
  export type UpdateObjectFactory<DB, TB extends keyof DB, UT extends keyof DB> = (eb: ExpressionBuilder<DB, TB>) => UpdateObject<DB, TB, UT>;
10
13
  export type UpdateObjectExpression<DB, TB extends keyof DB, UT extends keyof DB = TB> = UpdateObject<DB, TB, UT> | UpdateObjectFactory<DB, TB, UT>;
11
14
  export type ExtractUpdateTypeFromReferenceExpression<DB, TB extends keyof DB, RE, DV = unknown> = UpdateType<ExtractRawTypeFromReferenceExpression<DB, TB, RE, DV>>;
@@ -83,7 +83,7 @@ export class CamelCasePlugin {
83
83
  this.#snakeCaseTransformer = new SnakeCaseTransformer(this.snakeCase.bind(this));
84
84
  }
85
85
  transformQuery(args) {
86
- return this.#snakeCaseTransformer.transformNode(args.node);
86
+ return this.#snakeCaseTransformer.transformNode(args.node, args.queryId);
87
87
  }
88
88
  async transformResult(args) {
89
89
  if (args.result.rows && Array.isArray(args.result.rows)) {
@@ -1,8 +1,9 @@
1
1
  import { IdentifierNode } from '../../operation-node/identifier-node.js';
2
2
  import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js';
3
+ import { QueryId } from '../../util/query-id.js';
3
4
  import { StringMapper } from './camel-case.js';
4
5
  export declare class SnakeCaseTransformer extends OperationNodeTransformer {
5
6
  #private;
6
7
  constructor(snakeCase: StringMapper);
7
- protected transformIdentifier(node: IdentifierNode): IdentifierNode;
8
+ protected transformIdentifier(node: IdentifierNode, queryId: QueryId): IdentifierNode;
8
9
  }
@@ -6,8 +6,8 @@ export class SnakeCaseTransformer extends OperationNodeTransformer {
6
6
  super();
7
7
  this.#snakeCase = snakeCase;
8
8
  }
9
- transformIdentifier(node) {
10
- node = super.transformIdentifier(node);
9
+ transformIdentifier(node, queryId) {
10
+ node = super.transformIdentifier(node, queryId);
11
11
  return {
12
12
  ...node,
13
13
  name: this.#snakeCase(node.name),
@@ -20,7 +20,10 @@ export function createSnakeCaseMapper({ upperCase = false, underscoreBeforeDigit
20
20
  // If underScoreBeforeDigits is true then, well, insert an underscore
21
21
  // before digits :). Only the first digit gets an underscore if
22
22
  // there are multiple.
23
- if (underscoreBeforeDigits && isDigit(char) && !isDigit(prevChar)) {
23
+ if (underscoreBeforeDigits &&
24
+ isDigit(char) &&
25
+ !isDigit(prevChar) &&
26
+ !out.endsWith('_')) {
24
27
  out += '_' + char;
25
28
  continue;
26
29
  }
@@ -8,7 +8,7 @@ import { DeduplicateJoinsTransformer } from './deduplicate-joins-transformer.js'
8
8
  export class DeduplicateJoinsPlugin {
9
9
  #transformer = new DeduplicateJoinsTransformer();
10
10
  transformQuery(args) {
11
- return this.#transformer.transformNode(args.node);
11
+ return this.#transformer.transformNode(args.node, args.queryId);
12
12
  }
13
13
  transformResult(args) {
14
14
  return Promise.resolve(args.result);
@@ -2,9 +2,10 @@ import { DeleteQueryNode } from '../../operation-node/delete-query-node.js';
2
2
  import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js';
3
3
  import { SelectQueryNode } from '../../operation-node/select-query-node.js';
4
4
  import { UpdateQueryNode } from '../../operation-node/update-query-node.js';
5
+ import { QueryId } from '../../util/query-id.js';
5
6
  export declare class DeduplicateJoinsTransformer extends OperationNodeTransformer {
6
7
  #private;
7
- protected transformSelectQuery(node: SelectQueryNode): SelectQueryNode;
8
- protected transformUpdateQuery(node: UpdateQueryNode): UpdateQueryNode;
9
- protected transformDeleteQuery(node: DeleteQueryNode): DeleteQueryNode;
8
+ protected transformSelectQuery(node: SelectQueryNode, queryId: QueryId): SelectQueryNode;
9
+ protected transformUpdateQuery(node: UpdateQueryNode, queryId: QueryId): UpdateQueryNode;
10
+ protected transformDeleteQuery(node: DeleteQueryNode, queryId: QueryId): DeleteQueryNode;
10
11
  }
@@ -2,14 +2,14 @@
2
2
  import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js';
3
3
  import { compare, freeze } from '../../util/object-utils.js';
4
4
  export class DeduplicateJoinsTransformer extends OperationNodeTransformer {
5
- transformSelectQuery(node) {
6
- return this.#transformQuery(super.transformSelectQuery(node));
5
+ transformSelectQuery(node, queryId) {
6
+ return this.#transformQuery(super.transformSelectQuery(node, queryId));
7
7
  }
8
- transformUpdateQuery(node) {
9
- return this.#transformQuery(super.transformUpdateQuery(node));
8
+ transformUpdateQuery(node, queryId) {
9
+ return this.#transformQuery(super.transformUpdateQuery(node, queryId));
10
10
  }
11
- transformDeleteQuery(node) {
12
- return this.#transformQuery(super.transformDeleteQuery(node));
11
+ transformDeleteQuery(node, queryId) {
12
+ return this.#transformQuery(super.transformDeleteQuery(node, queryId));
13
13
  }
14
14
  #transformQuery(node) {
15
15
  if (!node.joins || node.joins.length === 0) {
@@ -0,0 +1,211 @@
1
+ import { QueryResult } from '../../driver/database-connection.js';
2
+ import { RootOperationNode } from '../../query-compiler/query-compiler.js';
3
+ import { KyselyPlugin, PluginTransformQueryArgs, PluginTransformResultArgs } from '../kysely-plugin.js';
4
+ import { UnknownRow } from '../../util/type-utils.js';
5
+ import { HandleEmptyInListsOptions } from './handle-empty-in-lists.js';
6
+ /**
7
+ * A plugin that allows handling `in ()` and `not in ()` expressions.
8
+ *
9
+ * These expressions are invalid SQL syntax for many databases, and result in runtime
10
+ * database errors.
11
+ *
12
+ * The workarounds used by other libraries always involve modifying the query under
13
+ * the hood, which is not aligned with Kysely's philosophy of WYSIWYG. We recommend manually checking
14
+ * for empty arrays before passing them as arguments to `in` and `not in` expressions
15
+ * instead, but understand that this can be cumbersome. Hence we're going with an
16
+ * opt-in approach where you can choose if and how to handle these cases. We do
17
+ * not want to make this the default behavior, as it can lead to unexpected behavior.
18
+ * Use it at your own risk. Test it. Make sure it works as expected for you.
19
+ *
20
+ * Using this plugin also allows you to throw an error (thus avoiding unnecessary
21
+ * requests to the database) or print a warning in these cases.
22
+ *
23
+ * ### Examples
24
+ *
25
+ * The following strategy replaces the `in`/`not in` expression with a noncontingent
26
+ * expression. A contradiction (falsy) `1 = 0` for `in`, and a tautology (truthy) `1 = 1` for `not in`),
27
+ * similarily to how {@link https://github.com/knex/knex/blob/176151d8048b2a7feeb89a3d649a5580786d4f4e/docs/src/guide/query-builder.md#L1763 | Knex.js},
28
+ * {@link https://github.com/prisma/prisma-engines/blob/99168c54187178484dae45d9478aa40cfd1866d2/quaint/src/visitor.rs#L804-L823 | PrismaORM},
29
+ * {@link https://github.com/laravel/framework/blob/8.x/src/Illuminate/Database/Query/Grammars/Grammar.php#L284-L291 | Laravel},
30
+ * {@link https://docs.sqlalchemy.org/en/13/core/engines.html#sqlalchemy.create_engine.params.empty_in_strategy | SQLAlchemy}
31
+ * handle this.
32
+ *
33
+ * ```ts
34
+ * import Sqlite from 'better-sqlite3'
35
+ * import {
36
+ * HandleEmptyInListsPlugin,
37
+ * Kysely,
38
+ * replaceWithNoncontingentExpression,
39
+ * SqliteDialect,
40
+ * } from 'kysely'
41
+ * import type { Database } from 'type-editor' // imaginary module
42
+ *
43
+ * const db = new Kysely<Database>({
44
+ * dialect: new SqliteDialect({
45
+ * database: new Sqlite(':memory:'),
46
+ * }),
47
+ * plugins: [
48
+ * new HandleEmptyInListsPlugin({
49
+ * strategy: replaceWithNoncontingentExpression
50
+ * })
51
+ * ],
52
+ * })
53
+ *
54
+ * const results = await db
55
+ * .selectFrom('person')
56
+ * .where('id', 'in', [])
57
+ * .where('first_name', 'not in', [])
58
+ * .selectAll()
59
+ * .execute()
60
+ * ```
61
+ *
62
+ * The generated SQL (SQLite):
63
+ *
64
+ * ```sql
65
+ * select * from "person" where 1 = 0 and 1 = 1
66
+ * ```
67
+ *
68
+ * The following strategy does the following:
69
+ *
70
+ * When `in`, pushes a `null` value into the empty list resulting in `in (null)`,
71
+ * similiarly to how {@link https://github.com/typeorm/typeorm/blob/0280cdc451c35ef73c830eb1191c95d34f6ce06e/src/query-builder/QueryBuilder.ts#L919-L922 | TypeORM}
72
+ * and {@link https://github.com/sequelize/sequelize/blob/0f2891c6897e12bf9bf56df344aae5b698f58c7d/packages/core/src/abstract-dialect/where-sql-builder.ts#L368-L379 | Sequelize}
73
+ * handle `in ()`. `in (null)` is logically the equivalent of `= null`, which returns
74
+ * `null`, which is a falsy expression in most SQL databases. We recommend NOT
75
+ * using this strategy if you plan to use `in` in `select`, `returning`, or `output`
76
+ * clauses, as the return type differs from the `SqlBool` default type for comparisons.
77
+ *
78
+ * When `not in`, casts the left operand as `char` and pushes a unique value into
79
+ * the empty list resulting in `cast({{lhs}} as char) not in ({{VALUE}})`. Casting
80
+ * is required to avoid database errors with non-string values.
81
+ *
82
+ * ```ts
83
+ * import Sqlite from 'better-sqlite3'
84
+ * import {
85
+ * HandleEmptyInListsPlugin,
86
+ * Kysely,
87
+ * pushValueIntoList,
88
+ * SqliteDialect
89
+ * } from 'kysely'
90
+ * import type { Database } from 'type-editor' // imaginary module
91
+ *
92
+ * const db = new Kysely<Database>({
93
+ * dialect: new SqliteDialect({
94
+ * database: new Sqlite(':memory:'),
95
+ * }),
96
+ * plugins: [
97
+ * new HandleEmptyInListsPlugin({
98
+ * strategy: pushValueIntoList('__kysely_no_values_were_provided__') // choose a unique value for not in. has to be something with zero chance being in the data.
99
+ * })
100
+ * ],
101
+ * })
102
+ *
103
+ * const results = await db
104
+ * .selectFrom('person')
105
+ * .where('id', 'in', [])
106
+ * .where('first_name', 'not in', [])
107
+ * .selectAll()
108
+ * .execute()
109
+ * ```
110
+ *
111
+ * The generated SQL (SQLite):
112
+ *
113
+ * ```sql
114
+ * select * from "person" where "id" in (null) and cast("first_name" as char) not in ('__kysely_no_values_were_provided__')
115
+ * ```
116
+ *
117
+ * The following custom strategy throws an error when an empty list is encountered
118
+ * to avoid unnecessary requests to the database:
119
+ *
120
+ * ```ts
121
+ * import Sqlite from 'better-sqlite3'
122
+ * import {
123
+ * HandleEmptyInListsPlugin,
124
+ * Kysely,
125
+ * SqliteDialect
126
+ * } from 'kysely'
127
+ * import type { Database } from 'type-editor' // imaginary module
128
+ *
129
+ * const db = new Kysely<Database>({
130
+ * dialect: new SqliteDialect({
131
+ * database: new Sqlite(':memory:'),
132
+ * }),
133
+ * plugins: [
134
+ * new HandleEmptyInListsPlugin({
135
+ * strategy: () => {
136
+ * throw new Error('Empty in/not-in is not allowed')
137
+ * }
138
+ * })
139
+ * ],
140
+ * })
141
+ *
142
+ * const results = await db
143
+ * .selectFrom('person')
144
+ * .where('id', 'in', [])
145
+ * .selectAll()
146
+ * .execute() // throws an error with 'Empty in/not-in is not allowed' message!
147
+ * ```
148
+ */
149
+ export declare class HandleEmptyInListsPlugin implements KyselyPlugin {
150
+ #private;
151
+ readonly opt: HandleEmptyInListsOptions;
152
+ constructor(opt: HandleEmptyInListsOptions);
153
+ /**
154
+ * This is called for each query before it is executed. You can modify the query by
155
+ * transforming its {@link OperationNode} tree provided in {@link PluginTransformQueryArgs.node | args.node}
156
+ * and returning the transformed tree. You'd usually want to use an {@link OperationNodeTransformer}
157
+ * for this.
158
+ *
159
+ * If you need to pass some query-related data between this method and `transformResult` you
160
+ * can use a `WeakMap` with {@link PluginTransformQueryArgs.queryId | args.queryId} as the key:
161
+ *
162
+ * ```ts
163
+ * import type {
164
+ * KyselyPlugin,
165
+ * QueryResult,
166
+ * RootOperationNode,
167
+ * UnknownRow
168
+ * } from 'kysely'
169
+ *
170
+ * interface MyData {
171
+ * // ...
172
+ * }
173
+ * const data = new WeakMap<any, MyData>()
174
+ *
175
+ * const plugin = {
176
+ * transformQuery(args: PluginTransformQueryArgs): RootOperationNode {
177
+ * const something: MyData = {}
178
+ *
179
+ * // ...
180
+ *
181
+ * data.set(args.queryId, something)
182
+ *
183
+ * // ...
184
+ *
185
+ * return args.node
186
+ * },
187
+ *
188
+ * async transformResult(args: PluginTransformResultArgs): Promise<QueryResult<UnknownRow>> {
189
+ * // ...
190
+ *
191
+ * const something = data.get(args.queryId)
192
+ *
193
+ * // ...
194
+ *
195
+ * return args.result
196
+ * }
197
+ * } satisfies KyselyPlugin
198
+ * ```
199
+ *
200
+ * You should use a `WeakMap` instead of a `Map` or some other strong references because `transformQuery`
201
+ * is not always matched by a call to `transformResult` which would leave orphaned items in the map
202
+ * and cause a memory leak.
203
+ */
204
+ transformQuery(args: PluginTransformQueryArgs): RootOperationNode;
205
+ /**
206
+ * This method is called for each query after it has been executed. The result
207
+ * of the query can be accessed through {@link PluginTransformResultArgs.result | args.result}.
208
+ * You can modify the result and return the modifier result.
209
+ */
210
+ transformResult(args: PluginTransformResultArgs): Promise<QueryResult<UnknownRow>>;
211
+ }
@@ -0,0 +1,159 @@
1
+ /// <reference types="./handle-empty-in-lists-plugin.d.ts" />
2
+ import { HandleEmptyInListsTransformer } from './handle-empty-in-lists-transformer.js';
3
+ /**
4
+ * A plugin that allows handling `in ()` and `not in ()` expressions.
5
+ *
6
+ * These expressions are invalid SQL syntax for many databases, and result in runtime
7
+ * database errors.
8
+ *
9
+ * The workarounds used by other libraries always involve modifying the query under
10
+ * the hood, which is not aligned with Kysely's philosophy of WYSIWYG. We recommend manually checking
11
+ * for empty arrays before passing them as arguments to `in` and `not in` expressions
12
+ * instead, but understand that this can be cumbersome. Hence we're going with an
13
+ * opt-in approach where you can choose if and how to handle these cases. We do
14
+ * not want to make this the default behavior, as it can lead to unexpected behavior.
15
+ * Use it at your own risk. Test it. Make sure it works as expected for you.
16
+ *
17
+ * Using this plugin also allows you to throw an error (thus avoiding unnecessary
18
+ * requests to the database) or print a warning in these cases.
19
+ *
20
+ * ### Examples
21
+ *
22
+ * The following strategy replaces the `in`/`not in` expression with a noncontingent
23
+ * expression. A contradiction (falsy) `1 = 0` for `in`, and a tautology (truthy) `1 = 1` for `not in`),
24
+ * similarily to how {@link https://github.com/knex/knex/blob/176151d8048b2a7feeb89a3d649a5580786d4f4e/docs/src/guide/query-builder.md#L1763 | Knex.js},
25
+ * {@link https://github.com/prisma/prisma-engines/blob/99168c54187178484dae45d9478aa40cfd1866d2/quaint/src/visitor.rs#L804-L823 | PrismaORM},
26
+ * {@link https://github.com/laravel/framework/blob/8.x/src/Illuminate/Database/Query/Grammars/Grammar.php#L284-L291 | Laravel},
27
+ * {@link https://docs.sqlalchemy.org/en/13/core/engines.html#sqlalchemy.create_engine.params.empty_in_strategy | SQLAlchemy}
28
+ * handle this.
29
+ *
30
+ * ```ts
31
+ * import Sqlite from 'better-sqlite3'
32
+ * import {
33
+ * HandleEmptyInListsPlugin,
34
+ * Kysely,
35
+ * replaceWithNoncontingentExpression,
36
+ * SqliteDialect,
37
+ * } from 'kysely'
38
+ * import type { Database } from 'type-editor' // imaginary module
39
+ *
40
+ * const db = new Kysely<Database>({
41
+ * dialect: new SqliteDialect({
42
+ * database: new Sqlite(':memory:'),
43
+ * }),
44
+ * plugins: [
45
+ * new HandleEmptyInListsPlugin({
46
+ * strategy: replaceWithNoncontingentExpression
47
+ * })
48
+ * ],
49
+ * })
50
+ *
51
+ * const results = await db
52
+ * .selectFrom('person')
53
+ * .where('id', 'in', [])
54
+ * .where('first_name', 'not in', [])
55
+ * .selectAll()
56
+ * .execute()
57
+ * ```
58
+ *
59
+ * The generated SQL (SQLite):
60
+ *
61
+ * ```sql
62
+ * select * from "person" where 1 = 0 and 1 = 1
63
+ * ```
64
+ *
65
+ * The following strategy does the following:
66
+ *
67
+ * When `in`, pushes a `null` value into the empty list resulting in `in (null)`,
68
+ * similiarly to how {@link https://github.com/typeorm/typeorm/blob/0280cdc451c35ef73c830eb1191c95d34f6ce06e/src/query-builder/QueryBuilder.ts#L919-L922 | TypeORM}
69
+ * and {@link https://github.com/sequelize/sequelize/blob/0f2891c6897e12bf9bf56df344aae5b698f58c7d/packages/core/src/abstract-dialect/where-sql-builder.ts#L368-L379 | Sequelize}
70
+ * handle `in ()`. `in (null)` is logically the equivalent of `= null`, which returns
71
+ * `null`, which is a falsy expression in most SQL databases. We recommend NOT
72
+ * using this strategy if you plan to use `in` in `select`, `returning`, or `output`
73
+ * clauses, as the return type differs from the `SqlBool` default type for comparisons.
74
+ *
75
+ * When `not in`, casts the left operand as `char` and pushes a unique value into
76
+ * the empty list resulting in `cast({{lhs}} as char) not in ({{VALUE}})`. Casting
77
+ * is required to avoid database errors with non-string values.
78
+ *
79
+ * ```ts
80
+ * import Sqlite from 'better-sqlite3'
81
+ * import {
82
+ * HandleEmptyInListsPlugin,
83
+ * Kysely,
84
+ * pushValueIntoList,
85
+ * SqliteDialect
86
+ * } from 'kysely'
87
+ * import type { Database } from 'type-editor' // imaginary module
88
+ *
89
+ * const db = new Kysely<Database>({
90
+ * dialect: new SqliteDialect({
91
+ * database: new Sqlite(':memory:'),
92
+ * }),
93
+ * plugins: [
94
+ * new HandleEmptyInListsPlugin({
95
+ * strategy: pushValueIntoList('__kysely_no_values_were_provided__') // choose a unique value for not in. has to be something with zero chance being in the data.
96
+ * })
97
+ * ],
98
+ * })
99
+ *
100
+ * const results = await db
101
+ * .selectFrom('person')
102
+ * .where('id', 'in', [])
103
+ * .where('first_name', 'not in', [])
104
+ * .selectAll()
105
+ * .execute()
106
+ * ```
107
+ *
108
+ * The generated SQL (SQLite):
109
+ *
110
+ * ```sql
111
+ * select * from "person" where "id" in (null) and cast("first_name" as char) not in ('__kysely_no_values_were_provided__')
112
+ * ```
113
+ *
114
+ * The following custom strategy throws an error when an empty list is encountered
115
+ * to avoid unnecessary requests to the database:
116
+ *
117
+ * ```ts
118
+ * import Sqlite from 'better-sqlite3'
119
+ * import {
120
+ * HandleEmptyInListsPlugin,
121
+ * Kysely,
122
+ * SqliteDialect
123
+ * } from 'kysely'
124
+ * import type { Database } from 'type-editor' // imaginary module
125
+ *
126
+ * const db = new Kysely<Database>({
127
+ * dialect: new SqliteDialect({
128
+ * database: new Sqlite(':memory:'),
129
+ * }),
130
+ * plugins: [
131
+ * new HandleEmptyInListsPlugin({
132
+ * strategy: () => {
133
+ * throw new Error('Empty in/not-in is not allowed')
134
+ * }
135
+ * })
136
+ * ],
137
+ * })
138
+ *
139
+ * const results = await db
140
+ * .selectFrom('person')
141
+ * .where('id', 'in', [])
142
+ * .selectAll()
143
+ * .execute() // throws an error with 'Empty in/not-in is not allowed' message!
144
+ * ```
145
+ */
146
+ export class HandleEmptyInListsPlugin {
147
+ opt;
148
+ #transformer;
149
+ constructor(opt) {
150
+ this.opt = opt;
151
+ this.#transformer = new HandleEmptyInListsTransformer(opt.strategy);
152
+ }
153
+ transformQuery(args) {
154
+ return this.#transformer.transformNode(args.node, args.queryId);
155
+ }
156
+ async transformResult(args) {
157
+ return args.result;
158
+ }
159
+ }
@@ -0,0 +1,8 @@
1
+ import { BinaryOperationNode } from '../../operation-node/binary-operation-node.js';
2
+ import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js';
3
+ import { EmptyInListsStrategy } from './handle-empty-in-lists.js';
4
+ export declare class HandleEmptyInListsTransformer extends OperationNodeTransformer {
5
+ #private;
6
+ constructor(strategy: EmptyInListsStrategy);
7
+ protected transformBinaryOperation(node: BinaryOperationNode): BinaryOperationNode;
8
+ }