bun-types 1.3.2-canary.20251105T140650 → 1.3.2-canary.20251106T140813

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 (308) hide show
  1. package/docs/README.md +28 -0
  2. package/package.json +1 -1
  3. package/docs/api/binary-data.md +0 -1038
  4. package/docs/api/cc.md +0 -197
  5. package/docs/api/color.md +0 -262
  6. package/docs/api/console.md +0 -57
  7. package/docs/api/cookie.md +0 -449
  8. package/docs/api/dns.md +0 -110
  9. package/docs/api/fetch.md +0 -463
  10. package/docs/api/ffi.md +0 -557
  11. package/docs/api/file-io.md +0 -366
  12. package/docs/api/file-system-router.md +0 -112
  13. package/docs/api/file.md +0 -19
  14. package/docs/api/glob.md +0 -178
  15. package/docs/api/globals.md +0 -387
  16. package/docs/api/hashing.md +0 -319
  17. package/docs/api/html-rewriter.md +0 -334
  18. package/docs/api/http.md +0 -1408
  19. package/docs/api/import-meta.md +0 -69
  20. package/docs/api/node-api.md +0 -14
  21. package/docs/api/redis.md +0 -597
  22. package/docs/api/s3.md +0 -850
  23. package/docs/api/secrets.md +0 -319
  24. package/docs/api/semver.md +0 -52
  25. package/docs/api/spawn.md +0 -582
  26. package/docs/api/sql.md +0 -1374
  27. package/docs/api/sqlite.md +0 -694
  28. package/docs/api/streams.md +0 -230
  29. package/docs/api/tcp.md +0 -221
  30. package/docs/api/transpiler.md +0 -276
  31. package/docs/api/udp.md +0 -123
  32. package/docs/api/utils.md +0 -891
  33. package/docs/api/websockets.md +0 -573
  34. package/docs/api/workers.md +0 -322
  35. package/docs/api/yaml.md +0 -668
  36. package/docs/benchmarks.md +0 -120
  37. package/docs/bun-flavored-toml.md +0 -42
  38. package/docs/bundler/css.md +0 -1028
  39. package/docs/bundler/css_modules.md +0 -145
  40. package/docs/bundler/executables.md +0 -626
  41. package/docs/bundler/fullstack.md +0 -418
  42. package/docs/bundler/hmr.md +0 -234
  43. package/docs/bundler/html.md +0 -349
  44. package/docs/bundler/index.md +0 -1735
  45. package/docs/bundler/intro.md +0 -75
  46. package/docs/bundler/loaders.md +0 -410
  47. package/docs/bundler/macros.md +0 -329
  48. package/docs/bundler/plugins.md +0 -449
  49. package/docs/bundler/vs-esbuild.md +0 -1127
  50. package/docs/cli/add.md +0 -173
  51. package/docs/cli/bun-completions.md +0 -3
  52. package/docs/cli/bun-create.md +0 -338
  53. package/docs/cli/bun-install.md +0 -349
  54. package/docs/cli/bun-upgrade.md +0 -39
  55. package/docs/cli/bunx.md +0 -89
  56. package/docs/cli/filter.md +0 -90
  57. package/docs/cli/info.md +0 -65
  58. package/docs/cli/init.md +0 -85
  59. package/docs/cli/install.md +0 -344
  60. package/docs/cli/link.md +0 -40
  61. package/docs/cli/outdated.md +0 -90
  62. package/docs/cli/patch-commit.md +0 -11
  63. package/docs/cli/pm.md +0 -285
  64. package/docs/cli/publish.md +0 -120
  65. package/docs/cli/remove.md +0 -7
  66. package/docs/cli/run.md +0 -261
  67. package/docs/cli/test.md +0 -397
  68. package/docs/cli/unlink.md +0 -9
  69. package/docs/cli/update.md +0 -129
  70. package/docs/cli/why.md +0 -67
  71. package/docs/contributing/upgrading-webkit.md +0 -57
  72. package/docs/ecosystem/elysia.md +0 -24
  73. package/docs/ecosystem/express.md +0 -37
  74. package/docs/ecosystem/hono.md +0 -18
  75. package/docs/ecosystem/react.md +0 -65
  76. package/docs/ecosystem/stric.md +0 -38
  77. package/docs/guides/binary/arraybuffer-to-array.md +0 -27
  78. package/docs/guides/binary/arraybuffer-to-blob.md +0 -24
  79. package/docs/guides/binary/arraybuffer-to-buffer.md +0 -25
  80. package/docs/guides/binary/arraybuffer-to-string.md +0 -15
  81. package/docs/guides/binary/arraybuffer-to-typedarray.md +0 -39
  82. package/docs/guides/binary/blob-to-arraybuffer.md +0 -14
  83. package/docs/guides/binary/blob-to-dataview.md +0 -14
  84. package/docs/guides/binary/blob-to-stream.md +0 -14
  85. package/docs/guides/binary/blob-to-string.md +0 -15
  86. package/docs/guides/binary/blob-to-typedarray.md +0 -14
  87. package/docs/guides/binary/buffer-to-arraybuffer.md +0 -14
  88. package/docs/guides/binary/buffer-to-blob.md +0 -14
  89. package/docs/guides/binary/buffer-to-readablestream.md +0 -41
  90. package/docs/guides/binary/buffer-to-string.md +0 -25
  91. package/docs/guides/binary/buffer-to-typedarray.md +0 -14
  92. package/docs/guides/binary/dataview-to-string.md +0 -15
  93. package/docs/guides/binary/typedarray-to-arraybuffer.md +0 -25
  94. package/docs/guides/binary/typedarray-to-blob.md +0 -16
  95. package/docs/guides/binary/typedarray-to-buffer.md +0 -14
  96. package/docs/guides/binary/typedarray-to-dataview.md +0 -14
  97. package/docs/guides/binary/typedarray-to-readablestream.md +0 -41
  98. package/docs/guides/binary/typedarray-to-string.md +0 -16
  99. package/docs/guides/deployment/railway.md +0 -157
  100. package/docs/guides/ecosystem/astro.md +0 -72
  101. package/docs/guides/ecosystem/discordjs.md +0 -77
  102. package/docs/guides/ecosystem/docker.md +0 -140
  103. package/docs/guides/ecosystem/drizzle.md +0 -185
  104. package/docs/guides/ecosystem/edgedb.md +0 -228
  105. package/docs/guides/ecosystem/elysia.md +0 -31
  106. package/docs/guides/ecosystem/express.md +0 -40
  107. package/docs/guides/ecosystem/hono.md +0 -39
  108. package/docs/guides/ecosystem/mongoose.md +0 -87
  109. package/docs/guides/ecosystem/neon-drizzle.md +0 -220
  110. package/docs/guides/ecosystem/neon-serverless-postgres.md +0 -55
  111. package/docs/guides/ecosystem/nextjs.md +0 -49
  112. package/docs/guides/ecosystem/nuxt.md +0 -56
  113. package/docs/guides/ecosystem/pm2.md +0 -57
  114. package/docs/guides/ecosystem/prisma.md +0 -141
  115. package/docs/guides/ecosystem/qwik.md +0 -107
  116. package/docs/guides/ecosystem/react.md +0 -50
  117. package/docs/guides/ecosystem/remix.md +0 -78
  118. package/docs/guides/ecosystem/render.md +0 -79
  119. package/docs/guides/ecosystem/sentry.md +0 -52
  120. package/docs/guides/ecosystem/solidstart.md +0 -58
  121. package/docs/guides/ecosystem/ssr-react.md +0 -51
  122. package/docs/guides/ecosystem/stric.md +0 -55
  123. package/docs/guides/ecosystem/sveltekit.md +0 -125
  124. package/docs/guides/ecosystem/systemd.md +0 -113
  125. package/docs/guides/ecosystem/vite.md +0 -71
  126. package/docs/guides/html-rewriter/extract-links.md +0 -68
  127. package/docs/guides/html-rewriter/extract-social-meta.md +0 -93
  128. package/docs/guides/http/cluster.md +0 -66
  129. package/docs/guides/http/fetch-unix.md +0 -33
  130. package/docs/guides/http/fetch.md +0 -24
  131. package/docs/guides/http/file-uploads.md +0 -94
  132. package/docs/guides/http/hot.md +0 -26
  133. package/docs/guides/http/proxy.md +0 -24
  134. package/docs/guides/http/server.md +0 -46
  135. package/docs/guides/http/simple.md +0 -18
  136. package/docs/guides/http/stream-file.md +0 -48
  137. package/docs/guides/http/stream-iterator.md +0 -47
  138. package/docs/guides/http/stream-node-streams-in-bun.md +0 -20
  139. package/docs/guides/http/tls.md +0 -30
  140. package/docs/guides/install/add-dev.md +0 -26
  141. package/docs/guides/install/add-git.md +0 -36
  142. package/docs/guides/install/add-optional.md +0 -25
  143. package/docs/guides/install/add-peer.md +0 -43
  144. package/docs/guides/install/add-tarball.md +0 -33
  145. package/docs/guides/install/add.md +0 -42
  146. package/docs/guides/install/azure-artifacts.md +0 -73
  147. package/docs/guides/install/cicd.md +0 -41
  148. package/docs/guides/install/custom-registry.md +0 -30
  149. package/docs/guides/install/from-npm-install-to-bun-install.md +0 -214
  150. package/docs/guides/install/git-diff-bun-lockfile.md +0 -44
  151. package/docs/guides/install/jfrog-artifactory.md +0 -28
  152. package/docs/guides/install/npm-alias.md +0 -23
  153. package/docs/guides/install/registry-scope.md +0 -38
  154. package/docs/guides/install/trusted.md +0 -46
  155. package/docs/guides/install/workspaces.md +0 -70
  156. package/docs/guides/install/yarnlock.md +0 -44
  157. package/docs/guides/process/argv.md +0 -58
  158. package/docs/guides/process/ctrl-c.md +0 -16
  159. package/docs/guides/process/ipc.md +0 -66
  160. package/docs/guides/process/nanoseconds.md +0 -13
  161. package/docs/guides/process/os-signals.md +0 -39
  162. package/docs/guides/process/spawn-stderr.md +0 -31
  163. package/docs/guides/process/spawn-stdout.md +0 -26
  164. package/docs/guides/process/spawn.md +0 -41
  165. package/docs/guides/process/stdin.md +0 -54
  166. package/docs/guides/read-file/arraybuffer.md +0 -28
  167. package/docs/guides/read-file/buffer.md +0 -19
  168. package/docs/guides/read-file/exists.md +0 -16
  169. package/docs/guides/read-file/json.md +0 -17
  170. package/docs/guides/read-file/mime.md +0 -20
  171. package/docs/guides/read-file/stream.md +0 -26
  172. package/docs/guides/read-file/string.md +0 -22
  173. package/docs/guides/read-file/uint8array.md +0 -21
  174. package/docs/guides/read-file/watch.md +0 -68
  175. package/docs/guides/runtime/build-time-constants.md +0 -293
  176. package/docs/guides/runtime/cicd.md +0 -43
  177. package/docs/guides/runtime/codesign-macos-executable.md +0 -56
  178. package/docs/guides/runtime/define-constant.md +0 -145
  179. package/docs/guides/runtime/delete-directory.md +0 -37
  180. package/docs/guides/runtime/delete-file.md +0 -19
  181. package/docs/guides/runtime/heap-snapshot.md +0 -26
  182. package/docs/guides/runtime/import-html.md +0 -15
  183. package/docs/guides/runtime/import-json.md +0 -44
  184. package/docs/guides/runtime/import-toml.md +0 -30
  185. package/docs/guides/runtime/import-yaml.md +0 -102
  186. package/docs/guides/runtime/read-env.md +0 -32
  187. package/docs/guides/runtime/set-env.md +0 -47
  188. package/docs/guides/runtime/shell.md +0 -40
  189. package/docs/guides/runtime/timezone.md +0 -35
  190. package/docs/guides/runtime/tsconfig-paths.md +0 -29
  191. package/docs/guides/runtime/typescript.md +0 -49
  192. package/docs/guides/runtime/vscode-debugger.md +0 -47
  193. package/docs/guides/runtime/web-debugger.md +0 -82
  194. package/docs/guides/streams/node-readable-to-arraybuffer.md +0 -11
  195. package/docs/guides/streams/node-readable-to-blob.md +0 -11
  196. package/docs/guides/streams/node-readable-to-json.md +0 -12
  197. package/docs/guides/streams/node-readable-to-string.md +0 -12
  198. package/docs/guides/streams/node-readable-to-uint8array.md +0 -11
  199. package/docs/guides/streams/to-array.md +0 -14
  200. package/docs/guides/streams/to-arraybuffer.md +0 -14
  201. package/docs/guides/streams/to-blob.md +0 -14
  202. package/docs/guides/streams/to-buffer.md +0 -15
  203. package/docs/guides/streams/to-json.md +0 -14
  204. package/docs/guides/streams/to-string.md +0 -14
  205. package/docs/guides/streams/to-typedarray.md +0 -22
  206. package/docs/guides/test/bail.md +0 -22
  207. package/docs/guides/test/coverage-threshold.md +0 -60
  208. package/docs/guides/test/coverage.md +0 -44
  209. package/docs/guides/test/happy-dom.md +0 -68
  210. package/docs/guides/test/migrate-from-jest.md +0 -143
  211. package/docs/guides/test/mock-clock.md +0 -48
  212. package/docs/guides/test/mock-functions.md +0 -68
  213. package/docs/guides/test/rerun-each.md +0 -14
  214. package/docs/guides/test/run-tests.md +0 -111
  215. package/docs/guides/test/skip-tests.md +0 -39
  216. package/docs/guides/test/snapshot.md +0 -95
  217. package/docs/guides/test/spy-on.md +0 -46
  218. package/docs/guides/test/svelte-test.md +0 -120
  219. package/docs/guides/test/testing-library.md +0 -92
  220. package/docs/guides/test/timeout.md +0 -15
  221. package/docs/guides/test/todo-tests.md +0 -67
  222. package/docs/guides/test/update-snapshots.md +0 -46
  223. package/docs/guides/test/watch-mode.md +0 -19
  224. package/docs/guides/util/base64.md +0 -15
  225. package/docs/guides/util/deep-equals.md +0 -39
  226. package/docs/guides/util/deflate.md +0 -18
  227. package/docs/guides/util/detect-bun.md +0 -23
  228. package/docs/guides/util/entrypoint.md +0 -17
  229. package/docs/guides/util/escape-html.md +0 -22
  230. package/docs/guides/util/file-url-to-path.md +0 -14
  231. package/docs/guides/util/gzip.md +0 -18
  232. package/docs/guides/util/hash-a-password.md +0 -54
  233. package/docs/guides/util/import-meta-dir.md +0 -13
  234. package/docs/guides/util/import-meta-file.md +0 -13
  235. package/docs/guides/util/import-meta-path.md +0 -13
  236. package/docs/guides/util/javascript-uuid.md +0 -23
  237. package/docs/guides/util/main.md +0 -32
  238. package/docs/guides/util/path-to-file-url.md +0 -14
  239. package/docs/guides/util/sleep.md +0 -22
  240. package/docs/guides/util/version.md +0 -21
  241. package/docs/guides/util/which-path-to-executable-bin.md +0 -15
  242. package/docs/guides/websocket/compression.md +0 -31
  243. package/docs/guides/websocket/context.md +0 -77
  244. package/docs/guides/websocket/pubsub.md +0 -41
  245. package/docs/guides/websocket/simple.md +0 -33
  246. package/docs/guides/write-file/append.md +0 -52
  247. package/docs/guides/write-file/basic.md +0 -44
  248. package/docs/guides/write-file/blob.md +0 -28
  249. package/docs/guides/write-file/cat.md +0 -17
  250. package/docs/guides/write-file/file-cp.md +0 -16
  251. package/docs/guides/write-file/filesink.md +0 -52
  252. package/docs/guides/write-file/response.md +0 -17
  253. package/docs/guides/write-file/stdout.md +0 -21
  254. package/docs/guides/write-file/stream.md +0 -17
  255. package/docs/guides/write-file/unlink.md +0 -16
  256. package/docs/index.md +0 -77
  257. package/docs/install/audit.md +0 -57
  258. package/docs/install/cache.md +0 -59
  259. package/docs/install/catalogs.md +0 -298
  260. package/docs/install/index.md +0 -248
  261. package/docs/install/isolated.md +0 -197
  262. package/docs/install/lifecycle.md +0 -46
  263. package/docs/install/lockfile.md +0 -58
  264. package/docs/install/npmrc.md +0 -105
  265. package/docs/install/overrides.md +0 -73
  266. package/docs/install/patch.md +0 -59
  267. package/docs/install/registries.md +0 -30
  268. package/docs/install/security-scanner-api.md +0 -81
  269. package/docs/install/workspaces.md +0 -114
  270. package/docs/installation.md +0 -327
  271. package/docs/project/asan.md +0 -124
  272. package/docs/project/benchmarking.md +0 -203
  273. package/docs/project/bindgen.md +0 -225
  274. package/docs/project/building-windows.md +0 -162
  275. package/docs/project/contributing.md +0 -347
  276. package/docs/project/internals/build-process-for-ci.md +0 -75
  277. package/docs/project/licensing.md +0 -73
  278. package/docs/project/roadmap.md +0 -87
  279. package/docs/quickstart.md +0 -157
  280. package/docs/runtime/autoimport.md +0 -94
  281. package/docs/runtime/bun-apis.md +0 -207
  282. package/docs/runtime/bunfig.md +0 -772
  283. package/docs/runtime/debugger.md +0 -325
  284. package/docs/runtime/env.md +0 -253
  285. package/docs/runtime/hot.md +0 -145
  286. package/docs/runtime/index.md +0 -312
  287. package/docs/runtime/jsx.md +0 -385
  288. package/docs/runtime/loaders.md +0 -130
  289. package/docs/runtime/modules.md +0 -320
  290. package/docs/runtime/nodejs-apis.md +0 -463
  291. package/docs/runtime/plugins.md +0 -561
  292. package/docs/runtime/shell.md +0 -605
  293. package/docs/runtime/typescript.md +0 -139
  294. package/docs/runtime/web-apis.md +0 -128
  295. package/docs/test/configuration.md +0 -154
  296. package/docs/test/coverage.md +0 -142
  297. package/docs/test/discovery.md +0 -85
  298. package/docs/test/dom.md +0 -75
  299. package/docs/test/examples/concurrent-test-glob.md +0 -132
  300. package/docs/test/hot.md +0 -15
  301. package/docs/test/lifecycle.md +0 -81
  302. package/docs/test/mocks.md +0 -313
  303. package/docs/test/reporters.md +0 -117
  304. package/docs/test/runtime-behavior.md +0 -95
  305. package/docs/test/snapshots.md +0 -68
  306. package/docs/test/time.md +0 -126
  307. package/docs/test/writing.md +0 -825
  308. package/docs/typescript.md +0 -53
