mirror of
https://github.com/trailbaseio/trailbase.git
synced 2026-01-06 01:40:12 -06:00
Parse and unparse conflict clauses in table and column constraints.
This commit is contained in:
349
pnpm-lock.yaml
generated
349
pnpm-lock.yaml
generated
@@ -126,7 +126,7 @@ importers:
|
||||
dependencies:
|
||||
'@astrojs/tailwind':
|
||||
specifier: ^5.1.5
|
||||
version: 5.1.5(astro@5.5.4(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.1)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0))(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)))(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2))
|
||||
version: 5.1.5(astro@5.5.4(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(rollup@4.36.0)(typescript@4.9.4)(yaml@2.7.0))(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4)))(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4))
|
||||
'@nanostores/persistent':
|
||||
specifier: ^0.10.2
|
||||
version: 0.10.2(nanostores@0.11.4)
|
||||
@@ -135,7 +135,7 @@ importers:
|
||||
version: 0.5.0(nanostores@0.11.4)(solid-js@1.9.5)
|
||||
astro:
|
||||
specifier: ^5.5.4
|
||||
version: 5.5.4(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.1)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0)
|
||||
version: 5.5.4(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(rollup@4.36.0)(typescript@4.9.4)(yaml@2.7.0)
|
||||
astro-icon:
|
||||
specifier: ^1.1.5
|
||||
version: 1.1.5
|
||||
@@ -154,7 +154,7 @@ importers:
|
||||
devDependencies:
|
||||
'@astrojs/solid-js':
|
||||
specifier: ^5.0.5
|
||||
version: 5.0.5(@testing-library/jest-dom@6.6.3)(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@22.13.11)(lightningcss@1.29.1)))(solid-js@1.9.5)(yaml@2.7.0)
|
||||
version: 5.0.5(@testing-library/jest-dom@6.6.3)(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@16.18.126)(lightningcss@1.29.1)))(solid-js@1.9.5)(yaml@2.7.0)
|
||||
'@eslint/js':
|
||||
specifier: ^9.23.0
|
||||
version: 9.23.0
|
||||
@@ -163,7 +163,7 @@ importers:
|
||||
version: 1.2.17
|
||||
'@tailwindcss/typography':
|
||||
specifier: ^0.5.16
|
||||
version: 0.5.16(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)))
|
||||
version: 0.5.16(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4)))
|
||||
'@types/dateformat':
|
||||
specifier: ^5.0.3
|
||||
version: 5.0.3
|
||||
@@ -175,10 +175,10 @@ importers:
|
||||
version: 1.3.1(eslint@9.23.0(jiti@2.4.2))
|
||||
eslint-plugin-solid:
|
||||
specifier: ^0.14.5
|
||||
version: 0.14.5(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)
|
||||
version: 0.14.5(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)
|
||||
eslint-plugin-tailwindcss:
|
||||
specifier: ^3.18.0
|
||||
version: 3.18.0(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)))
|
||||
version: 3.18.0(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4)))
|
||||
globals:
|
||||
specifier: ^16.0.0
|
||||
version: 16.0.0
|
||||
@@ -196,10 +196,10 @@ importers:
|
||||
version: 0.33.5
|
||||
tailwindcss:
|
||||
specifier: ^3.4.17
|
||||
version: 3.4.17(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2))
|
||||
version: 3.4.17(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4))
|
||||
typescript-eslint:
|
||||
specifier: ^8.27.0
|
||||
version: 8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)
|
||||
version: 8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)
|
||||
|
||||
examples/coffee-vector-search:
|
||||
dependencies:
|
||||
@@ -6067,6 +6067,28 @@ snapshots:
|
||||
stream-replace-string: 2.0.0
|
||||
zod: 3.24.2
|
||||
|
||||
'@astrojs/solid-js@5.0.5(@testing-library/jest-dom@6.6.3)(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@16.18.126)(lightningcss@1.29.1)))(solid-js@1.9.5)(yaml@2.7.0)':
|
||||
dependencies:
|
||||
solid-js: 1.9.5
|
||||
vite: 6.2.2(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)
|
||||
vite-plugin-solid: 2.11.6(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.2.2(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0))
|
||||
optionalDependencies:
|
||||
solid-devtools: 0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@16.18.126)(lightningcss@1.29.1))
|
||||
transitivePeerDependencies:
|
||||
- '@testing-library/jest-dom'
|
||||
- '@types/node'
|
||||
- jiti
|
||||
- less
|
||||
- lightningcss
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
'@astrojs/solid-js@5.0.5(@testing-library/jest-dom@6.6.3)(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.1)(solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@22.13.11)(lightningcss@1.29.1)))(solid-js@1.9.5)(yaml@2.7.0)':
|
||||
dependencies:
|
||||
solid-js: 1.9.5
|
||||
@@ -6148,6 +6170,16 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@astrojs/tailwind@5.1.5(astro@5.5.4(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(rollup@4.36.0)(typescript@4.9.4)(yaml@2.7.0))(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4)))(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4))':
|
||||
dependencies:
|
||||
astro: 5.5.4(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(rollup@4.36.0)(typescript@4.9.4)(yaml@2.7.0)
|
||||
autoprefixer: 10.4.21(postcss@8.5.3)
|
||||
postcss: 8.5.3
|
||||
postcss-load-config: 4.0.2(postcss@8.5.3)(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4))
|
||||
tailwindcss: 3.4.17(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4))
|
||||
transitivePeerDependencies:
|
||||
- ts-node
|
||||
|
||||
'@astrojs/tailwind@5.1.5(astro@5.5.4(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.1)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0))(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)))(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2))':
|
||||
dependencies:
|
||||
astro: 5.5.4(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.1)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0)
|
||||
@@ -7339,6 +7371,14 @@ snapshots:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@tailwindcss/typography@0.5.16(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4)))':
|
||||
dependencies:
|
||||
lodash.castarray: 4.4.0
|
||||
lodash.isplainobject: 4.0.6
|
||||
lodash.merge: 4.6.2
|
||||
postcss-selector-parser: 6.0.10
|
||||
tailwindcss: 3.4.17(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4))
|
||||
|
||||
'@tailwindcss/typography@0.5.16(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)))':
|
||||
dependencies:
|
||||
lodash.castarray: 4.4.0
|
||||
@@ -7564,6 +7604,23 @@ snapshots:
|
||||
'@types/node': 22.13.11
|
||||
optional: true
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.27.0(@typescript-eslint/parser@8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4))(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.1
|
||||
'@typescript-eslint/parser': 8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)
|
||||
'@typescript-eslint/scope-manager': 8.27.0
|
||||
'@typescript-eslint/type-utils': 8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)
|
||||
'@typescript-eslint/utils': 8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)
|
||||
'@typescript-eslint/visitor-keys': 8.27.0
|
||||
eslint: 9.23.0(jiti@2.4.2)
|
||||
graphemer: 1.4.0
|
||||
ignore: 5.3.2
|
||||
natural-compare: 1.4.0
|
||||
ts-api-utils: 2.1.0(typescript@4.9.4)
|
||||
typescript: 4.9.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.27.0(@typescript-eslint/parser@8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.1
|
||||
@@ -7581,6 +7638,18 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/parser@8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)':
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 8.27.0
|
||||
'@typescript-eslint/types': 8.27.0
|
||||
'@typescript-eslint/typescript-estree': 8.27.0(typescript@4.9.4)
|
||||
'@typescript-eslint/visitor-keys': 8.27.0
|
||||
debug: 4.4.0
|
||||
eslint: 9.23.0(jiti@2.4.2)
|
||||
typescript: 4.9.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/parser@8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)':
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 8.27.0
|
||||
@@ -7598,6 +7667,17 @@ snapshots:
|
||||
'@typescript-eslint/types': 8.27.0
|
||||
'@typescript-eslint/visitor-keys': 8.27.0
|
||||
|
||||
'@typescript-eslint/type-utils@8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)':
|
||||
dependencies:
|
||||
'@typescript-eslint/typescript-estree': 8.27.0(typescript@4.9.4)
|
||||
'@typescript-eslint/utils': 8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)
|
||||
debug: 4.4.0
|
||||
eslint: 9.23.0(jiti@2.4.2)
|
||||
ts-api-utils: 2.1.0(typescript@4.9.4)
|
||||
typescript: 4.9.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/type-utils@8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)':
|
||||
dependencies:
|
||||
'@typescript-eslint/typescript-estree': 8.27.0(typescript@5.8.2)
|
||||
@@ -7611,6 +7691,20 @@ snapshots:
|
||||
|
||||
'@typescript-eslint/types@8.27.0': {}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.27.0(typescript@4.9.4)':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.27.0
|
||||
'@typescript-eslint/visitor-keys': 8.27.0
|
||||
debug: 4.4.0
|
||||
fast-glob: 3.3.3
|
||||
is-glob: 4.0.3
|
||||
minimatch: 9.0.5
|
||||
semver: 7.7.1
|
||||
ts-api-utils: 2.1.0(typescript@4.9.4)
|
||||
typescript: 4.9.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.27.0(typescript@5.8.2)':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.27.0
|
||||
@@ -7625,6 +7719,17 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/utils@8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.5.1(eslint@9.23.0(jiti@2.4.2))
|
||||
'@typescript-eslint/scope-manager': 8.27.0
|
||||
'@typescript-eslint/types': 8.27.0
|
||||
'@typescript-eslint/typescript-estree': 8.27.0(typescript@4.9.4)
|
||||
eslint: 9.23.0(jiti@2.4.2)
|
||||
typescript: 4.9.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/utils@8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.5.1(eslint@9.23.0(jiti@2.4.2))
|
||||
@@ -7928,6 +8033,101 @@ snapshots:
|
||||
valid-filename: 4.0.0
|
||||
zod: 3.24.2
|
||||
|
||||
astro@5.5.4(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(rollup@4.36.0)(typescript@4.9.4)(yaml@2.7.0):
|
||||
dependencies:
|
||||
'@astrojs/compiler': 2.11.0
|
||||
'@astrojs/internal-helpers': 0.6.1
|
||||
'@astrojs/markdown-remark': 6.3.1
|
||||
'@astrojs/telemetry': 3.2.0
|
||||
'@oslojs/encoding': 1.1.0
|
||||
'@rollup/pluginutils': 5.1.4(rollup@4.36.0)
|
||||
acorn: 8.14.1
|
||||
aria-query: 5.3.2
|
||||
axobject-query: 4.1.0
|
||||
boxen: 8.0.1
|
||||
ci-info: 4.2.0
|
||||
clsx: 2.1.1
|
||||
common-ancestor-path: 1.0.1
|
||||
cookie: 1.0.2
|
||||
cssesc: 3.0.0
|
||||
debug: 4.4.0
|
||||
deterministic-object-hash: 2.0.2
|
||||
devalue: 5.1.1
|
||||
diff: 5.2.0
|
||||
dlv: 1.1.3
|
||||
dset: 3.1.4
|
||||
es-module-lexer: 1.6.0
|
||||
esbuild: 0.25.1
|
||||
estree-walker: 3.0.3
|
||||
flattie: 1.1.1
|
||||
github-slugger: 2.0.0
|
||||
html-escaper: 3.0.3
|
||||
http-cache-semantics: 4.1.1
|
||||
js-yaml: 4.1.0
|
||||
kleur: 4.1.5
|
||||
magic-string: 0.30.17
|
||||
magicast: 0.3.5
|
||||
mrmime: 2.0.1
|
||||
neotraverse: 0.6.18
|
||||
p-limit: 6.2.0
|
||||
p-queue: 8.1.0
|
||||
package-manager-detector: 1.1.0
|
||||
picomatch: 4.0.2
|
||||
prompts: 2.4.2
|
||||
rehype: 13.0.2
|
||||
semver: 7.7.1
|
||||
shiki: 3.2.1
|
||||
tinyexec: 0.3.2
|
||||
tinyglobby: 0.2.12
|
||||
tsconfck: 3.1.5(typescript@4.9.4)
|
||||
ultrahtml: 1.5.3
|
||||
unist-util-visit: 5.0.0
|
||||
unstorage: 1.15.0
|
||||
vfile: 6.0.3
|
||||
vite: 6.2.2(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)
|
||||
vitefu: 1.0.6(vite@6.2.2(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0))
|
||||
xxhash-wasm: 1.1.0
|
||||
yargs-parser: 21.1.1
|
||||
yocto-spinner: 0.2.1
|
||||
zod: 3.24.2
|
||||
zod-to-json-schema: 3.24.5(zod@3.24.2)
|
||||
zod-to-ts: 1.2.0(typescript@4.9.4)(zod@3.24.2)
|
||||
optionalDependencies:
|
||||
sharp: 0.33.5
|
||||
transitivePeerDependencies:
|
||||
- '@azure/app-configuration'
|
||||
- '@azure/cosmos'
|
||||
- '@azure/data-tables'
|
||||
- '@azure/identity'
|
||||
- '@azure/keyvault-secrets'
|
||||
- '@azure/storage-blob'
|
||||
- '@capacitor/preferences'
|
||||
- '@deno/kv'
|
||||
- '@netlify/blobs'
|
||||
- '@planetscale/database'
|
||||
- '@types/node'
|
||||
- '@upstash/redis'
|
||||
- '@vercel/blob'
|
||||
- '@vercel/kv'
|
||||
- aws4fetch
|
||||
- db0
|
||||
- idb-keyval
|
||||
- ioredis
|
||||
- jiti
|
||||
- less
|
||||
- lightningcss
|
||||
- rollup
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- tsx
|
||||
- typescript
|
||||
- uploadthing
|
||||
- yaml
|
||||
|
||||
astro@5.5.4(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.1)(rollup@4.36.0)(typescript@5.8.2)(yaml@2.7.0):
|
||||
dependencies:
|
||||
'@astrojs/compiler': 2.11.0
|
||||
@@ -8717,6 +8917,19 @@ snapshots:
|
||||
dependencies:
|
||||
eslint: 9.23.0(jiti@2.4.2)
|
||||
|
||||
eslint-plugin-solid@0.14.5(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4):
|
||||
dependencies:
|
||||
'@typescript-eslint/utils': 8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)
|
||||
eslint: 9.23.0(jiti@2.4.2)
|
||||
estraverse: 5.3.0
|
||||
is-html: 2.0.0
|
||||
kebab-case: 1.0.2
|
||||
known-css-properties: 0.30.0
|
||||
style-to-object: 1.0.8
|
||||
typescript: 4.9.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-solid@0.14.5(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2):
|
||||
dependencies:
|
||||
'@typescript-eslint/utils': 8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)
|
||||
@@ -8730,6 +8943,12 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-tailwindcss@3.18.0(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4))):
|
||||
dependencies:
|
||||
fast-glob: 3.3.3
|
||||
postcss: 8.5.3
|
||||
tailwindcss: 3.4.17(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4))
|
||||
|
||||
eslint-plugin-tailwindcss@3.18.0(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2))):
|
||||
dependencies:
|
||||
fast-glob: 3.3.3
|
||||
@@ -10560,6 +10779,14 @@ snapshots:
|
||||
camelcase-css: 2.0.1
|
||||
postcss: 8.5.3
|
||||
|
||||
postcss-load-config@4.0.2(postcss@8.5.3)(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4)):
|
||||
dependencies:
|
||||
lilconfig: 3.1.3
|
||||
yaml: 2.7.0
|
||||
optionalDependencies:
|
||||
postcss: 8.5.3
|
||||
ts-node: 10.9.2(@types/node@16.18.126)(typescript@4.9.4)
|
||||
|
||||
postcss-load-config@4.0.2(postcss@8.5.3)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)):
|
||||
dependencies:
|
||||
lilconfig: 3.1.3
|
||||
@@ -11237,6 +11464,20 @@ snapshots:
|
||||
|
||||
smol-toml@1.3.1: {}
|
||||
|
||||
solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@16.18.126)(lightningcss@1.29.1)):
|
||||
dependencies:
|
||||
'@babel/core': 7.26.10
|
||||
'@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.10)
|
||||
'@babel/types': 7.26.10
|
||||
'@solid-devtools/debugger': 0.23.4(solid-js@1.9.5)
|
||||
'@solid-devtools/shared': 0.13.2(solid-js@1.9.5)
|
||||
solid-js: 1.9.5
|
||||
optionalDependencies:
|
||||
vite: 5.4.14(@types/node@16.18.126)(lightningcss@1.29.1)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
optional: true
|
||||
|
||||
solid-devtools@0.30.1(solid-js@1.9.5)(vite@5.4.14(@types/node@22.13.11)(lightningcss@1.29.1)):
|
||||
dependencies:
|
||||
'@babel/core': 7.26.10
|
||||
@@ -11445,6 +11686,33 @@ snapshots:
|
||||
dependencies:
|
||||
tailwindcss: 3.4.17(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2))
|
||||
|
||||
tailwindcss@3.4.17(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4)):
|
||||
dependencies:
|
||||
'@alloc/quick-lru': 5.2.0
|
||||
arg: 5.0.2
|
||||
chokidar: 3.6.0
|
||||
didyoumean: 1.2.2
|
||||
dlv: 1.1.3
|
||||
fast-glob: 3.3.3
|
||||
glob-parent: 6.0.2
|
||||
is-glob: 4.0.3
|
||||
jiti: 1.21.7
|
||||
lilconfig: 3.1.3
|
||||
micromatch: 4.0.8
|
||||
normalize-path: 3.0.0
|
||||
object-hash: 3.0.0
|
||||
picocolors: 1.1.1
|
||||
postcss: 8.5.3
|
||||
postcss-import: 15.1.0(postcss@8.5.3)
|
||||
postcss-js: 4.0.1(postcss@8.5.3)
|
||||
postcss-load-config: 4.0.2(postcss@8.5.3)(ts-node@10.9.2(@types/node@16.18.126)(typescript@4.9.4))
|
||||
postcss-nested: 6.2.0(postcss@8.5.3)
|
||||
postcss-selector-parser: 6.1.2
|
||||
resolve: 1.22.10
|
||||
sucrase: 3.35.0
|
||||
transitivePeerDependencies:
|
||||
- ts-node
|
||||
|
||||
tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)):
|
||||
dependencies:
|
||||
'@alloc/quick-lru': 5.2.0
|
||||
@@ -11541,6 +11809,10 @@ snapshots:
|
||||
|
||||
trough@2.2.0: {}
|
||||
|
||||
ts-api-utils@2.1.0(typescript@4.9.4):
|
||||
dependencies:
|
||||
typescript: 4.9.4
|
||||
|
||||
ts-api-utils@2.1.0(typescript@5.8.2):
|
||||
dependencies:
|
||||
typescript: 5.8.2
|
||||
@@ -11598,6 +11870,10 @@ snapshots:
|
||||
ts-poet: 6.11.0
|
||||
ts-proto-descriptors: 2.0.0
|
||||
|
||||
tsconfck@3.1.5(typescript@4.9.4):
|
||||
optionalDependencies:
|
||||
typescript: 4.9.4
|
||||
|
||||
tsconfck@3.1.5(typescript@5.8.2):
|
||||
optionalDependencies:
|
||||
typescript: 5.8.2
|
||||
@@ -11627,6 +11903,16 @@ snapshots:
|
||||
dependencies:
|
||||
semver: 7.7.1
|
||||
|
||||
typescript-eslint@8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4):
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 8.27.0(@typescript-eslint/parser@8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4))(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)
|
||||
'@typescript-eslint/parser': 8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)
|
||||
'@typescript-eslint/utils': 8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.4)
|
||||
eslint: 9.23.0(jiti@2.4.2)
|
||||
typescript: 4.9.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
typescript-eslint@8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2):
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 8.27.0(@typescript-eslint/parser@8.27.0(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.23.0(jiti@2.4.2))(typescript@5.8.2)
|
||||
@@ -11831,6 +12117,21 @@ snapshots:
|
||||
rollup: 2.79.2
|
||||
vite: 6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)
|
||||
|
||||
vite-plugin-solid@2.11.6(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.2.2(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)):
|
||||
dependencies:
|
||||
'@babel/core': 7.26.10
|
||||
'@types/babel__core': 7.20.5
|
||||
babel-preset-solid: 1.9.5(@babel/core@7.26.10)
|
||||
merge-anything: 5.1.7
|
||||
solid-js: 1.9.5
|
||||
solid-refresh: 0.6.3(solid-js@1.9.5)
|
||||
vite: 6.2.2(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)
|
||||
vitefu: 1.0.6(vite@6.2.2(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0))
|
||||
optionalDependencies:
|
||||
'@testing-library/jest-dom': 6.6.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-solid@2.11.6(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)):
|
||||
dependencies:
|
||||
'@babel/core': 7.26.10
|
||||
@@ -11857,6 +12158,17 @@ snapshots:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
vite@5.4.14(@types/node@16.18.126)(lightningcss@1.29.1):
|
||||
dependencies:
|
||||
esbuild: 0.21.5
|
||||
postcss: 8.5.3
|
||||
rollup: 4.36.0
|
||||
optionalDependencies:
|
||||
'@types/node': 16.18.126
|
||||
fsevents: 2.3.3
|
||||
lightningcss: 1.29.1
|
||||
optional: true
|
||||
|
||||
vite@5.4.14(@types/node@22.13.11)(lightningcss@1.29.1):
|
||||
dependencies:
|
||||
esbuild: 0.21.5
|
||||
@@ -11868,6 +12180,18 @@ snapshots:
|
||||
lightningcss: 1.29.1
|
||||
optional: true
|
||||
|
||||
vite@6.2.2(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0):
|
||||
dependencies:
|
||||
esbuild: 0.25.1
|
||||
postcss: 8.5.3
|
||||
rollup: 4.36.0
|
||||
optionalDependencies:
|
||||
'@types/node': 16.18.126
|
||||
fsevents: 2.3.3
|
||||
jiti: 2.4.2
|
||||
lightningcss: 1.29.1
|
||||
yaml: 2.7.0
|
||||
|
||||
vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0):
|
||||
dependencies:
|
||||
esbuild: 0.25.1
|
||||
@@ -11880,6 +12204,10 @@ snapshots:
|
||||
lightningcss: 1.29.1
|
||||
yaml: 2.7.0
|
||||
|
||||
vitefu@1.0.6(vite@6.2.2(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)):
|
||||
optionalDependencies:
|
||||
vite: 6.2.2(@types/node@16.18.126)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)
|
||||
|
||||
vitefu@1.0.6(vite@6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)):
|
||||
optionalDependencies:
|
||||
vite: 6.2.2(@types/node@22.13.11)(jiti@2.4.2)(lightningcss@1.29.1)(yaml@2.7.0)
|
||||
@@ -12173,6 +12501,11 @@ snapshots:
|
||||
dependencies:
|
||||
zod: 3.24.2
|
||||
|
||||
zod-to-ts@1.2.0(typescript@4.9.4)(zod@3.24.2):
|
||||
dependencies:
|
||||
typescript: 4.9.4
|
||||
zod: 3.24.2
|
||||
|
||||
zod-to-ts@1.2.0(typescript@5.8.2)(zod@3.24.2):
|
||||
dependencies:
|
||||
typescript: 5.8.2
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { ConflictResolution } from "./ConflictResolution";
|
||||
import type { GeneratedExpressionMode } from "./GeneratedExpressionMode";
|
||||
import type { ReferentialAction } from "./ReferentialAction";
|
||||
|
||||
export type ColumnOption = "Null" | "NotNull" | { "Default": string } | { "Unique": { is_primary: boolean, } } | { "ForeignKey": { foreign_table: string, referred_columns: Array<string>, on_delete: ReferentialAction | null, on_update: ReferentialAction | null, } } | { "Check": string } | { "OnUpdate": string } | { "Generated": { expr: string, mode: GeneratedExpressionMode | null, } };
|
||||
export type ColumnOption = "Null" | "NotNull" | { "Default": string } | { "Unique": { is_primary: boolean, conflict_clause: ConflictResolution | null, } } | { "ForeignKey": { foreign_table: string, referred_columns: Array<string>, on_delete: ReferentialAction | null, on_update: ReferentialAction | null, } } | { "Check": string } | { "OnUpdate": string } | { "Generated": { expr: string, mode: GeneratedExpressionMode | null, } };
|
||||
|
||||
6
trailbase-core/bindings/ConflictResolution.ts
Normal file
6
trailbase-core/bindings/ConflictResolution.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* Conflict resolution types
|
||||
*/
|
||||
export type ConflictResolution = "Rollback" | "Abort" | "Fail" | "Ignore" | "Replace";
|
||||
@@ -1,8 +1,11 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { ConflictResolution } from "./ConflictResolution";
|
||||
|
||||
export type UniqueConstraint = { name: string | null,
|
||||
/**
|
||||
* Identifiers of the columns that are unique.
|
||||
* TODO: Should be indexed/ordered column.
|
||||
*
|
||||
* TODO: Should be indexed/ordered column, e.g. ASC/DESC:
|
||||
* https://www.sqlite.org/syntax/indexed-column.html
|
||||
*/
|
||||
columns: Array<string>, };
|
||||
columns: Array<string>, conflict_clause: ConflictResolution | null, };
|
||||
|
||||
@@ -415,7 +415,9 @@ function ColumnOptionsFields(props: {
|
||||
props.onChange(
|
||||
setUnique(
|
||||
props.value,
|
||||
value ? { is_primary: false } : undefined,
|
||||
value
|
||||
? { is_primary: false, conflict_clause: null }
|
||||
: undefined,
|
||||
),
|
||||
);
|
||||
}}
|
||||
@@ -724,7 +726,7 @@ export const primaryKeyPresets: [string, (colName: string) => Preset][] = [
|
||||
return {
|
||||
data_type: "Blob",
|
||||
options: [
|
||||
{ Unique: { is_primary: true } },
|
||||
{ Unique: { is_primary: true, conflict_clause: null } },
|
||||
{ Check: `is_uuid_v7(${colName})` },
|
||||
{ Default: "(uuid_v7())" },
|
||||
"NotNull",
|
||||
@@ -737,7 +739,10 @@ export const primaryKeyPresets: [string, (colName: string) => Preset][] = [
|
||||
(_colName: string) => {
|
||||
return {
|
||||
data_type: "Integer",
|
||||
options: [{ Unique: { is_primary: true } }, "NotNull"],
|
||||
options: [
|
||||
{ Unique: { is_primary: true, conflict_clause: null } },
|
||||
"NotNull",
|
||||
],
|
||||
};
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Column } from "@bindings/Column";
|
||||
import type { ColumnOption } from "@bindings/ColumnOption";
|
||||
import type { ReferentialAction } from "@bindings/ReferentialAction";
|
||||
import type { ConflictResolution } from "@bindings/ConflictResolution";
|
||||
import type { Table } from "@bindings/Table";
|
||||
import type { View } from "@bindings/View";
|
||||
|
||||
@@ -116,7 +117,10 @@ export function setForeignKey(
|
||||
return newOpts;
|
||||
}
|
||||
|
||||
export type Unique = { is_primary: boolean };
|
||||
export type Unique = {
|
||||
is_primary: boolean;
|
||||
conflict_clause: ConflictResolution | null;
|
||||
};
|
||||
|
||||
export function getUnique(options: ColumnOption[]): Unique | undefined {
|
||||
return options.reduce<Unique | undefined>((acc, cur: ColumnOption) => {
|
||||
|
||||
@@ -133,7 +133,10 @@ mod tests {
|
||||
name: pk_col.clone(),
|
||||
data_type: ColumnDataType::Blob,
|
||||
options: vec![
|
||||
ColumnOption::Unique { is_primary: true },
|
||||
ColumnOption::Unique {
|
||||
is_primary: true,
|
||||
conflict_clause: None,
|
||||
},
|
||||
ColumnOption::Check(format!("(is_uuid_v7({pk_col}))")),
|
||||
ColumnOption::Default("(uuid_v7())".to_string()),
|
||||
],
|
||||
|
||||
@@ -154,7 +154,10 @@ mod tests {
|
||||
columns: vec![Column {
|
||||
name: pk_col.clone(),
|
||||
data_type: ColumnDataType::Blob,
|
||||
options: vec![ColumnOption::Unique { is_primary: true }],
|
||||
options: vec![ColumnOption::Unique {
|
||||
is_primary: true,
|
||||
conflict_clause: None,
|
||||
}],
|
||||
}],
|
||||
foreign_keys: vec![],
|
||||
unique: vec![],
|
||||
|
||||
@@ -662,7 +662,7 @@ impl InsertQueryBuilder {
|
||||
let query = if !column_names.is_empty() {
|
||||
format!(
|
||||
r#"INSERT {conflict_clause} INTO "{table_name}" ({col_names}) VALUES ({placeholders}) {return_fragment}"#,
|
||||
col_names = Self::build_col_names(column_names),
|
||||
col_names = crate::schema::quote(column_names),
|
||||
placeholders = params.placeholders(),
|
||||
)
|
||||
} else {
|
||||
@@ -673,21 +673,6 @@ impl InsertQueryBuilder {
|
||||
return Ok((query, params.named_params, params.files));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn build_col_names(column_names: &[String]) -> String {
|
||||
let mut s = String::new();
|
||||
for (i, name) in column_names.iter().enumerate() {
|
||||
if i > 0 {
|
||||
s.push_str(", \"");
|
||||
} else {
|
||||
s.push('"');
|
||||
}
|
||||
s.push_str(name);
|
||||
s.push('"');
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conflict_resolution_clause(config: ConflictResolutionStrategy) -> &'static str {
|
||||
type C = ConflictResolutionStrategy;
|
||||
|
||||
@@ -2,8 +2,8 @@ use itertools::Itertools;
|
||||
use log::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlite3_parser::ast::{
|
||||
fmt::ToTokens, ColumnDefinition, CreateTableBody, Expr, FromClause, Literal, Name, SelectTable,
|
||||
Stmt, TableConstraint, TableOptions,
|
||||
fmt::ToTokens, ColumnDefinition, CreateTableBody, Expr, FromClause, Literal, Name, QualifiedName,
|
||||
SelectTable, Stmt, TableConstraint, TableOptions,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use thiserror::Error;
|
||||
@@ -36,33 +36,38 @@ pub struct ForeignKey {
|
||||
pub columns: Vec<String>,
|
||||
pub foreign_table: String,
|
||||
pub referred_columns: Vec<String>,
|
||||
|
||||
// Only "ON DELETE" and "ON UPDATE" are supported in foreign key clause, i.e. no "ON INSERT":
|
||||
// https://www.sqlite.org/syntax/foreign-key-clause.html
|
||||
pub on_delete: Option<ReferentialAction>,
|
||||
pub on_update: Option<ReferentialAction>,
|
||||
// TODO: Missing DEFERRABLE.
|
||||
}
|
||||
|
||||
impl ForeignKey {
|
||||
fn to_fragment(&self) -> String {
|
||||
return format!(
|
||||
"{name} FOREIGN KEY ({cols}) REFERENCES '{foreign_table}'{ref_col} {on_delete} {on_update}",
|
||||
name = self
|
||||
.name
|
||||
.as_ref()
|
||||
.map_or_else(|| "".to_string(), |n| format!("CONSTRAINT {n}")),
|
||||
cols = quote(&self.columns),
|
||||
foreign_table = self.foreign_table,
|
||||
ref_col = match self.referred_columns.len() {
|
||||
0 => "".to_string(),
|
||||
_ => format!("({})", quote(&self.referred_columns)),
|
||||
},
|
||||
on_delete = self.on_delete.as_ref().map_or_else(
|
||||
|| "".to_string(),
|
||||
|action| format!("ON DELETE {}", action.to_fragment())
|
||||
),
|
||||
on_update = self.on_update.as_ref().map_or_else(
|
||||
|| "".to_string(),
|
||||
|action| format!("ON UPDATE {}", action.to_fragment())
|
||||
),
|
||||
let cols = quote(&self.columns);
|
||||
let foreign_table = &self.foreign_table;
|
||||
let ref_col = match self.referred_columns.len() {
|
||||
0 => "".to_string(),
|
||||
_ => format!("({})", quote(&self.referred_columns)),
|
||||
};
|
||||
|
||||
let on_delete = self.on_delete.as_ref().map_or_else(
|
||||
|| "".to_string(),
|
||||
|action| format!("ON DELETE {}", action.to_fragment()),
|
||||
);
|
||||
let on_update = self.on_update.as_ref().map_or_else(
|
||||
|| "".to_string(),
|
||||
|action| format!("ON UPDATE {}", action.to_fragment()),
|
||||
);
|
||||
|
||||
return if let Some(ref name) = self.name {
|
||||
format!(
|
||||
"CONSTRAINT '{name}' FOREIGN KEY ({cols}) REFERENCES '{foreign_table}'{ref_col} {on_delete} {on_update}")
|
||||
} else {
|
||||
format!("FOREIGN KEY ({cols}) REFERENCES '{foreign_table}'{ref_col} {on_delete} {on_update}")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,22 +76,31 @@ impl ForeignKey {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, TS, PartialEq)]
|
||||
pub struct UniqueConstraint {
|
||||
pub name: Option<String>,
|
||||
|
||||
/// Identifiers of the columns that are unique.
|
||||
/// TODO: Should be indexed/ordered column.
|
||||
///
|
||||
/// TODO: Should be indexed/ordered column, e.g. ASC/DESC:
|
||||
/// https://www.sqlite.org/syntax/indexed-column.html
|
||||
pub columns: Vec<String>,
|
||||
|
||||
pub conflict_clause: Option<ConflictResolution>,
|
||||
}
|
||||
|
||||
impl UniqueConstraint {
|
||||
fn to_fragment(&self) -> String {
|
||||
return format!(
|
||||
"{name}UNIQUE ({cols}) {conflict_clause}",
|
||||
name = self
|
||||
.name
|
||||
.as_ref()
|
||||
.map_or_else(|| "".to_string(), |n| format!("CONSTRAINT '{n}' ")),
|
||||
cols = quote(&self.columns),
|
||||
conflict_clause = "",
|
||||
);
|
||||
let cols = quote(&self.columns);
|
||||
|
||||
return match (self.name.as_ref(), &self.conflict_clause.as_ref()) {
|
||||
(Some(name), Some(resolution)) => format!(
|
||||
"CONSTRAINT '{name}' UNIQUE ({cols}) ON CONFLICT {}",
|
||||
resolution.to_fragment()
|
||||
),
|
||||
(Some(name), None) => format!("CONSTRAINT '{name}' UNIQUE ({cols})"),
|
||||
(None, Some(resolution)) => {
|
||||
format!("UNIQUE ({cols}) ON CONFLICT {}", resolution.to_fragment())
|
||||
}
|
||||
(None, None) => format!("UNIQUE ({cols})"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +111,47 @@ pub struct ColumnOrder {
|
||||
pub nulls_first: Option<bool>,
|
||||
}
|
||||
|
||||
/// Conflict resolution types
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, TS, PartialEq)]
|
||||
pub enum ConflictResolution {
|
||||
/// `ROLLBACK`
|
||||
Rollback,
|
||||
/// `ABORT`
|
||||
Abort, // default
|
||||
/// `FAIL`
|
||||
Fail,
|
||||
/// `IGNORE`
|
||||
Ignore,
|
||||
/// `REPLACE`
|
||||
Replace,
|
||||
}
|
||||
|
||||
impl From<sqlite3_parser::ast::ResolveType> for ConflictResolution {
|
||||
fn from(res: sqlite3_parser::ast::ResolveType) -> Self {
|
||||
use sqlite3_parser::ast::ResolveType;
|
||||
match res {
|
||||
ResolveType::Rollback => ConflictResolution::Rollback,
|
||||
ResolveType::Abort => ConflictResolution::Abort,
|
||||
ResolveType::Fail => ConflictResolution::Fail,
|
||||
ResolveType::Ignore => ConflictResolution::Ignore,
|
||||
ResolveType::Replace => ConflictResolution::Replace,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConflictResolution {
|
||||
// https://www.sqlite.org/syntax/conflict-clause.html
|
||||
fn to_fragment(&self) -> &'static str {
|
||||
return match self {
|
||||
Self::Rollback => "ROLLBACK",
|
||||
Self::Abort => "ABORT",
|
||||
Self::Fail => "FAIL",
|
||||
Self::Ignore => "IGNORE",
|
||||
Self::Replace => "REPLACE",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, TS, PartialEq)]
|
||||
pub enum ReferentialAction {
|
||||
Restrict,
|
||||
@@ -146,6 +201,8 @@ pub enum ColumnOption {
|
||||
// NOTE: Unique { is_primary: true} means PrimaryKey.
|
||||
Unique {
|
||||
is_primary: bool,
|
||||
conflict_clause: Option<ConflictResolution>,
|
||||
// TODO: Missing ASC/DESC & AUTOINCREMENT for PK.
|
||||
},
|
||||
ForeignKey {
|
||||
foreign_table: String,
|
||||
@@ -167,13 +224,15 @@ impl ColumnOption {
|
||||
Self::Null => "NULL".to_string(),
|
||||
Self::NotNull => "NOT NULL".to_string(),
|
||||
Self::Default(v) => format!("DEFAULT {v}"),
|
||||
Self::Unique { is_primary } => {
|
||||
if *is_primary {
|
||||
"PRIMARY KEY".to_string()
|
||||
} else {
|
||||
"UNIQUE".to_string()
|
||||
}
|
||||
}
|
||||
Self::Unique {
|
||||
is_primary,
|
||||
conflict_clause,
|
||||
} => match (*is_primary, conflict_clause.as_ref()) {
|
||||
(true, Some(res)) => format!("PRIMARY KEY ON CONFLICT {}", res.to_fragment()),
|
||||
(true, None) => "PRIMARY KEY".to_string(),
|
||||
(false, Some(res)) => format!("UNIQUE ON CONFLICT {}", res.to_fragment()),
|
||||
(false, None) => "UNIQUE".to_string(),
|
||||
},
|
||||
Self::ForeignKey {
|
||||
foreign_table,
|
||||
referred_columns,
|
||||
@@ -185,7 +244,6 @@ impl ColumnOption {
|
||||
ref_col = match referred_columns.len() {
|
||||
0 => "".to_string(),
|
||||
_ => format!("({})", quote(referred_columns)),
|
||||
//_ => format!("({})", referred_columns.join(", ")),
|
||||
},
|
||||
on_delete = on_delete.as_ref().map_or_else(
|
||||
|| "".to_string(),
|
||||
@@ -349,10 +407,9 @@ impl Column {
|
||||
|
||||
impl Column {
|
||||
pub fn is_primary(&self) -> bool {
|
||||
self
|
||||
.options
|
||||
.iter()
|
||||
.any(|opt| matches!(opt, ColumnOption::Unique { is_primary } if *is_primary ))
|
||||
self.options.iter().any(
|
||||
|opt| matches!(opt, ColumnOption::Unique { is_primary, conflict_clause: _ } if *is_primary ),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,10 +571,16 @@ impl TryFrom<sqlite3_parser::ast::Stmt> for Table {
|
||||
TableConstraint::ForeignKey {
|
||||
columns,
|
||||
clause,
|
||||
deref_clause: _,
|
||||
deref_clause,
|
||||
} => {
|
||||
if let Some(ref clause) = deref_clause {
|
||||
// TOOD: Parse DEFERRABLE.
|
||||
log::warn!("Unsupported DEFERRABLE in FK clause: {clause:?}");
|
||||
}
|
||||
|
||||
let mut on_delete: Option<ReferentialAction> = None;
|
||||
let mut on_update: Option<ReferentialAction> = None;
|
||||
|
||||
for arg in &clause.args {
|
||||
use sqlite3_parser::ast::RefArg;
|
||||
|
||||
@@ -528,21 +591,31 @@ impl TryFrom<sqlite3_parser::ast::Stmt> for Table {
|
||||
RefArg::OnUpdate(action) => {
|
||||
on_update = Some((*action).into());
|
||||
}
|
||||
_ => {}
|
||||
RefArg::OnInsert(action) => {
|
||||
log::error!("Unexpected ON INSERT in FK clause: {action:?}");
|
||||
}
|
||||
RefArg::Match(name) => {
|
||||
// SQL supports FK MATCH clause, which is *not* supported by sqlite:
|
||||
// https://www.sqlite.org/foreignkeys.html#fk_unsupported
|
||||
log::warn!("Unsupported MATCH in FK clause: {name:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(ForeignKey {
|
||||
name: constraint.name.as_ref().map(|name| unquote(name.clone())),
|
||||
foreign_table: unquote(clause.tbl_name.clone()),
|
||||
name: constraint
|
||||
.name
|
||||
.as_ref()
|
||||
.map(|name| unquote_name(name.clone())),
|
||||
foreign_table: unquote_name(clause.tbl_name.clone()),
|
||||
columns: columns
|
||||
.iter()
|
||||
.map(|c| unquote(c.col_name.clone()))
|
||||
.map(|c| unquote_name(c.col_name.clone()))
|
||||
.collect(),
|
||||
referred_columns: clause.columns.as_ref().map_or_else(Vec::new, |columns| {
|
||||
columns
|
||||
.iter()
|
||||
.map(|c| unquote(c.col_name.clone()))
|
||||
.map(|c| unquote_name(c.col_name.clone()))
|
||||
.collect()
|
||||
}),
|
||||
on_update,
|
||||
@@ -558,13 +631,17 @@ impl TryFrom<sqlite3_parser::ast::Stmt> for Table {
|
||||
.filter_map(|constraint| match &constraint.constraint {
|
||||
TableConstraint::Unique {
|
||||
columns,
|
||||
conflict_clause: _,
|
||||
conflict_clause,
|
||||
} => Some(UniqueConstraint {
|
||||
name: constraint.name.as_ref().map(|name| unquote(name.clone())),
|
||||
name: constraint
|
||||
.name
|
||||
.as_ref()
|
||||
.map(|name| unquote_name(name.clone())),
|
||||
columns: columns
|
||||
.iter()
|
||||
.map(|c| unquote_expr(c.expr.clone()))
|
||||
.collect(),
|
||||
conflict_clause: conflict_clause.map(|c| c.into()),
|
||||
}),
|
||||
_ => None,
|
||||
})
|
||||
@@ -584,7 +661,7 @@ impl TryFrom<sqlite3_parser::ast::Stmt> for Table {
|
||||
} = def;
|
||||
assert_eq!(name, col_name);
|
||||
|
||||
let name = unquote(col_name);
|
||||
let name = unquote_name(col_name);
|
||||
assert!(!name.is_empty());
|
||||
|
||||
let data_type: ColumnDataType = match col_type {
|
||||
@@ -605,21 +682,8 @@ impl TryFrom<sqlite3_parser::ast::Stmt> for Table {
|
||||
})
|
||||
.collect();
|
||||
|
||||
// WARN: SQLite escaping is weird, altering a table adds double quote escaping and
|
||||
// sqlite3_parser unlike sqlparser, doesn't parse out the escaping.
|
||||
//
|
||||
// sqlite> CREATE TABLE foo (x text);
|
||||
// sqlite> SELECT sql FROM main.sqlite_schema;
|
||||
// CREATE TABLE foo (x text)
|
||||
// sqlite> ALTER TABLE foo RENAME TO bar
|
||||
// sqlite> SELECT sql FROM main.sqlite_schema;
|
||||
// CREATE TABLE "bar" (x text)
|
||||
//
|
||||
// TODO: factor out QualifiedNamed conversion.
|
||||
let table_name = unquote(tbl_name.name);
|
||||
|
||||
Ok(Table {
|
||||
name: table_name,
|
||||
name: unquote_qualified(tbl_name),
|
||||
strict: options.contains(TableOptions::STRICT),
|
||||
columns,
|
||||
foreign_keys,
|
||||
@@ -633,7 +697,7 @@ impl TryFrom<sqlite3_parser::ast::Stmt> for Table {
|
||||
args: _args,
|
||||
..
|
||||
} => Ok(Table {
|
||||
name: unquote(tbl_name.name),
|
||||
name: unquote_qualified(tbl_name),
|
||||
strict: false,
|
||||
columns: vec![],
|
||||
foreign_keys: vec![],
|
||||
@@ -660,9 +724,17 @@ impl From<sqlite3_parser::ast::ColumnConstraint> for ColumnOption {
|
||||
|
||||
return match constraint {
|
||||
Constraint::PrimaryKey {
|
||||
conflict_clause: _, ..
|
||||
} => ColumnOption::Unique { is_primary: true },
|
||||
Constraint::Unique(_) => ColumnOption::Unique { is_primary: false },
|
||||
conflict_clause,
|
||||
order: _,
|
||||
auto_increment: _,
|
||||
} => ColumnOption::Unique {
|
||||
is_primary: true,
|
||||
conflict_clause: conflict_clause.map(|c| c.into()),
|
||||
},
|
||||
Constraint::Unique(conflict_clause) => ColumnOption::Unique {
|
||||
is_primary: false,
|
||||
conflict_clause: conflict_clause.map(|c| c.into()),
|
||||
},
|
||||
Constraint::Check(expr) => {
|
||||
// NOTE: This is not using unquote on purpose, since this is not an identifier.
|
||||
ColumnOption::Check(expr.to_string())
|
||||
@@ -671,8 +743,11 @@ impl From<sqlite3_parser::ast::ColumnConstraint> for ColumnOption {
|
||||
let columns = clause.columns.unwrap_or(vec![]);
|
||||
|
||||
ColumnOption::ForeignKey {
|
||||
foreign_table: unquote(clause.tbl_name),
|
||||
referred_columns: columns.into_iter().map(|c| unquote(c.col_name)).collect(),
|
||||
foreign_table: unquote_name(clause.tbl_name),
|
||||
referred_columns: columns
|
||||
.into_iter()
|
||||
.map(|c| unquote_name(c.col_name))
|
||||
.collect(),
|
||||
on_delete: None,
|
||||
on_update: None,
|
||||
}
|
||||
@@ -714,8 +789,8 @@ impl TryFrom<sqlite3_parser::ast::Stmt> for TableIndex {
|
||||
columns,
|
||||
where_clause,
|
||||
} => Ok(TableIndex {
|
||||
name: unquote(idx_name.name),
|
||||
table_name: unquote(tbl_name),
|
||||
name: unquote_name(idx_name.name),
|
||||
table_name: unquote_name(tbl_name),
|
||||
columns: columns
|
||||
.into_iter()
|
||||
.map(|order_expr| ColumnOrder {
|
||||
@@ -774,7 +849,7 @@ impl View {
|
||||
};
|
||||
|
||||
Ok(View {
|
||||
name: unquote(view_name.name),
|
||||
name: unquote_qualified(view_name),
|
||||
columns,
|
||||
query: SelectFormatter(*select).to_string(),
|
||||
temporary,
|
||||
@@ -788,15 +863,12 @@ impl View {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_entry(
|
||||
qn: sqlite3_parser::ast::QualifiedName,
|
||||
alias: Option<sqlite3_parser::ast::As>,
|
||||
) -> (String, String) {
|
||||
fn to_entry(qn: QualifiedName, alias: Option<sqlite3_parser::ast::As>) -> (String, String) {
|
||||
return (
|
||||
alias
|
||||
.and_then(|alias| {
|
||||
if let sqlite3_parser::ast::As::As(name) = alias {
|
||||
return Some(unquote(name));
|
||||
return Some(unquote_name(name));
|
||||
}
|
||||
None
|
||||
})
|
||||
@@ -917,7 +989,7 @@ fn try_extract_column_mapping(
|
||||
}
|
||||
}
|
||||
ResultColumn::TableStar(name) => {
|
||||
let name = unquote(name);
|
||||
let name = unquote_name(name);
|
||||
let Some(table_name) = table_names.get(&name) else {
|
||||
return Err(SchemaError::Precondition(
|
||||
format!("Missing alias: {name}").into(),
|
||||
@@ -947,7 +1019,7 @@ fn try_extract_column_mapping(
|
||||
let name = alias
|
||||
.and_then(|alias| {
|
||||
if let sqlite3_parser::ast::As::As(name) = alias {
|
||||
return Some(unquote(name));
|
||||
return Some(unquote_name(name));
|
||||
}
|
||||
None
|
||||
})
|
||||
@@ -966,8 +1038,8 @@ fn try_extract_column_mapping(
|
||||
});
|
||||
}
|
||||
Expr::Qualified(qualifier, name) => {
|
||||
let qualifier = unquote(qualifier);
|
||||
let col_name = unquote(name);
|
||||
let qualifier = unquote_name(qualifier);
|
||||
let col_name = unquote_name(name);
|
||||
|
||||
let Some(table_name) = table_names.get(&qualifier) else {
|
||||
return Err(SchemaError::Precondition(
|
||||
@@ -985,7 +1057,7 @@ fn try_extract_column_mapping(
|
||||
let name = alias
|
||||
.and_then(|alias| {
|
||||
if let sqlite3_parser::ast::As::As(name) = alias {
|
||||
return Some(unquote(name));
|
||||
return Some(unquote_name(name));
|
||||
}
|
||||
None
|
||||
})
|
||||
@@ -1017,7 +1089,7 @@ fn try_extract_column_mapping(
|
||||
|
||||
let Some(name) = alias.and_then(|alias| {
|
||||
if let sqlite3_parser::ast::As::As(name) = alias {
|
||||
return Some(unquote(name));
|
||||
return Some(unquote_name(name));
|
||||
}
|
||||
None
|
||||
}) else {
|
||||
@@ -1047,7 +1119,8 @@ fn try_extract_column_mapping(
|
||||
return Ok(Some(mapping));
|
||||
}
|
||||
|
||||
fn quote(column_names: &[String]) -> String {
|
||||
#[inline]
|
||||
pub(crate) fn quote(column_names: &[String]) -> String {
|
||||
let mut s = String::new();
|
||||
for (i, name) in column_names.iter().enumerate() {
|
||||
if i > 0 {
|
||||
@@ -1077,17 +1150,22 @@ fn unquote_string(s: String) -> String {
|
||||
};
|
||||
}
|
||||
|
||||
fn unquote(name: Name) -> String {
|
||||
fn unquote_name(name: Name) -> String {
|
||||
return unquote_string(name.0);
|
||||
}
|
||||
|
||||
fn unquote_qualified(name: QualifiedName) -> String {
|
||||
// FIXME: unquoting of qualified name.
|
||||
return unquote_name(name.name);
|
||||
}
|
||||
|
||||
fn unquote_id(id: sqlite3_parser::ast::Id) -> String {
|
||||
return unquote_string(id.0);
|
||||
}
|
||||
|
||||
fn unquote_expr(expr: Expr) -> String {
|
||||
return match expr {
|
||||
Expr::Name(n) => unquote(n),
|
||||
Expr::Name(n) => unquote_name(n),
|
||||
Expr::Id(id) => unquote_id(id),
|
||||
Expr::Literal(Literal::String(s)) => unquote_string(s),
|
||||
x => x.to_string(),
|
||||
@@ -1099,11 +1177,18 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::table_metadata::sqlite3_parse_into_statement;
|
||||
|
||||
#[test]
|
||||
fn test_quote() {
|
||||
assert_eq!("", quote(&vec![]));
|
||||
assert_eq!("''", quote(&vec!["".to_string()]));
|
||||
assert_eq!("'foo', ''", quote(&vec!["foo".to_string(), "".to_string()]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unquote() {
|
||||
assert_eq!(unquote(Name("".to_string())), "");
|
||||
assert_eq!(unquote(Name("['``']".to_string())), "'``'");
|
||||
assert_eq!(unquote(Name("\"[]\"".to_string())), "[]");
|
||||
assert_eq!(unquote_name(Name("".to_string())), "");
|
||||
assert_eq!(unquote_name(Name("['``']".to_string())), "'``'");
|
||||
assert_eq!(unquote_name(Name("\"[]\"".to_string())), "[]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1142,7 +1227,7 @@ mod tests {
|
||||
user_id BLOB,
|
||||
email TEXT NOT NULL,
|
||||
email_visibility INTEGER DEFAULT FALSE NOT NULL,
|
||||
username TEXT,
|
||||
username TEXT UNIQUE ON CONFLICT ABORT,
|
||||
age INTEGER,
|
||||
double_age INTEGER GENERATED ALWAYS AS (2 * 'age') VIRTUAL,
|
||||
triple_age INTEGER AS (3 * age) STORED,
|
||||
@@ -1150,8 +1235,9 @@ mod tests {
|
||||
[index] TEXT,
|
||||
|
||||
UNIQUE (email),
|
||||
UNIQUE ([index]) ON CONFLICT FAIL,
|
||||
CONSTRAINT optional_tbl_constraint_name CHECK(username != ''),
|
||||
-- optional constraint name:
|
||||
CONSTRAINT `unique` UNIQUE ([index]) ON CONFLICT FAIL,
|
||||
CHECK(username != ''),
|
||||
FOREIGN KEY(user_id) REFERENCES 'table'('index') ON DELETE CASCADE
|
||||
) STRICT;
|
||||
"#
|
||||
@@ -1243,7 +1329,10 @@ mod tests {
|
||||
name: "user".to_string(),
|
||||
data_type: ColumnDataType::Blob,
|
||||
options: vec![
|
||||
ColumnOption::Unique { is_primary: true },
|
||||
ColumnOption::Unique {
|
||||
is_primary: true,
|
||||
conflict_clause: None,
|
||||
},
|
||||
ColumnOption::ForeignKey {
|
||||
foreign_table: "_user".to_string(),
|
||||
referred_columns: vec!["id".to_string()],
|
||||
@@ -1270,7 +1359,10 @@ mod tests {
|
||||
Column {
|
||||
name: "id".to_string(),
|
||||
data_type: ColumnDataType::Blob,
|
||||
options: vec![ColumnOption::Unique { is_primary: true }],
|
||||
options: vec![ColumnOption::Unique {
|
||||
is_primary: true,
|
||||
conflict_clause: None,
|
||||
}],
|
||||
},
|
||||
Column {
|
||||
name: "author".to_string(),
|
||||
|
||||
@@ -386,7 +386,7 @@ fn find_user_id_foreign_key_columns(columns: &[Column]) -> Vec<usize> {
|
||||
fn find_record_pk_column_index(columns: &[Column], tables: &[Table]) -> Option<usize> {
|
||||
let primary_key_col_index = columns.iter().position(|col| {
|
||||
for opt in &col.options {
|
||||
if let ColumnOption::Unique { is_primary } = opt {
|
||||
if let ColumnOption::Unique { is_primary, .. } = opt {
|
||||
return *is_primary;
|
||||
}
|
||||
}
|
||||
@@ -435,7 +435,7 @@ fn find_record_pk_column_index(columns: &[Column], tables: &[Table]) -> Option<u
|
||||
ColumnOption::Check(expr) if UUID_V7_RE.is_match(expr) => {
|
||||
return Some(index);
|
||||
}
|
||||
ColumnOption::Unique { is_primary } if *is_primary => {
|
||||
ColumnOption::Unique { is_primary, .. } if *is_primary => {
|
||||
is_pk = true;
|
||||
}
|
||||
_ => {}
|
||||
@@ -823,7 +823,7 @@ pub(crate) fn build_json_schema_recursive(
|
||||
}
|
||||
}
|
||||
}
|
||||
ColumnOption::Unique { is_primary } => {
|
||||
ColumnOption::Unique { is_primary, .. } => {
|
||||
// According to the SQL standard, PRIMARY KEY should always imply NOT NULL.
|
||||
// Unfortunately, due to a bug in some early versions, this is not the case in SQLite.
|
||||
// Unless the column is an INTEGER PRIMARY KEY or the table is a WITHOUT ROWID table or a
|
||||
|
||||
Reference in New Issue
Block a user