package/docs/api/sql.md DELETED
@@ -1,1374 +0,0 @@
1
- Bun provides native bindings for working with SQL databases through a unified Promise-based API that supports PostgreSQL, MySQL, and SQLite. The interface is designed to be simple and performant, using tagged template literals for queries and offering features like connection pooling, transactions, and prepared statements.
2
-
3
- ```ts
4
- import { sql, SQL } from "bun";
5
-
6
- // PostgreSQL (default)
7
- const users = await sql`
8
- SELECT * FROM users
9
- WHERE active = ${true}
10
- LIMIT ${10}
11
- `;
12
-
13
- // With MySQL
14
- const mysql = new SQL("mysql://user:pass@localhost:3306/mydb");
15
- const mysqlResults = await mysql`
16
- SELECT * FROM users
17
- WHERE active = ${true}
18
- `;
19
-
20
- // With SQLite
21
- const sqlite = new SQL("sqlite://myapp.db");
22
- const sqliteResults = await sqlite`
23
- SELECT * FROM users
24
- WHERE active = ${1}
25
- `;
26
- ```
27
-
28
- {% features title="Features" %}
29
-
30
- {% icon size=20 name="Shield" /%} Tagged template literals to protect against SQL injection
31
-
32
- {% icon size=20 name="GitMerge" /%} Transactions
33
-
34
- {% icon size=20 name="Variable" /%} Named & positional parameters
35
-
36
- {% icon size=20 name="Network" /%} Connection pooling
37
-
38
- {% icon size=20 name="Binary" /%} `BigInt` support
39
-
40
- {% icon size=20 name="Key" /%} SASL Auth support (SCRAM-SHA-256), MD5, and Clear Text
41
-
42
- {% icon size=20 name="Timer" /%} Connection timeouts
43
-
44
- {% icon size=20 name="Database" /%} Returning rows as data objects, arrays of arrays, or `Buffer`
45
-
46
- {% icon size=20 name="Code" /%} Binary protocol support makes it faster
47
-
48
- {% icon size=20 name="Lock" /%} TLS support (and auth mode)
49
-
50
- {% icon size=20 name="Settings" /%} Automatic configuration with environment variable
51
-
52
- {% /features %}
53
-
54
- ## Database Support
55
-
56
- Bun.SQL provides a unified API for multiple database systems:
57
-
58
- ### PostgreSQL
59
-
60
- PostgreSQL is used when:
61
-
62
- - The connection string doesn't match SQLite or MySQL patterns (it's the fallback adapter)
63
- - The connection string explicitly uses `postgres://` or `postgresql://` protocols
64
- - No connection string is provided and environment variables point to PostgreSQL
65
-
66
- ```ts
67
- import { sql } from "bun";
68
- // Uses PostgreSQL if DATABASE_URL is not set or is a PostgreSQL URL
69
- await sql`SELECT ...`;
70
-
71
- import { SQL } from "bun";
72
- const pg = new SQL("postgres://user:pass@localhost:5432/mydb");
73
- await pg`SELECT ...`;
74
- ```
75
-
76
- ### MySQL
77
-
78
- MySQL support is built into Bun.SQL, providing the same tagged template literal interface with full compatibility for MySQL 5.7+ and MySQL 8.0+:
79
-
80
- ```ts
81
- import { SQL } from "bun";
82
-
83
- // MySQL connection
84
- const mysql = new SQL("mysql://user:password@localhost:3306/database");
85
- const mysql2 = new SQL("mysql2://user:password@localhost:3306/database"); // mysql2 protocol also works
86
-
87
- // Using options object
88
- const mysql3 = new SQL({
89
- adapter: "mysql",
90
- hostname: "localhost",
91
- port: 3306,
92
- database: "myapp",
93
- username: "dbuser",
94
- password: "secretpass",
95
- });
96
-
97
- // Works with parameters - automatically uses prepared statements
98
- const users = await mysql`SELECT * FROM users WHERE id = ${userId}`;
99
-
100
- // Transactions work the same as PostgreSQL
101
- await mysql.begin(async tx => {
102
- await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
103
- await tx`UPDATE accounts SET balance = balance - 100 WHERE user_id = ${userId}`;
104
- });
105
-
106
- // Bulk inserts
107
- const newUsers = [
108
- { name: "Alice", email: "alice@example.com" },
109
- { name: "Bob", email: "bob@example.com" },
110
- ];
111
- await mysql`INSERT INTO users ${mysql(newUsers)}`;
112
- ```
113
-
114
- {% details summary="MySQL Connection String Formats" %}
115
-
116
- MySQL accepts various URL formats for connection strings:
117
-
118
- ```ts
119
- // Standard mysql:// protocol
120
- new SQL("mysql://user:pass@localhost:3306/database");
121
- new SQL("mysql://user:pass@localhost/database"); // Default port 3306
122
-
123
- // mysql2:// protocol (compatibility with mysql2 npm package)
124
- new SQL("mysql2://user:pass@localhost:3306/database");
125
-
126
- // With query parameters
127
- new SQL("mysql://user:pass@localhost/db?ssl=true");
128
-
129
- // Unix socket connection
130
- new SQL("mysql://user:pass@/database?socket=/var/run/mysqld/mysqld.sock");
131
- ```
132
-
133
- {% /details %}
134
-
135
- {% details summary="MySQL-Specific Features" %}
136
-
137
- MySQL databases support:
138
-
139
- - **Prepared statements**: Automatically created for parameterized queries with statement caching
140
- - **Binary protocol**: For better performance with prepared statements and accurate type handling
141
- - **Multiple result sets**: Support for stored procedures returning multiple result sets
142
- - **Authentication plugins**: Support for mysql_native_password, caching_sha2_password (MySQL 8.0 default), and sha256_password
143
- - **SSL/TLS connections**: Configurable SSL modes similar to PostgreSQL
144
- - **Connection attributes**: Client information sent to server for monitoring
145
- - **Query pipelining**: Execute multiple prepared statements without waiting for responses
146
-
147
- {% /details %}
148
-
149
- ### SQLite
150
-
151
- SQLite support is built into Bun.SQL, providing the same tagged template literal interface:
152
-
153
- ```ts
154
- import { SQL } from "bun";
155
-
156
- // In-memory database
157
- const memory = new SQL(":memory:");
158
- const memory2 = new SQL("sqlite://:memory:");
159
-
160
- // File-based database
161
- const db = new SQL("sqlite://myapp.db");
162
-
163
- // Using options object
164
- const db2 = new SQL({
165
- adapter: "sqlite",
166
- filename: "./data/app.db",
167
- });
168
-
169
- // For simple filenames, specify adapter explicitly
170
- const db3 = new SQL("myapp.db", { adapter: "sqlite" });
171
- ```
172
-
173
- {% details summary="SQLite Connection String Formats" %}
174
-
175
- SQLite accepts various URL formats for connection strings:
176
-
177
- ```ts
178
- // Standard sqlite:// protocol
179
- new SQL("sqlite://path/to/database.db");
180
- new SQL("sqlite:path/to/database.db"); // Without slashes
181
-
182
- // file:// protocol (also recognized as SQLite)
183
- new SQL("file://path/to/database.db");
184
- new SQL("file:path/to/database.db");
185
-
186
- // Special :memory: database
187
- new SQL(":memory:");
188
- new SQL("sqlite://:memory:");
189
- new SQL("file://:memory:");
190
-
191
- // Relative and absolute paths
192
- new SQL("sqlite://./local.db"); // Relative to current directory
193
- new SQL("sqlite://../parent/db.db"); // Parent directory
194
- new SQL("sqlite:///absolute/path.db"); // Absolute path
195
-
196
- // With query parameters
197
- new SQL("sqlite://data.db?mode=ro"); // Read-only mode
198
- new SQL("sqlite://data.db?mode=rw"); // Read-write mode (no create)
199
- new SQL("sqlite://data.db?mode=rwc"); // Read-write-create mode (default)
200
- ```
201
-
202
- **Note:** Simple filenames without a protocol (like `"myapp.db"`) require explicitly specifying `{ adapter: "sqlite" }` to avoid ambiguity with PostgreSQL.
203
-
204
- {% /details %}
205
-
206
- {% details summary="SQLite-Specific Options" %}
207
-
208
- SQLite databases support additional configuration options:
209
-
210
- ```ts
211
- const db = new SQL({
212
- adapter: "sqlite",
213
- filename: "app.db",
214
-
215
- // SQLite-specific options
216
- readonly: false, // Open in read-only mode
217
- create: true, // Create database if it doesn't exist
218
- readwrite: true, // Open for reading and writing
219
-
220
- // Additional Bun:sqlite options
221
- strict: true, // Enable strict mode
222
- safeIntegers: false, // Use JavaScript numbers for integers
223
- });
224
- ```
225
-
226
- Query parameters in the URL are parsed to set these options:
227
-
228
- - `?mode=ro` → `readonly: true`
229
- - `?mode=rw` → `readonly: false, create: false`
230
- - `?mode=rwc` → `readonly: false, create: true` (default)
231
-
232
- {% /details %}
233
-
234
- ### Inserting data
235
-
236
- You can pass JavaScript values directly to the SQL template literal and escaping will be handled for you.
237
-
238
- ```ts
239
- import { sql } from "bun";
240
-
241
- // Basic insert with direct values
242
- const [user] = await sql`
243
- INSERT INTO users (name, email)
244
- VALUES (${name}, ${email})
245
- RETURNING *
246
- `;
247
-
248
- // Using object helper for cleaner syntax
249
- const userData = {
250
- name: "Alice",
251
- email: "alice@example.com",
252
- };
253
-
254
- const [newUser] = await sql`
255
- INSERT INTO users ${sql(userData)}
256
- RETURNING *
257
- `;
258
- // Expands to: INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')
259
- ```
260
-
261
- ### Bulk Insert
262
-
263
- You can also pass arrays of objects to the SQL template literal and it will be expanded to a `INSERT INTO ... VALUES ...` statement.
264
-
265
- ```ts
266
- const users = [
267
- { name: "Alice", email: "alice@example.com" },
268
- { name: "Bob", email: "bob@example.com" },
269
- { name: "Charlie", email: "charlie@example.com" },
270
- ];
271
-
272
- await sql`INSERT INTO users ${sql(users)}`;
273
- ```
274
-
275
- ### Picking columns to insert
276
-
277
- You can use `sql(object, ...string)` to pick which columns to insert. Each of the columns must be defined on the object.
278
-
279
- ```ts
280
- const user = {
281
- name: "Alice",
282
- email: "alice@example.com",
283
- age: 25,
284
- };
285
-
286
- await sql`INSERT INTO users ${sql(user, "name", "email")}`;
287
- // Only inserts name and email columns, ignoring other fields
288
- ```
289
-
290
- ## Query Results
291
-
292
- By default, Bun's SQL client returns query results as arrays of objects, where each object represents a row with column names as keys. However, there are cases where you might want the data in a different format. The client provides two additional methods for this purpose.
293
-
294
- ### `sql``.values()` format
295
-
296
- The `sql``.values()` method returns rows as arrays of values rather than objects. Each row becomes an array where the values are in the same order as the columns in your query.
297
-
298
- ```ts
299
- const rows = await sql`SELECT * FROM users`.values();
300
- console.log(rows);
301
- ```
302
-
303
- This returns something like:
304
-
305
- ```ts
306
- [
307
- ["Alice", "alice@example.com"],
308
- ["Bob", "bob@example.com"],
309
- ];
310
- ```
311
-
312
- `sql``.values()` is especially useful if duplicate column names are returned in the query results. When using objects (the default), the last column name is used as the key in the object, which means duplicate column names overwrite each other — but when using `sql``.values()`, each column is present in the array so you can access the values of duplicate columns by index.
313
-
314
- ### `sql``.raw()` format
315
-
316
- The `.raw()` method returns rows as arrays of `Buffer` objects. This can be useful for working with binary data or for performance reasons.
317
-
318
- ```ts
319
- const rows = await sql`SELECT * FROM users`.raw();
320
- console.log(rows); // [[Buffer, Buffer], [Buffer, Buffer], [Buffer, Buffer]]
321
- ```
322
-
323
- ## SQL Fragments
324
-
325
- A common need in database applications is the ability to construct queries dynamically based on runtime conditions. Bun provides safe ways to do this without risking SQL injection.
326
-
327
- ### Dynamic Table Names
328
-
329
- When you need to reference tables or schemas dynamically, use the `sql()` helper to ensure proper escaping:
330
-
331
- ```ts
332
- // Safely reference tables dynamically
333
- await sql`SELECT * FROM ${sql("users")}`;
334
-
335
- // With schema qualification
336
- await sql`SELECT * FROM ${sql("public.users")}`;
337
- ```
338
-
339
- ### Conditional Queries
340
-
341
- You can use the `sql()` helper to build queries with conditional clauses. This allows you to create flexible queries that adapt to your application's needs:
342
-
343
- ```ts
344
- // Optional WHERE clauses
345
- const filterAge = true;
346
- const minAge = 21;
347
- const ageFilter = sql`AND age > ${minAge}`;
348
- await sql`
349
- SELECT * FROM users
350
- WHERE active = ${true}
351
- ${filterAge ? ageFilter : sql``}
352
- `;
353
- ```
354
-
355
- ### Dynamic columns in updates
356
-
357
- You can use `sql(object, ...string)` to pick which columns to update. Each of the columns must be defined on the object. If the columns are not informed all keys will be used to update the row.
358
-
359
- ```ts
360
- await sql`UPDATE users SET ${sql(user, "name", "email")} WHERE id = ${user.id}`;
361
- // uses all keys from the object to update the row
362
- await sql`UPDATE users SET ${sql(user)} WHERE id = ${user.id}`;
363
- ```
364
-
365
- ### Dynamic values and `where in`
366
-
367
- Value lists can also be created dynamically, making where in queries simple too. Optionally you can pass a array of objects and inform what key to use to create the list.
368
-
369
- ```ts
370
- await sql`SELECT * FROM users WHERE id IN ${sql([1, 2, 3])}`;
371
-
372
- const users = [
373
- { id: 1, name: "Alice" },
374
- { id: 2, name: "Bob" },
375
- { id: 3, name: "Charlie" },
376
- ];
377
- await sql`SELECT * FROM users WHERE id IN ${sql(users, "id")}`;
378
- ```
379
-
380
- ### `sql.array` helper
381
-
382
- The `sql.array` helper creates PostgreSQL array literals from JavaScript arrays:
383
-
384
- ```ts
385
- // Create array literals for PostgreSQL
386
- await sql`INSERT INTO tags (items) VALUES (${sql.array(["red", "blue", "green"])})`;
387
- // Generates: INSERT INTO tags (items) VALUES (ARRAY['red', 'blue', 'green'])
388
-
389
- // Works with numeric arrays too
390
- await sql`SELECT * FROM products WHERE ids = ANY(${sql.array([1, 2, 3])})`;
391
- // Generates: SELECT * FROM products WHERE ids = ANY(ARRAY[1, 2, 3])
392
- ```
393
-
394
- **Note**: `sql.array` is PostgreSQL-only. Multi-dimensional arrays and NULL elements may not be supported yet.
395
-
396
- ## `sql``.simple()`
397
-
398
- The PostgreSQL wire protocol supports two types of queries: "simple" and "extended". Simple queries can contain multiple statements but don't support parameters, while extended queries (the default) support parameters but only allow one statement.
399
-
400
- To run multiple statements in a single query, use `sql``.simple()`:
401
-
402
- ```ts
403
- // Multiple statements in one query
404
- await sql`
405
- SELECT 1;
406
- SELECT 2;
407
- `.simple();
408
- ```
409
-
410
- Simple queries are often useful for database migrations and setup scripts.
411
-
412
- Note that simple queries cannot use parameters (`${value}`). If you need parameters, you must split your query into separate statements.
413
-
414
- ### Queries in files
415
-
416
- You can use the `sql.file` method to read a query from a file and execute it, if the file includes $1, $2, etc you can pass parameters to the query. If no parameters are used it can execute multiple commands per file.
417
-
418
- ```ts
419
- const result = await sql.file("query.sql", [1, 2, 3]);
420
- ```
421
-
422
- ### Unsafe Queries
423
-
424
- You can use the `sql.unsafe` function to execute raw SQL strings. Use this with caution, as it will not escape user input. Executing more than one command per query is allowed if no parameters are used.
425
-
426
- ```ts
427
- // Multiple commands without parameters
428
- const result = await sql.unsafe(`
429
- SELECT ${userColumns} FROM users;
430
- SELECT ${accountColumns} FROM accounts;
431
- `);
432
-
433
- // Using parameters (only one command is allowed)
434
- const result = await sql.unsafe(
435
- "SELECT " + dangerous + " FROM users WHERE id = $1",
436
- [id],
437
- );
438
- ```
439
-
440
- #### What is SQL Injection?
441
-
442
- {% image href="https://xkcd.com/327/" src="https://imgs.xkcd.com/comics/exploits_of_a_mom.png" /%}
443
-
444
- ### Execute and Cancelling Queries
445
-
446
- Bun's SQL is lazy, which means it will only start executing when awaited or executed with `.execute()`.
447
- You can cancel a query that is currently executing by calling the `cancel()` method on the query object.
448
-
449
- ```ts
450
- const query = await sql`SELECT * FROM users`.execute();
451
- setTimeout(() => query.cancel(), 100);
452
- await query;
453
- ```
454
-
455
- ## Database Environment Variables
456
-
457
- `sql` connection parameters can be configured using environment variables. The client checks these variables in a specific order of precedence and automatically detects the database type based on the connection string format.
458
-
459
- ### Automatic Database Detection
460
-
461
- When using `Bun.sql()` without arguments or `new SQL()` with a connection string, the adapter is automatically detected based on the URL format:
462
-
463
- #### MySQL Auto-Detection
464
-
465
- MySQL is automatically selected when the connection string matches these patterns:
466
-
467
- - `mysql://...` - MySQL protocol URLs
468
- - `mysql2://...` - MySQL2 protocol URLs (compatibility alias)
469
-
470
- ```ts
471
- // These all use MySQL automatically (no adapter needed)
472
- const sql1 = new SQL("mysql://user:pass@localhost/mydb");
473
- const sql2 = new SQL("mysql2://user:pass@localhost:3306/mydb");
474
-
475
- // Works with DATABASE_URL environment variable
476
- DATABASE_URL="mysql://user:pass@localhost/mydb" bun run app.js
477
- DATABASE_URL="mysql2://user:pass@localhost:3306/mydb" bun run app.js
478
- ```
479
-
480
- #### SQLite Auto-Detection
481
-
482
- SQLite is automatically selected when the connection string matches these patterns:
483
-
484
- - `:memory:` - In-memory database
485
- - `sqlite://...` - SQLite protocol URLs
486
- - `sqlite:...` - SQLite protocol without slashes
487
- - `file://...` - File protocol URLs
488
- - `file:...` - File protocol without slashes
489
-
490
- ```ts
491
- // These all use SQLite automatically (no adapter needed)
492
- const sql1 = new SQL(":memory:");
493
- const sql2 = new SQL("sqlite://app.db");
494
- const sql3 = new SQL("file://./database.db");
495
-
496
- // Works with DATABASE_URL environment variable
497
- DATABASE_URL=":memory:" bun run app.js
498
- DATABASE_URL="sqlite://myapp.db" bun run app.js
499
- DATABASE_URL="file://./data/app.db" bun run app.js
500
- ```
501
-
502
- #### PostgreSQL Auto-Detection
503
-
504
- PostgreSQL is the default for connection strings that don't match MySQL or SQLite patterns:
505
-
506
- ```bash
507
- # PostgreSQL is detected for these patterns
508
- DATABASE_URL="postgres://user:pass@localhost:5432/mydb" bun run app.js
509
- DATABASE_URL="postgresql://user:pass@localhost:5432/mydb" bun run app.js
510
-
511
- # Or any URL that doesn't match MySQL or SQLite patterns
512
- DATABASE_URL="localhost:5432/mydb" bun run app.js
513
- ```
514
-
515
- ### MySQL Environment Variables
516
-
517
- MySQL connections can be configured via environment variables:
518
-
519
- ```bash
520
- # Primary connection URL (checked first)
521
- MYSQL_URL="mysql://user:pass@localhost:3306/mydb"
522
-
523
- # Alternative: DATABASE_URL with MySQL protocol
524
- DATABASE_URL="mysql://user:pass@localhost:3306/mydb"
525
- DATABASE_URL="mysql2://user:pass@localhost:3306/mydb"
526
- ```
527
-
528
- If no connection URL is provided, MySQL checks these individual parameters:
529
-
530
- | Environment Variable | Default Value | Description |
531
- | ------------------------ | ------------- | -------------------------------- |
532
- | `MYSQL_HOST` | `localhost` | Database host |
533
- | `MYSQL_PORT` | `3306` | Database port |
534
- | `MYSQL_USER` | `root` | Database user |
535
- | `MYSQL_PASSWORD` | (empty) | Database password |
536
- | `MYSQL_DATABASE` | `mysql` | Database name |
537
- | `MYSQL_URL` | (empty) | Primary connection URL for MySQL |
538
- | `TLS_MYSQL_DATABASE_URL` | (empty) | SSL/TLS-enabled connection URL |
539
-
540
- ### PostgreSQL Environment Variables
541
-
542
- The following environment variables can be used to define the PostgreSQL connection:
543
-
544
- | Environment Variable | Description |
545
- | --------------------------- | ------------------------------------------ |
546
- | `POSTGRES_URL` | Primary connection URL for PostgreSQL |
547
- | `DATABASE_URL` | Alternative connection URL (auto-detected) |
548
- | `PGURL` | Alternative connection URL |
549
- | `PG_URL` | Alternative connection URL |
550
- | `TLS_POSTGRES_DATABASE_URL` | SSL/TLS-enabled connection URL |
551
- | `TLS_DATABASE_URL` | Alternative SSL/TLS-enabled connection URL |
552
-
553
- If no connection URL is provided, the system checks for the following individual parameters:
554
-
555
- | Environment Variable | Fallback Variables | Default Value | Description |
556
- | -------------------- | ---------------------------- | ------------- | ----------------- |
557
- | `PGHOST` | - | `localhost` | Database host |
558
- | `PGPORT` | - | `5432` | Database port |
559
- | `PGUSERNAME` | `PGUSER`, `USER`, `USERNAME` | `postgres` | Database user |
560
- | `PGPASSWORD` | - | (empty) | Database password |
561
- | `PGDATABASE` | - | username | Database name |
562
-
563
- ### SQLite Environment Variables
564
-
565
- SQLite connections can be configured via `DATABASE_URL` when it contains a SQLite-compatible URL:
566
-
567
- ```bash
568
- # These are all recognized as SQLite
569
- DATABASE_URL=":memory:"
570
- DATABASE_URL="sqlite://./app.db"
571
- DATABASE_URL="file:///absolute/path/to/db.sqlite"
572
- ```
573
-
574
- **Note:** PostgreSQL-specific environment variables (`POSTGRES_URL`, `PGHOST`, etc.) are ignored when using SQLite.
575
-
576
- ## Runtime Preconnection
577
-
578
- Bun can preconnect to PostgreSQL at startup to improve performance by establishing database connections before your application code runs. This is useful for reducing connection latency on the first database query.
579
-
580
- ```bash
581
- # Enable PostgreSQL preconnection
582
- bun --sql-preconnect index.js
583
-
584
- # Works with DATABASE_URL environment variable
585
- DATABASE_URL=postgres://user:pass@localhost:5432/db bun --sql-preconnect index.js
586
-
587
- # Can be combined with other runtime flags
588
- bun --sql-preconnect --hot index.js
589
- ```
590
-
591
- The `--sql-preconnect` flag will automatically establish a PostgreSQL connection using your configured environment variables at startup. If the connection fails, it won't crash your application - the error will be handled gracefully.
592
-
593
- ## Connection Options
594
-
595
- You can configure your database connection manually by passing options to the SQL constructor. Options vary depending on the database adapter:
596
-
597
- ### MySQL Options
598
-
599
- ```ts
600
- import { SQL } from "bun";
601
-
602
- const db = new SQL({
603
- // Required for MySQL when using options object
604
- adapter: "mysql",
605
-
606
- // Connection details
607
- hostname: "localhost",
608
- port: 3306,
609
- database: "myapp",
610
- username: "dbuser",
611
- password: "secretpass",
612
-
613
- // Unix socket connection (alternative to hostname/port)
614
- // socket: "/var/run/mysqld/mysqld.sock",
615
-
616
- // Connection pool settings
617
- max: 20, // Maximum connections in pool (default: 10)
618
- idleTimeout: 30, // Close idle connections after 30s
619
- maxLifetime: 0, // Connection lifetime in seconds (0 = forever)
620
- connectionTimeout: 30, // Timeout when establishing new connections
621
-
622
- // SSL/TLS options
623
- tls: {
624
- rejectUnauthorized: true,
625
- ca: "path/to/ca.pem",
626
- key: "path/to/key.pem",
627
- cert: "path/to/cert.pem",
628
- },
629
-
630
- // Callbacks
631
- onconnect: client => {
632
- console.log("Connected to MySQL");
633
- },
634
- onclose: (client, err) => {
635
- if (err) {
636
- console.error("MySQL connection error:", err);
637
- } else {
638
- console.log("MySQL connection closed");
639
- }
640
- },
641
- });
642
- ```
643
-
644
- ### PostgreSQL Options
645
-
646
- ```ts
647
- import { SQL } from "bun";
648
-
649
- const db = new SQL({
650
- // Connection details (adapter is auto-detected as PostgreSQL)
651
- url: "postgres://user:pass@localhost:5432/dbname",
652
-
653
- // Alternative connection parameters
654
- hostname: "localhost",
655
- port: 5432,
656
- database: "myapp",
657
- username: "dbuser",
658
- password: "secretpass",
659
-
660
- // Connection pool settings
661
- max: 20, // Maximum connections in pool
662
- idleTimeout: 30, // Close idle connections after 30s
663
- maxLifetime: 0, // Connection lifetime in seconds (0 = forever)
664
- connectionTimeout: 30, // Timeout when establishing new connections
665
-
666
- // SSL/TLS options
667
- tls: true,
668
- // tls: {
669
- // rejectUnauthorized: true,
670
- // requestCert: true,
671
- // ca: "path/to/ca.pem",
672
- // key: "path/to/key.pem",
673
- // cert: "path/to/cert.pem",
674
- // checkServerIdentity(hostname, cert) {
675
- // ...
676
- // },
677
- // },
678
-
679
- // Callbacks
680
- onconnect: client => {
681
- console.log("Connected to PostgreSQL");
682
- },
683
- onclose: client => {
684
- console.log("PostgreSQL connection closed");
685
- },
686
- });
687
- ```
688
-
689
- ### SQLite Options
690
-
691
- ```ts
692
- import { SQL } from "bun";
693
-
694
- const db = new SQL({
695
- // Required for SQLite
696
- adapter: "sqlite",
697
- filename: "./data/app.db", // or ":memory:" for in-memory database
698
-
699
- // SQLite-specific access modes
700
- readonly: false, // Open in read-only mode
701
- create: true, // Create database if it doesn't exist
702
- readwrite: true, // Allow read and write operations
703
-
704
- // SQLite data handling
705
- strict: true, // Enable strict mode for better type safety
706
- safeIntegers: false, // Use BigInt for integers exceeding JS number range
707
-
708
- // Callbacks
709
- onconnect: client => {
710
- console.log("SQLite database opened");
711
- },
712
- onclose: client => {
713
- console.log("SQLite database closed");
714
- },
715
- });
716
- ```
717
-
718
- {% details summary="SQLite Connection Notes" %}
719
-
720
- - **Connection Pooling**: SQLite doesn't use connection pooling as it's a file-based database. Each `SQL` instance represents a single connection.
721
- - **Transactions**: SQLite supports nested transactions through savepoints, similar to PostgreSQL.
722
- - **Concurrent Access**: SQLite handles concurrent access through file locking. Use WAL mode for better concurrency.
723
- - **Memory Databases**: Using `:memory:` creates a temporary database that exists only for the connection lifetime.
724
-
725
- {% /details %}
726
-
727
- ## Dynamic passwords
728
-
729
- When clients need to use alternative authentication schemes such as access tokens or connections to databases with rotating passwords, provide either a synchronous or asynchronous function that will resolve the dynamic password value at connection time.
730
-
731
- ```ts
732
- import { SQL } from "bun";
733
-
734
- const sql = new SQL(url, {
735
- // Other connection config
736
- ...
737
- // Password function for the database user
738
- password: async () => await signer.getAuthToken(),
739
- });
740
- ```
741
-
742
- ## SQLite-Specific Features
743
-
744
- ### Query Execution
745
-
746
- SQLite executes queries synchronously, unlike PostgreSQL which uses asynchronous I/O. However, the API remains consistent using Promises:
747
-
748
- ```ts
749
- const sqlite = new SQL("sqlite://app.db");
750
-
751
- // Works the same as PostgreSQL, but executes synchronously under the hood
752
- const users = await sqlite`SELECT * FROM users`;
753
-
754
- // Parameters work identically
755
- const user = await sqlite`SELECT * FROM users WHERE id = ${userId}`;
756
- ```
757
-
758
- ### SQLite Pragmas
759
-
760
- You can use PRAGMA statements to configure SQLite behavior:
761
-
762
- ```ts
763
- const sqlite = new SQL("sqlite://app.db");
764
-
765
- // Enable foreign keys
766
- await sqlite`PRAGMA foreign_keys = ON`;
767
-
768
- // Set journal mode to WAL for better concurrency
769
- await sqlite`PRAGMA journal_mode = WAL`;
770
-
771
- // Check integrity
772
- const integrity = await sqlite`PRAGMA integrity_check`;
773
- ```
774
-
775
- ### Data Type Differences
776
-
777
- SQLite has a more flexible type system than PostgreSQL:
778
-
779
- ```ts
780
- // SQLite stores data in 5 storage classes: NULL, INTEGER, REAL, TEXT, BLOB
781
- const sqlite = new SQL("sqlite://app.db");
782
-
783
- // SQLite is more lenient with types
784
- await sqlite`
785
- CREATE TABLE flexible (
786
- id INTEGER PRIMARY KEY,
787
- data TEXT, -- Can store numbers as strings
788
- value NUMERIC, -- Can store integers, reals, or text
789
- blob BLOB -- Binary data
790
- )
791
- `;
792
-
793
- // JavaScript values are automatically converted
794
- await sqlite`INSERT INTO flexible VALUES (${1}, ${"text"}, ${123.45}, ${Buffer.from("binary")})`;
795
- ```
796
-
797
- ## Transactions
798
-
799
- To start a new transaction, use `sql.begin`. This method works for both PostgreSQL and SQLite. For PostgreSQL, it reserves a dedicated connection from the pool. For SQLite, it begins a transaction on the single connection.
800
-
801
- The `BEGIN` command is sent automatically, including any optional configurations you specify. If an error occurs during the transaction, a `ROLLBACK` is triggered to ensure the process continues smoothly.
802
-
803
- ### Basic Transactions
804
-
805
- ```ts
806
- await sql.begin(async tx => {
807
- // All queries in this function run in a transaction
808
- await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
809
- await tx`UPDATE accounts SET balance = balance - 100 WHERE user_id = 1`;
810
-
811
- // Transaction automatically commits if no errors are thrown
812
- // Rolls back if any error occurs
813
- });
814
- ```
815
-
816
- It's also possible to pipeline the requests in a transaction if needed by returning an array with queries from the callback function like this:
817
-
818
- ```ts
819
- await sql.begin(async tx => {
820
- return [
821
- tx`INSERT INTO users (name) VALUES (${"Alice"})`,
822
- tx`UPDATE accounts SET balance = balance - 100 WHERE user_id = 1`,
823
- ];
824
- });
825
- ```
826
-
827
- ### Savepoints
828
-
829
- Savepoints in SQL create intermediate checkpoints within a transaction, enabling partial rollbacks without affecting the entire operation. They are useful in complex transactions, allowing error recovery and maintaining consistent results.
830
-
831
- ```ts
832
- await sql.begin(async tx => {
833
- await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
834
-
835
- await tx.savepoint(async sp => {
836
- // This part can be rolled back separately
837
- await sp`UPDATE users SET status = 'active'`;
838
- if (someCondition) {
839
- throw new Error("Rollback to savepoint");
840
- }
841
- });
842
-
843
- // Continue with transaction even if savepoint rolled back
844
- await tx`INSERT INTO audit_log (action) VALUES ('user_created')`;
845
- });
846
- ```
847
-
848
- ### Distributed Transactions
849
-
850
- Two-Phase Commit (2PC) is a distributed transaction protocol where Phase 1 has the coordinator preparing nodes by ensuring data is written and ready to commit, while Phase 2 finalizes with nodes either committing or rolling back based on the coordinator's decision. This process ensures data durability and proper lock management.
851
-
852
- In PostgreSQL and MySQL, distributed transactions persist beyond their original session, allowing privileged users or coordinators to commit or rollback them later. This supports robust distributed transactions, recovery processes, and administrative operations.
853
-
854
- Each database system implements distributed transactions differently:
855
-
856
- PostgreSQL natively supports them through prepared transactions, while MySQL uses XA Transactions.
857
-
858
- If any exceptions occur during the distributed transaction and aren't caught, the system will automatically rollback all changes. When everything proceeds normally, you maintain the flexibility to either commit or rollback the transaction later.
859
-
860
- ```ts
861
- // Begin a distributed transaction
862
- await sql.beginDistributed("tx1", async tx => {
863
- await tx`INSERT INTO users (name) VALUES (${"Alice"})`;
864
- });
865
-
866
- // Later, commit or rollback
867
- await sql.commitDistributed("tx1");
868
- // or
869
- await sql.rollbackDistributed("tx1");
870
- ```
871
-
872
- ## Authentication
873
-
874
- Bun supports SCRAM-SHA-256 (SASL), MD5, and Clear Text authentication. SASL is recommended for better security. Check [Postgres SASL Authentication](https://www.postgresql.org/docs/current/sasl-authentication.html) for more information.
875
-
876
- ### SSL Modes Overview
877
-
878
- PostgreSQL supports different SSL/TLS modes to control how secure connections are established. These modes determine the behavior when connecting and the level of certificate verification performed.
879
-
880
- ```ts
881
- const sql = new SQL({
882
- hostname: "localhost",
883
- username: "user",
884
- password: "password",
885
- ssl: "disable", // | "prefer" | "require" | "verify-ca" | "verify-full"
886
- });
887
- ```
888
-
889
- | SSL Mode | Description |
890
- | ------------- | -------------------------------------------------------------------------------------------------------------------- |
891
- | `disable` | No SSL/TLS used. Connections fail if server requires SSL. |
892
- | `prefer` | Tries SSL first, falls back to non-SSL if SSL fails. Default mode if none specified. |
893
- | `require` | Requires SSL without certificate verification. Fails if SSL cannot be established. |
894
- | `verify-ca` | Verifies server certificate is signed by trusted CA. Fails if verification fails. |
895
- | `verify-full` | Most secure mode. Verifies certificate and hostname match. Protects against untrusted certificates and MITM attacks. |
896
-
897
- ### Using With Connection Strings
898
-
899
- The SSL mode can also be specified in connection strings:
900
-
901
- ```ts
902
- // Using prefer mode
903
- const sql = new SQL("postgres://user:password@localhost/mydb?sslmode=prefer");
904
-
905
- // Using verify-full mode
906
- const sql = new SQL(
907
- "postgres://user:password@localhost/mydb?sslmode=verify-full",
908
- );
909
- ```
910
-
911
- ## Connection Pooling
912
-
913
- Bun's SQL client automatically manages a connection pool, which is a pool of database connections that are reused for multiple queries. This helps to reduce the overhead of establishing and closing connections for each query, and it also helps to manage the number of concurrent connections to the database.
914
-
915
- ```ts
916
- const db = new SQL({
917
- // Pool configuration
918
- max: 20, // Maximum 20 concurrent connections
919
- idleTimeout: 30, // Close idle connections after 30s
920
- maxLifetime: 3600, // Max connection lifetime 1 hour
921
- connectionTimeout: 10, // Connection timeout 10s
922
- });
923
- ```
924
-
925
- No connection will be made until a query is made.
926
-
927
- ```ts
928
- const sql = Bun.sql(); // no connection are created
929
-
930
- await sql`...`; // pool is started until max is reached (if possible), first available connection is used
931
- await sql`...`; // previous connection is reused
932
-
933
- // two connections are used now at the same time
934
- await Promise.all([
935
- sql`INSERT INTO users ${sql({ name: "Alice" })}`,
936
- sql`UPDATE users SET name = ${user.name} WHERE id = ${user.id}`,
937
- ]);
938
-
939
- await sql.close(); // await all queries to finish and close all connections from the pool
940
- await sql.close({ timeout: 5 }); // wait 5 seconds and close all connections from the pool
941
- await sql.close({ timeout: 0 }); // close all connections from the pool immediately
942
- ```
943
-
944
- ## Reserved Connections
945
-
946
- Bun enables you to reserve a connection from the pool, and returns a client that wraps the single connection. This can be used for running queries on an isolated connection.
947
-
948
- ```ts
949
- // Get exclusive connection from pool
950
- const reserved = await sql.reserve();
951
-
952
- try {
953
- await reserved`INSERT INTO users (name) VALUES (${"Alice"})`;
954
- } finally {
955
- // Important: Release connection back to pool
956
- reserved.release();
957
- }
958
-
959
- // Or using Symbol.dispose
960
- {
961
- using reserved = await sql.reserve();
962
- await reserved`SELECT 1`;
963
- } // Automatically released
964
- ```
965
-
966
- ## Prepared Statements
967
-
968
- By default, Bun's SQL client automatically creates named prepared statements for queries where it can be inferred that the query is static. This provides better performance. However, you can change this behavior by setting `prepare: false` in the connection options:
969
-
970
- ```ts
971
- const sql = new SQL({
972
- // ... other options ...
973
- prepare: false, // Disable persisting named prepared statements on the server
974
- });
975
- ```
976
-
977
- When `prepare: false` is set:
978
-
979
- Queries are still executed using the "extended" protocol, but they are executed using [unnamed prepared statements](https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY), an unnamed prepared statement lasts only until the next Parse statement specifying the unnamed statement as destination is issued.
980
-
981
- - Parameter binding is still safe against SQL injection
982
- - Each query is parsed and planned from scratch by the server
983
- - Queries will not be [pipelined](https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-PIPELINING)
984
-
985
- You might want to use `prepare: false` when:
986
-
987
- - Using PGBouncer in transaction mode (though since PGBouncer 1.21.0, protocol-level named prepared statements are supported when configured properly)
988
- - Debugging query execution plans
989
- - Working with dynamic SQL where query plans need to be regenerated frequently
990
- - More than one command per query will not be supported (unless you use `sql``.simple()`)
991
-
992
- Note that disabling prepared statements may impact performance for queries that are executed frequently with different parameters, as the server needs to parse and plan each query from scratch.
993
-
994
- ## Error Handling
995
-
996
- The client provides typed errors for different failure scenarios. Errors are database-specific and extend from base error classes:
997
-
998
- ### Error Classes
999
-
1000
- ```ts
1001
- import { SQL } from "bun";
1002
-
1003
- try {
1004
- await sql`SELECT * FROM users`;
1005
- } catch (error) {
1006
- if (error instanceof SQL.PostgresError) {
1007
- // PostgreSQL-specific error
1008
- console.log(error.code); // PostgreSQL error code
1009
- console.log(error.detail); // Detailed error message
1010
- console.log(error.hint); // Helpful hint from PostgreSQL
1011
- } else if (error instanceof SQL.SQLiteError) {
1012
- // SQLite-specific error
1013
- console.log(error.code); // SQLite error code (e.g., "SQLITE_CONSTRAINT")
1014
- console.log(error.errno); // SQLite error number
1015
- console.log(error.byteOffset); // Byte offset in SQL statement (if available)
1016
- } else if (error instanceof SQL.SQLError) {
1017
- // Generic SQL error (base class)
1018
- console.log(error.message);
1019
- }
1020
- }
1021
- ```
1022
-
1023
- {% details summary="PostgreSQL-Specific Error Codes" %}
1024
-
1025
- ### PostgreSQL Connection Errors
1026
-
1027
- | Connection Errors | Description |
1028
- | --------------------------------- | ---------------------------------------------------- |
1029
- | `ERR_POSTGRES_CONNECTION_CLOSED` | Connection was terminated or never established |
1030
- | `ERR_POSTGRES_CONNECTION_TIMEOUT` | Failed to establish connection within timeout period |
1031
- | `ERR_POSTGRES_IDLE_TIMEOUT` | Connection closed due to inactivity |
1032
- | `ERR_POSTGRES_LIFETIME_TIMEOUT` | Connection exceeded maximum lifetime |
1033
- | `ERR_POSTGRES_TLS_NOT_AVAILABLE` | SSL/TLS connection not available |
1034
- | `ERR_POSTGRES_TLS_UPGRADE_FAILED` | Failed to upgrade connection to SSL/TLS |
1035
-
1036
- ### Authentication Errors
1037
-
1038
- | Authentication Errors | Description |
1039
- | ------------------------------------------------ | ---------------------------------------- |
1040
- | `ERR_POSTGRES_AUTHENTICATION_FAILED_PBKDF2` | Password authentication failed |
1041
- | `ERR_POSTGRES_UNKNOWN_AUTHENTICATION_METHOD` | Server requested unknown auth method |
1042
- | `ERR_POSTGRES_UNSUPPORTED_AUTHENTICATION_METHOD` | Server requested unsupported auth method |
1043
- | `ERR_POSTGRES_INVALID_SERVER_KEY` | Invalid server key during authentication |
1044
- | `ERR_POSTGRES_INVALID_SERVER_SIGNATURE` | Invalid server signature |
1045
- | `ERR_POSTGRES_SASL_SIGNATURE_INVALID_BASE64` | Invalid SASL signature encoding |
1046
- | `ERR_POSTGRES_SASL_SIGNATURE_MISMATCH` | SASL signature verification failed |
1047
-
1048
- ### Query Errors
1049
-
1050
- | Query Errors | Description |
1051
- | ------------------------------------ | ------------------------------------------ |
1052
- | `ERR_POSTGRES_SYNTAX_ERROR` | Invalid SQL syntax (extends `SyntaxError`) |
1053
- | `ERR_POSTGRES_SERVER_ERROR` | General error from PostgreSQL server |
1054
- | `ERR_POSTGRES_INVALID_QUERY_BINDING` | Invalid parameter binding |
1055
- | `ERR_POSTGRES_QUERY_CANCELLED` | Query was cancelled |
1056
- | `ERR_POSTGRES_NOT_TAGGED_CALL` | Query was called without a tagged call |
1057
-
1058
- ### Data Type Errors
1059
-
1060
- | Data Type Errors | Description |
1061
- | ------------------------------------------------------- | ------------------------------------- |
1062
- | `ERR_POSTGRES_INVALID_BINARY_DATA` | Invalid binary data format |
1063
- | `ERR_POSTGRES_INVALID_BYTE_SEQUENCE` | Invalid byte sequence |
1064
- | `ERR_POSTGRES_INVALID_BYTE_SEQUENCE_FOR_ENCODING` | Encoding error |
1065
- | `ERR_POSTGRES_INVALID_CHARACTER` | Invalid character in data |
1066
- | `ERR_POSTGRES_OVERFLOW` | Numeric overflow |
1067
- | `ERR_POSTGRES_UNSUPPORTED_BYTEA_FORMAT` | Unsupported binary format |
1068
- | `ERR_POSTGRES_UNSUPPORTED_INTEGER_SIZE` | Integer size not supported |
1069
- | `ERR_POSTGRES_MULTIDIMENSIONAL_ARRAY_NOT_SUPPORTED_YET` | Multidimensional arrays not supported |
1070
- | `ERR_POSTGRES_NULLS_IN_ARRAY_NOT_SUPPORTED_YET` | NULL values in arrays not supported |
1071
-
1072
- ### Protocol Errors
1073
-
1074
- | Protocol Errors | Description |
1075
- | --------------------------------------- | --------------------------- |
1076
- | `ERR_POSTGRES_EXPECTED_REQUEST` | Expected client request |
1077
- | `ERR_POSTGRES_EXPECTED_STATEMENT` | Expected prepared statement |
1078
- | `ERR_POSTGRES_INVALID_BACKEND_KEY_DATA` | Invalid backend key data |
1079
- | `ERR_POSTGRES_INVALID_MESSAGE` | Invalid protocol message |
1080
- | `ERR_POSTGRES_INVALID_MESSAGE_LENGTH` | Invalid message length |
1081
- | `ERR_POSTGRES_UNEXPECTED_MESSAGE` | Unexpected message type |
1082
-
1083
- ### Transaction Errors
1084
-
1085
- | Transaction Errors | Description |
1086
- | ---------------------------------------- | ------------------------------------- |
1087
- | `ERR_POSTGRES_UNSAFE_TRANSACTION` | Unsafe transaction operation detected |
1088
- | `ERR_POSTGRES_INVALID_TRANSACTION_STATE` | Invalid transaction state |
1089
-
1090
- {% /details %}
1091
-
1092
- ### SQLite-Specific Errors
1093
-
1094
- SQLite errors provide error codes and numbers that correspond to SQLite's standard error codes:
1095
-
1096
- {% details summary="Common SQLite Error Codes" %}
1097
-
1098
- | Error Code | errno | Description |
1099
- | ------------------- | ----- | ---------------------------------------------------- |
1100
- | `SQLITE_CONSTRAINT` | 19 | Constraint violation (UNIQUE, CHECK, NOT NULL, etc.) |
1101
- | `SQLITE_BUSY` | 5 | Database is locked |
1102
- | `SQLITE_LOCKED` | 6 | Table in the database is locked |
1103
- | `SQLITE_READONLY` | 8 | Attempt to write to a readonly database |
1104
- | `SQLITE_IOERR` | 10 | Disk I/O error |
1105
- | `SQLITE_CORRUPT` | 11 | Database disk image is malformed |
1106
- | `SQLITE_FULL` | 13 | Database or disk is full |
1107
- | `SQLITE_CANTOPEN` | 14 | Unable to open database file |
1108
- | `SQLITE_PROTOCOL` | 15 | Database lock protocol error |
1109
- | `SQLITE_SCHEMA` | 17 | Database schema has changed |
1110
- | `SQLITE_TOOBIG` | 18 | String or BLOB exceeds size limit |
1111
- | `SQLITE_MISMATCH` | 20 | Data type mismatch |
1112
- | `SQLITE_MISUSE` | 21 | Library used incorrectly |
1113
- | `SQLITE_AUTH` | 23 | Authorization denied |
1114
-
1115
- Example error handling:
1116
-
1117
- ```ts
1118
- const sqlite = new SQL("sqlite://app.db");
1119
-
1120
- try {
1121
- await sqlite`INSERT INTO users (id, name) VALUES (1, 'Alice')`;
1122
- await sqlite`INSERT INTO users (id, name) VALUES (1, 'Bob')`; // Duplicate ID
1123
- } catch (error) {
1124
- if (error instanceof SQL.SQLiteError) {
1125
- if (error.code === "SQLITE_CONSTRAINT") {
1126
- console.log("Constraint violation:", error.message);
1127
- // Handle unique constraint violation
1128
- }
1129
- }
1130
- }
1131
- ```
1132
-
1133
- {% /details %}
1134
-
1135
- ## Numbers and BigInt
1136
-
1137
- Bun's SQL client includes special handling for large numbers that exceed the range of a 53-bit integer. Here's how it works:
1138
-
1139
- ```ts
1140
- import { sql } from "bun";
1141
-
1142
- const [{ x, y }] = await sql`SELECT 9223372036854777 as x, 12345 as y`;
1143
-
1144
- console.log(typeof x, x); // "string" "9223372036854777"
1145
- console.log(typeof y, y); // "number" 12345
1146
- ```
1147
-
1148
- ## BigInt Instead of Strings
1149
-
1150
- If you need large numbers as BigInt instead of strings, you can enable this by setting the `bigint` option to `true` when initializing the SQL client:
1151
-
1152
- ```ts
1153
- const sql = new SQL({
1154
- bigint: true,
1155
- });
1156
-
1157
- const [{ x }] = await sql`SELECT 9223372036854777 as x`;
1158
-
1159
- console.log(typeof x, x); // "bigint" 9223372036854777n
1160
- ```
1161
-
1162
- ## Roadmap
1163
-
1164
- There's still some things we haven't finished yet.
1165
-
1166
- - Connection preloading via `--db-preconnect` Bun CLI flag
1167
- - Column name transforms (e.g. `snake_case` to `camelCase`). This is mostly blocked on a unicode-aware implementation of changing the case in C++ using WebKit's `WTF::String`.
1168
- - Column type transforms
1169
-
1170
- ## Database-Specific Features
1171
-
1172
- #### Authentication Methods
1173
-
1174
- MySQL supports multiple authentication plugins that are automatically negotiated:
1175
-
1176
- - **`mysql_native_password`** - Traditional MySQL authentication, widely compatible
1177
- - **`caching_sha2_password`** - Default in MySQL 8.0+, more secure with RSA key exchange
1178
- - **`sha256_password`** - SHA-256 based authentication
1179
-
1180
- The client automatically handles authentication plugin switching when requested by the server, including secure password exchange over non-SSL connections.
1181
-
1182
- #### Prepared Statements & Performance
1183
-
1184
- MySQL uses server-side prepared statements for all parameterized queries:
1185
-
1186
- ```ts
1187
- // This automatically creates a prepared statement on the server
1188
- const user = await mysql`SELECT * FROM users WHERE id = ${userId}`;
1189
-
1190
- // Prepared statements are cached and reused for identical queries
1191
- for (const id of userIds) {
1192
- // Same prepared statement is reused
1193
- await mysql`SELECT * FROM users WHERE id = ${id}`;
1194
- }
1195
-
1196
- // Query pipelining - multiple statements sent without waiting
1197
- const [users, orders, products] = await Promise.all([
1198
- mysql`SELECT * FROM users WHERE active = ${true}`,
1199
- mysql`SELECT * FROM orders WHERE status = ${"pending"}`,
1200
- mysql`SELECT * FROM products WHERE in_stock = ${true}`,
1201
- ]);
1202
- ```
1203
-
1204
- #### Multiple Result Sets
1205
-
1206
- MySQL can return multiple result sets from multi-statement queries:
1207
-
1208
- ```ts
1209
- const mysql = new SQL("mysql://user:pass@localhost/mydb");
1210
-
1211
- // Multi-statement queries with simple() method
1212
- const multiResults = await mysql`
1213
- SELECT * FROM users WHERE id = 1;
1214
- SELECT * FROM orders WHERE user_id = 1;
1215
- `.simple();
1216
- ```
1217
-
1218
- #### Character Sets & Collations
1219
-
1220
- Bun.SQL automatically uses `utf8mb4` character set for MySQL connections, ensuring full Unicode support including emojis. This is the recommended character set for modern MySQL applications.
1221
-
1222
- #### Connection Attributes
1223
-
1224
- Bun automatically sends client information to MySQL for better monitoring:
1225
-
1226
- ```ts
1227
- // These attributes are sent automatically:
1228
- // _client_name: "Bun"
1229
- // _client_version: <bun version>
1230
- // You can see these in MySQL's performance_schema.session_connect_attrs
1231
- ```
1232
-
1233
- #### Type Handling
1234
-
1235
- MySQL types are automatically converted to JavaScript types:
1236
-
1237
- | MySQL Type | JavaScript Type | Notes |
1238
- | --------------------------------------- | ------------------------ | ---------------------------------------------------------------------------------------------------- |
1239
- | INT, TINYINT, MEDIUMINT | number | Within safe integer range |
1240
- | BIGINT | string, number or BigInt | If the value fits in i32/u32 size will be number otherwise string or BigInt Based on `bigint` option |
1241
- | DECIMAL, NUMERIC | string | To preserve precision |
1242
- | FLOAT, DOUBLE | number | |
1243
- | DATE | Date | JavaScript Date object |
1244
- | DATETIME, TIMESTAMP | Date | With timezone handling |
1245
- | TIME | number | Total of microseconds |
1246
- | YEAR | number | |
1247
- | CHAR, VARCHAR, VARSTRING, STRING | string | |
1248
- | TINY TEXT, MEDIUM TEXT, TEXT, LONG TEXT | string | |
1249
- | TINY BLOB, MEDIUM BLOB, BLOG, LONG BLOB | string | BLOB Types are alias for TEXT types |
1250
- | JSON | object/array | Automatically parsed |
1251
- | BIT(1) | boolean | BIT(1) in MySQL |
1252
- | GEOMETRY | string | Geometry data |
1253
-
1254
- #### Differences from PostgreSQL
1255
-
1256
- While the API is unified, there are some behavioral differences:
1257
-
1258
- 1. **Parameter placeholders**: MySQL uses `?` internally but Bun converts `$1, $2` style automatically
1259
- 2. **RETURNING clause**: MySQL doesn't support RETURNING; use `result.lastInsertRowid` or a separate SELECT
1260
- 3. **Array types**: MySQL doesn't have native array types like PostgreSQL
1261
-
1262
- ### MySQL-Specific Features
1263
-
1264
- We haven't implemented `LOAD DATA INFILE` support yet
1265
-
1266
- ### PostgreSQL-Specific Features
1267
-
1268
- We haven't implemented these yet:
1269
-
1270
- - `COPY` support
1271
- - `LISTEN` support
1272
- - `NOTIFY` support
1273
-
1274
- We also haven't implemented some of the more uncommon features like:
1275
-
1276
- - GSSAPI authentication
1277
- - `SCRAM-SHA-256-PLUS` support
1278
- - Point & PostGIS types
1279
- - All the multi-dimensional integer array types (only a couple of the types are supported)
1280
-
1281
- ## Common Patterns & Best Practices
1282
-
1283
- ### Working with MySQL Result Sets
1284
-
1285
- ```ts
1286
- // Getting insert ID after INSERT
1287
- const result = await mysql`INSERT INTO users (name) VALUES (${"Alice"})`;
1288
- console.log(result.lastInsertRowid); // MySQL's LAST_INSERT_ID()
1289
-
1290
- // Handling affected rows
1291
- const updated =
1292
- await mysql`UPDATE users SET active = ${false} WHERE age < ${18}`;
1293
- console.log(updated.affectedRows); // Number of rows updated
1294
-
1295
- // Using MySQL-specific functions
1296
- const now = await mysql`SELECT NOW() as current_time`;
1297
- const uuid = await mysql`SELECT UUID() as id`;
1298
- ```
1299
-
1300
- ### MySQL Error Handling
1301
-
1302
- ```ts
1303
- try {
1304
- await mysql`INSERT INTO users (email) VALUES (${"duplicate@email.com"})`;
1305
- } catch (error) {
1306
- if (error.code === "ER_DUP_ENTRY") {
1307
- console.log("Duplicate entry detected");
1308
- } else if (error.code === "ER_ACCESS_DENIED_ERROR") {
1309
- console.log("Access denied");
1310
- } else if (error.code === "ER_BAD_DB_ERROR") {
1311
- console.log("Database does not exist");
1312
- }
1313
- // MySQL error codes are compatible with mysql/mysql2 packages
1314
- }
1315
- ```
1316
-
1317
- ### Performance Tips for MySQL
1318
-
1319
- 1. **Use connection pooling**: Set appropriate `max` pool size based on your workload
1320
- 2. **Enable prepared statements**: They're enabled by default and improve performance
1321
- 3. **Use transactions for bulk operations**: Group related queries in transactions
1322
- 4. **Index properly**: MySQL relies heavily on indexes for query performance
1323
- 5. **Use `utf8mb4` charset**: It's set by default and handles all Unicode characters
1324
-
1325
- ## Frequently Asked Questions
1326
-
1327
- > Why is this `Bun.sql` and not `Bun.postgres`?
1328
-
1329
- The plan was to add more database drivers in the future. Now with MySQL support added, this unified API supports PostgreSQL, MySQL, and SQLite.
1330
-
1331
- > How do I know which database adapter is being used?
1332
-
1333
- The adapter is automatically detected from the connection string:
1334
-
1335
- - URLs starting with `mysql://` or `mysql2://` use MySQL
1336
- - URLs matching SQLite patterns (`:memory:`, `sqlite://`, `file://`) use SQLite
1337
- - Everything else defaults to PostgreSQL
1338
-
1339
- > Are MySQL stored procedures supported?
1340
-
1341
- Yes, stored procedures are fully supported including OUT parameters and multiple result sets:
1342
-
1343
- ```ts
1344
- // Call stored procedure
1345
- const results = await mysql`CALL GetUserStats(${userId}, @total_orders)`;
1346
-
1347
- // Get OUT parameter
1348
- const outParam = await mysql`SELECT @total_orders as total`;
1349
- ```
1350
-
1351
- > Can I use MySQL-specific SQL syntax?
1352
-
1353
- Yes, you can use any MySQL-specific syntax:
1354
-
1355
- ```ts
1356
- // MySQL-specific syntax works fine
1357
- await mysql`SET @user_id = ${userId}`;
1358
- await mysql`SHOW TABLES`;
1359
- await mysql`DESCRIBE users`;
1360
- await mysql`EXPLAIN SELECT * FROM users WHERE id = ${id}`;
1361
- ```
1362
-
1363
- ## Why not just use an existing library?
1364
-
1365
- npm packages like postgres.js, pg, and node-postgres can be used in Bun too. They're great options.
1366
-
1367
- Two reasons why:
1368
-
1369
- 1. We think it's simpler for developers to have a database driver built into Bun. The time you spend library shopping is time you could be building your app.
1370
- 2. We leverage some JavaScriptCore engine internals to make it faster to create objects that would be difficult to implement in a library
1371
-
1372
- ## Credits
1373
-
1374
- Huge thanks to [@porsager](https://github.com/porsager)'s [postgres.js](https://github.com/porsager/postgres) for the inspiration for the API interface.