@rocicorp/zero 1.10.0-canary.14 → 1.10.0-canary.15

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 (62) hide show
  1. package/out/zero/package.js +1 -1
  2. package/out/zero/package.js.map +1 -1
  3. package/out/zero-cache/src/db/create.d.ts.map +1 -1
  4. package/out/zero-cache/src/db/create.js +4 -1
  5. package/out/zero-cache/src/db/create.js.map +1 -1
  6. package/out/zero-cache/src/db/index-predicate.d.ts +4 -0
  7. package/out/zero-cache/src/db/index-predicate.d.ts.map +1 -0
  8. package/out/zero-cache/src/db/index-predicate.js +46 -0
  9. package/out/zero-cache/src/db/index-predicate.js.map +1 -0
  10. package/out/zero-cache/src/db/lite-tables.d.ts +10 -2
  11. package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
  12. package/out/zero-cache/src/db/lite-tables.js +8 -3
  13. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  14. package/out/zero-cache/src/db/specs.d.ts +41 -0
  15. package/out/zero-cache/src/db/specs.d.ts.map +1 -1
  16. package/out/zero-cache/src/db/specs.js +30 -3
  17. package/out/zero-cache/src/db/specs.js.map +1 -1
  18. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +11 -1
  19. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  20. package/out/zero-cache/src/services/change-source/pg/change-source.js +20 -1
  21. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  22. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  23. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +2 -1
  24. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  25. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +1512 -228
  26. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
  27. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts +19 -0
  28. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts.map +1 -0
  29. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js +521 -0
  30. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js.map +1 -0
  31. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  32. package/out/zero-cache/src/services/change-source/pg/schema/init.js +9 -0
  33. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  34. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +136 -19
  35. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts.map +1 -1
  36. package/out/zero-cache/src/services/change-source/pg/schema/published.js +80 -12
  37. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  38. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +126 -19
  39. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  40. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +1 -1
  41. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  42. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +2 -0
  43. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  44. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +3 -0
  45. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  46. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +1 -0
  47. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  48. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  49. package/out/zero-cache/src/services/replicator/change-processor.js +16 -16
  50. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  51. package/out/zero-client/src/client/version.js +1 -1
  52. package/out/zqlite/src/query-builder.d.ts.map +1 -1
  53. package/out/zqlite/src/query-builder.js +2 -1
  54. package/out/zqlite/src/query-builder.js.map +1 -1
  55. package/out/zqlite/src/sqlite-stat-fanout.d.ts.map +1 -1
  56. package/out/zqlite/src/sqlite-stat-fanout.js +1 -0
  57. package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
  58. package/out/zqlite/src/table-source.d.ts +1 -1
  59. package/out/zqlite/src/table-source.d.ts.map +1 -1
  60. package/out/zqlite/src/table-source.js +2 -1
  61. package/out/zqlite/src/table-source.js.map +1 -1
  62. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  var package_default = {
2
2
  name: "@rocicorp/zero",
3
- version: "1.10.0-canary.14",
3
+ version: "1.10.0-canary.15",
4
4
  description: "Zero is a web framework for serverless web development.",
5
5
  homepage: "https://zero.rocicorp.dev",
6
6
  bugs: { "url": "https://bugs.rocicorp.dev" },
@@ -1 +1 @@
1
- {"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.10.0-canary.14\",\n \"description\": \"Zero is a web framework for serverless web development.\",\n \"homepage\": \"https://zero.rocicorp.dev\",\n \"bugs\": {\n \"url\": \"https://bugs.rocicorp.dev\"\n },\n \"license\": \"Apache-2.0\",\n \"author\": \"Rocicorp, Inc.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/rocicorp/mono.git\",\n \"directory\": \"packages/zero\"\n },\n \"bin\": {\n \"analyze-query\": \"./out/zero/src/analyze-query.js\",\n \"ast-to-zql\": \"./out/zero/src/ast-to-zql.js\",\n \"transform-query\": \"./out/zero/src/transform-query.js\",\n \"zero-build-schema\": \"./out/zero/src/build-schema.js\",\n \"zero-cache\": \"./out/zero/src/cli.js\",\n \"zero-cache-dev\": \"./out/zero/src/zero-cache-dev.js\",\n \"zero-deploy-permissions\": \"./out/zero/src/deploy-permissions.js\",\n \"zero-out\": \"./out/zero/src/zero-out.js\"\n },\n \"files\": [\n \"out\",\n \"!*.tsbuildinfo\"\n ],\n \"type\": \"module\",\n \"main\": \"out/zero/src/zero.js\",\n \"module\": \"out/zero/src/zero.js\",\n \"types\": \"out/zero/src/zero.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./out/zero/src/zero.d.ts\",\n \"default\": \"./out/zero/src/zero.js\"\n },\n \"./analyze\": {\n \"types\": \"./out/zero/src/analyze.d.ts\",\n \"default\": \"./out/zero/src/analyze.js\"\n },\n \"./bindings\": {\n \"types\": \"./out/zero/src/bindings.d.ts\",\n \"default\": \"./out/zero/src/bindings.js\"\n },\n \"./change-protocol/v0\": {\n \"types\": \"./out/zero/src/change-protocol/v0.d.ts\",\n \"default\": \"./out/zero/src/change-protocol/v0.js\"\n },\n \"./expo-sqlite\": {\n \"types\": \"./out/zero/src/expo-sqlite.d.ts\",\n \"default\": \"./out/zero/src/expo-sqlite.js\"\n },\n \"./op-sqlite\": {\n \"types\": \"./out/zero/src/op-sqlite.d.ts\",\n \"default\": \"./out/zero/src/op-sqlite.js\"\n },\n \"./pg\": {\n \"types\": \"./out/zero/src/pg.d.ts\",\n \"default\": \"./out/zero/src/pg.js\"\n },\n \"./react\": {\n \"types\": \"./out/zero/src/react.d.ts\",\n \"default\": \"./out/zero/src/react.js\"\n },\n \"./react-native\": {\n \"types\": \"./out/zero/src/react-native.d.ts\",\n \"default\": \"./out/zero/src/react-native.js\"\n },\n \"./server\": {\n \"types\": \"./out/zero/src/server.d.ts\",\n \"default\": \"./out/zero/src/server.js\"\n },\n \"./server/adapters/drizzle\": {\n \"types\": \"./out/zero/src/adapters/drizzle.d.ts\",\n \"default\": \"./out/zero/src/adapters/drizzle.js\"\n },\n \"./server/adapters/kysely\": {\n \"types\": \"./out/zero/src/adapters/kysely.d.ts\",\n \"default\": \"./out/zero/src/adapters/kysely.js\"\n },\n \"./server/adapters/prisma\": {\n \"types\": \"./out/zero/src/adapters/prisma.d.ts\",\n \"default\": \"./out/zero/src/adapters/prisma.js\"\n },\n \"./server/adapters/pg\": {\n \"types\": \"./out/zero/src/adapters/pg.d.ts\",\n \"default\": \"./out/zero/src/adapters/pg.js\"\n },\n \"./server/adapters/postgresjs\": {\n \"types\": \"./out/zero/src/adapters/postgresjs.d.ts\",\n \"default\": \"./out/zero/src/adapters/postgresjs.js\"\n },\n \"./solid\": {\n \"types\": \"./out/zero/src/solid.d.ts\",\n \"default\": \"./out/zero/src/solid.js\"\n },\n \"./sqlite\": {\n \"types\": \"./out/zero/src/sqlite.d.ts\",\n \"default\": \"./out/zero/src/sqlite.js\"\n },\n \"./zqlite\": {\n \"types\": \"./out/zero/src/zqlite.d.ts\",\n \"default\": \"./out/zero/src/zqlite.js\"\n }\n },\n \"scripts\": {\n \"build\": \"node --experimental-strip-types --no-warnings tool/build.ts\",\n \"build:watch\": \"node --experimental-strip-types --no-warnings tool/build.ts --watch\",\n \"check-types\": \"tsc -p tsconfig.client.json && tsc -p tsconfig.server.json\",\n \"check-types:client:watch\": \"tsc -p tsconfig.client.json --watch\",\n \"check-types:server:watch\": \"tsc -p tsconfig.server.json --watch\",\n \"format\": \"oxfmt .\",\n \"check-format\": \"oxfmt --check .\",\n \"lint\": \"oxlint --quiet --config ../../oxlint.config.ts src/\",\n \"docs\": \"node --experimental-strip-types --no-warnings tool/generate-docs.ts\",\n \"docs:server\": \"node --watch --experimental-strip-types --no-warnings tool/generate-docs.ts --server\",\n \"fmt\": \"oxfmt .\",\n \"check-fmt\": \"oxfmt --check .\"\n },\n \"dependencies\": {\n \"@badrap/valita\": \"0.3.11\",\n \"@databases/escape-identifier\": \"^1.0.3\",\n \"@databases/sql\": \"^3.3.0\",\n \"@dotenvx/dotenvx\": \"^1.39.0\",\n \"@drdgvhbh/postgres-error-codes\": \"^0.0.6\",\n \"@fastify/cors\": \"^10.0.0\",\n \"@fastify/websocket\": \"^11.0.0\",\n \"@google-cloud/precise-date\": \"^4.0.0\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/api-logs\": \"^0.218.0\",\n \"@opentelemetry/auto-instrumentations-node\": \"^0.76.0\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"^0.218.0\",\n \"@opentelemetry/resources\": \"^2.7.1\",\n \"@opentelemetry/sdk-metrics\": \"^2.7.1\",\n \"@opentelemetry/sdk-node\": \"^0.218.0\",\n \"@opentelemetry/sdk-trace-node\": \"^2.7.1\",\n \"@opentelemetry/semantic-conventions\": \"^1.41.1\",\n \"@postgresql-typed/oids\": \"^0.2.0\",\n \"@rocicorp/lock\": \"^1.0.4\",\n \"@rocicorp/logger\": \"^6.1.0\",\n \"@rocicorp/resolver\": \"^1.0.2\",\n \"@rocicorp/zero-sqlite3\": \"^1.1.4\",\n \"@standard-schema/spec\": \"^1.0.0\",\n \"@types/basic-auth\": \"^1.1.8\",\n \"@types/ws\": \"^8.5.12\",\n \"basic-auth\": \"^2.0.1\",\n \"chalk-template\": \"^1.1.0\",\n \"chokidar\": \"^4.0.1\",\n \"cloudevents\": \"^10.0.0\",\n \"command-line-args\": \"^6.0.1\",\n \"command-line-usage\": \"^7.0.3\",\n \"compare-utf8\": \"^0.2.0\",\n \"defu\": \"^6.1.4\",\n \"eventemitter3\": \"^5.0.1\",\n \"fastify\": \"^5.0.0\",\n \"is-in-subnet\": \"^4.0.1\",\n \"jose\": \"^5.9.3\",\n \"js-xxhash\": \"^4.0.0\",\n \"json-custom-numbers\": \"^3.1.1\",\n \"kasi\": \"^1.1.0\",\n \"nanoid\": \"^5.1.2\",\n \"oxfmt\": \"^0.45.0\",\n \"parse-prometheus-text-format\": \"^1.1.1\",\n \"pg-format\": \"npm:pg-format-fix@^1.0.5\",\n \"postgres\": \"3.4.7\",\n \"semver\": \"^7.5.4\",\n \"url-pattern\": \"^1.0.3\",\n \"urlpattern-polyfill\": \"^10.1.0\",\n \"ws\": \"^8.18.1\"\n },\n \"devDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"@vitest/runner\": \"^4.1.6\",\n \"analyze-query\": \"workspace:*\",\n \"ast-to-zql\": \"workspace:*\",\n \"expo-sqlite\": \">=15\",\n \"oxc-parser\": \"^0.129.0\",\n \"replicache\": \"workspace:*\",\n \"shared\": \"workspace:*\",\n \"syncpack\": \"^14.3.0\",\n \"typedoc\": \"^0.28.17\",\n \"typedoc-plugin-markdown\": \"^4.10.0\",\n \"typescript\": \"~6.0.2\",\n \"vite\": \"^8.0.13\",\n \"vitest\": \"^4.1.6\",\n \"zero-cache\": \"workspace:*\",\n \"zero-client\": \"workspace:*\",\n \"zero-pg\": \"workspace:*\",\n \"zero-react\": \"workspace:*\",\n \"zero-server\": \"workspace:*\",\n \"zero-solid\": \"workspace:*\",\n \"zqlite\": \"workspace:*\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"packageManager\": \"pnpm@11.11.0\"\n}\n"],"mappings":""}
1
+ {"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.10.0-canary.15\",\n \"description\": \"Zero is a web framework for serverless web development.\",\n \"homepage\": \"https://zero.rocicorp.dev\",\n \"bugs\": {\n \"url\": \"https://bugs.rocicorp.dev\"\n },\n \"license\": \"Apache-2.0\",\n \"author\": \"Rocicorp, Inc.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/rocicorp/mono.git\",\n \"directory\": \"packages/zero\"\n },\n \"bin\": {\n \"analyze-query\": \"./out/zero/src/analyze-query.js\",\n \"ast-to-zql\": \"./out/zero/src/ast-to-zql.js\",\n \"transform-query\": \"./out/zero/src/transform-query.js\",\n \"zero-build-schema\": \"./out/zero/src/build-schema.js\",\n \"zero-cache\": \"./out/zero/src/cli.js\",\n \"zero-cache-dev\": \"./out/zero/src/zero-cache-dev.js\",\n \"zero-deploy-permissions\": \"./out/zero/src/deploy-permissions.js\",\n \"zero-out\": \"./out/zero/src/zero-out.js\"\n },\n \"files\": [\n \"out\",\n \"!*.tsbuildinfo\"\n ],\n \"type\": \"module\",\n \"main\": \"out/zero/src/zero.js\",\n \"module\": \"out/zero/src/zero.js\",\n \"types\": \"out/zero/src/zero.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./out/zero/src/zero.d.ts\",\n \"default\": \"./out/zero/src/zero.js\"\n },\n \"./analyze\": {\n \"types\": \"./out/zero/src/analyze.d.ts\",\n \"default\": \"./out/zero/src/analyze.js\"\n },\n \"./bindings\": {\n \"types\": \"./out/zero/src/bindings.d.ts\",\n \"default\": \"./out/zero/src/bindings.js\"\n },\n \"./change-protocol/v0\": {\n \"types\": \"./out/zero/src/change-protocol/v0.d.ts\",\n \"default\": \"./out/zero/src/change-protocol/v0.js\"\n },\n \"./expo-sqlite\": {\n \"types\": \"./out/zero/src/expo-sqlite.d.ts\",\n \"default\": \"./out/zero/src/expo-sqlite.js\"\n },\n \"./op-sqlite\": {\n \"types\": \"./out/zero/src/op-sqlite.d.ts\",\n \"default\": \"./out/zero/src/op-sqlite.js\"\n },\n \"./pg\": {\n \"types\": \"./out/zero/src/pg.d.ts\",\n \"default\": \"./out/zero/src/pg.js\"\n },\n \"./react\": {\n \"types\": \"./out/zero/src/react.d.ts\",\n \"default\": \"./out/zero/src/react.js\"\n },\n \"./react-native\": {\n \"types\": \"./out/zero/src/react-native.d.ts\",\n \"default\": \"./out/zero/src/react-native.js\"\n },\n \"./server\": {\n \"types\": \"./out/zero/src/server.d.ts\",\n \"default\": \"./out/zero/src/server.js\"\n },\n \"./server/adapters/drizzle\": {\n \"types\": \"./out/zero/src/adapters/drizzle.d.ts\",\n \"default\": \"./out/zero/src/adapters/drizzle.js\"\n },\n \"./server/adapters/kysely\": {\n \"types\": \"./out/zero/src/adapters/kysely.d.ts\",\n \"default\": \"./out/zero/src/adapters/kysely.js\"\n },\n \"./server/adapters/prisma\": {\n \"types\": \"./out/zero/src/adapters/prisma.d.ts\",\n \"default\": \"./out/zero/src/adapters/prisma.js\"\n },\n \"./server/adapters/pg\": {\n \"types\": \"./out/zero/src/adapters/pg.d.ts\",\n \"default\": \"./out/zero/src/adapters/pg.js\"\n },\n \"./server/adapters/postgresjs\": {\n \"types\": \"./out/zero/src/adapters/postgresjs.d.ts\",\n \"default\": \"./out/zero/src/adapters/postgresjs.js\"\n },\n \"./solid\": {\n \"types\": \"./out/zero/src/solid.d.ts\",\n \"default\": \"./out/zero/src/solid.js\"\n },\n \"./sqlite\": {\n \"types\": \"./out/zero/src/sqlite.d.ts\",\n \"default\": \"./out/zero/src/sqlite.js\"\n },\n \"./zqlite\": {\n \"types\": \"./out/zero/src/zqlite.d.ts\",\n \"default\": \"./out/zero/src/zqlite.js\"\n }\n },\n \"scripts\": {\n \"build\": \"node --experimental-strip-types --no-warnings tool/build.ts\",\n \"build:watch\": \"node --experimental-strip-types --no-warnings tool/build.ts --watch\",\n \"check-types\": \"tsc -p tsconfig.client.json && tsc -p tsconfig.server.json\",\n \"check-types:client:watch\": \"tsc -p tsconfig.client.json --watch\",\n \"check-types:server:watch\": \"tsc -p tsconfig.server.json --watch\",\n \"format\": \"oxfmt .\",\n \"check-format\": \"oxfmt --check .\",\n \"lint\": \"oxlint --quiet --config ../../oxlint.config.ts src/\",\n \"docs\": \"node --experimental-strip-types --no-warnings tool/generate-docs.ts\",\n \"docs:server\": \"node --watch --experimental-strip-types --no-warnings tool/generate-docs.ts --server\",\n \"fmt\": \"oxfmt .\",\n \"check-fmt\": \"oxfmt --check .\"\n },\n \"dependencies\": {\n \"@badrap/valita\": \"0.3.11\",\n \"@databases/escape-identifier\": \"^1.0.3\",\n \"@databases/sql\": \"^3.3.0\",\n \"@dotenvx/dotenvx\": \"^1.39.0\",\n \"@drdgvhbh/postgres-error-codes\": \"^0.0.6\",\n \"@fastify/cors\": \"^10.0.0\",\n \"@fastify/websocket\": \"^11.0.0\",\n \"@google-cloud/precise-date\": \"^4.0.0\",\n \"@opentelemetry/api\": \"^1.9.0\",\n \"@opentelemetry/api-logs\": \"^0.218.0\",\n \"@opentelemetry/auto-instrumentations-node\": \"^0.76.0\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"^0.218.0\",\n \"@opentelemetry/resources\": \"^2.7.1\",\n \"@opentelemetry/sdk-metrics\": \"^2.7.1\",\n \"@opentelemetry/sdk-node\": \"^0.218.0\",\n \"@opentelemetry/sdk-trace-node\": \"^2.7.1\",\n \"@opentelemetry/semantic-conventions\": \"^1.41.1\",\n \"@postgresql-typed/oids\": \"^0.2.0\",\n \"@rocicorp/lock\": \"^1.0.4\",\n \"@rocicorp/logger\": \"^6.1.0\",\n \"@rocicorp/resolver\": \"^1.0.2\",\n \"@rocicorp/zero-sqlite3\": \"^1.1.4\",\n \"@standard-schema/spec\": \"^1.0.0\",\n \"@types/basic-auth\": \"^1.1.8\",\n \"@types/ws\": \"^8.5.12\",\n \"basic-auth\": \"^2.0.1\",\n \"chalk-template\": \"^1.1.0\",\n \"chokidar\": \"^4.0.1\",\n \"cloudevents\": \"^10.0.0\",\n \"command-line-args\": \"^6.0.1\",\n \"command-line-usage\": \"^7.0.3\",\n \"compare-utf8\": \"^0.2.0\",\n \"defu\": \"^6.1.4\",\n \"eventemitter3\": \"^5.0.1\",\n \"fastify\": \"^5.0.0\",\n \"is-in-subnet\": \"^4.0.1\",\n \"jose\": \"^5.9.3\",\n \"js-xxhash\": \"^4.0.0\",\n \"json-custom-numbers\": \"^3.1.1\",\n \"kasi\": \"^1.1.0\",\n \"nanoid\": \"^5.1.2\",\n \"oxfmt\": \"^0.45.0\",\n \"parse-prometheus-text-format\": \"^1.1.1\",\n \"pg-format\": \"npm:pg-format-fix@^1.0.5\",\n \"postgres\": \"3.4.7\",\n \"semver\": \"^7.5.4\",\n \"url-pattern\": \"^1.0.3\",\n \"urlpattern-polyfill\": \"^10.1.0\",\n \"ws\": \"^8.18.1\"\n },\n \"devDependencies\": {\n \"@op-engineering/op-sqlite\": \">=15\",\n \"@vitest/runner\": \"^4.1.6\",\n \"analyze-query\": \"workspace:*\",\n \"ast-to-zql\": \"workspace:*\",\n \"expo-sqlite\": \">=15\",\n \"oxc-parser\": \"^0.129.0\",\n \"replicache\": \"workspace:*\",\n \"shared\": \"workspace:*\",\n \"syncpack\": \"^14.3.0\",\n \"typedoc\": \"^0.28.17\",\n \"typedoc-plugin-markdown\": \"^4.10.0\",\n \"typescript\": \"~6.0.2\",\n \"vite\": \"^8.0.13\",\n \"vitest\": \"^4.1.6\",\n \"zero-cache\": \"workspace:*\",\n \"zero-client\": \"workspace:*\",\n \"zero-pg\": \"workspace:*\",\n \"zero-react\": \"workspace:*\",\n \"zero-server\": \"workspace:*\",\n \"zero-solid\": \"workspace:*\",\n \"zqlite\": \"workspace:*\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"packageManager\": \"pnpm@11.11.0\"\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/db/create.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,UAAU,EAAE,aAAa,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;AAEzE;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,UAe7C;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAUpE;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAQrE"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/db/create.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAE,aAAa,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;AAEzE;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,UAe7C;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAUpE;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAerE"}
@@ -1,5 +1,6 @@
1
1
  import { assertValidLiteColumnSpec } from "../types/lite.js";
2
2
  import { id, idList } from "../types/sql.js";
3
+ import { liteIndexPredicateSQL } from "./index-predicate.js";
3
4
  //#region ../zero-cache/src/db/create.ts
4
5
  /**
5
6
  * `spec` always comes from `mapPostgresToLiteColumn` so we only need to support
@@ -27,7 +28,9 @@ function createLiteTableStatement(spec) {
27
28
  }
28
29
  function createLiteIndexStatement(index) {
29
30
  const columns = Object.entries(index.columns).map(([name, dir]) => `${id(name)} ${dir}`).join(",");
30
- return `CREATE ${index.unique ? "UNIQUE" : ""} INDEX ${id(index.name)} ON ${id(index.tableName)} (${columns});`;
31
+ const unique = index.unique && !index.predicate ? "UNIQUE" : "";
32
+ const predicate = index.predicate ? ` WHERE ${liteIndexPredicateSQL(index.predicate)}` : "";
33
+ return `CREATE ${unique} INDEX ${id(index.name)} ON ${id(index.tableName)} (${columns})${predicate};`;
31
34
  }
32
35
  //#endregion
33
36
  export { createLiteIndexStatement, createLiteTableStatement, liteColumnDef };
@@ -1 +1 @@
1
- {"version":3,"file":"create.js","names":[],"sources":["../../../../../zero-cache/src/db/create.ts"],"sourcesContent":["import {assertValidLiteColumnSpec} from '../types/lite.ts';\nimport {id, idList} from '../types/sql.ts';\nimport type {ColumnSpec, LiteIndexSpec, LiteTableSpec} from './specs.ts';\n\n/**\n * `spec` always comes from `mapPostgresToLiteColumn` so we only need to support\n * the output of that function.\n */\nexport function liteColumnDef(spec: ColumnSpec) {\n assertValidLiteColumnSpec(spec);\n\n let def = id(spec.dataType);\n\n if (spec.characterMaximumLength) {\n def += `(${spec.characterMaximumLength})`;\n }\n if (spec.notNull) {\n def += ' NOT NULL';\n }\n if (spec.dflt) {\n def += ` DEFAULT ${spec.dflt}`;\n }\n return def;\n}\n\n/**\n * Constructs a `CREATE TABLE` statement for a {@link TableSpec}.\n */\nexport function createLiteTableStatement(spec: LiteTableSpec): string {\n const defs = Object.entries(spec.columns)\n .sort(([_a, {pos: a}], [_b, {pos: b}]) => a - b)\n .map(([name, columnSpec]) => `${id(name)} ${liteColumnDef(columnSpec)}`);\n if (spec.primaryKey) {\n defs.push(`PRIMARY KEY (${idList(spec.primaryKey)})`);\n }\n\n const createStmt = `CREATE TABLE ${id(spec.name)} (`;\n return [createStmt, defs.join(',\\n'), ');'].join('\\n');\n}\n\nexport function createLiteIndexStatement(index: LiteIndexSpec): string {\n const columns = Object.entries(index.columns)\n .map(([name, dir]) => `${id(name)} ${dir}`)\n .join(',');\n const unique = index.unique ? 'UNIQUE' : '';\n return `CREATE ${unique} INDEX ${id(index.name)} ON ${id(\n index.tableName,\n )} (${columns});`;\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,cAAc,MAAkB;CAC9C,0BAA0B,IAAI;CAE9B,IAAI,MAAM,GAAG,KAAK,QAAQ;CAE1B,IAAI,KAAK,wBACP,OAAO,IAAI,KAAK,uBAAuB;CAEzC,IAAI,KAAK,SACP,OAAO;CAET,IAAI,KAAK,MACP,OAAO,YAAY,KAAK;CAE1B,OAAO;AACT;;;;AAKA,SAAgB,yBAAyB,MAA6B;CACpE,MAAM,OAAO,OAAO,QAAQ,KAAK,OAAO,EACrC,MAAM,CAAC,IAAI,EAAC,KAAK,MAAK,CAAC,IAAI,EAAC,KAAK,SAAQ,IAAI,CAAC,EAC9C,KAAK,CAAC,MAAM,gBAAgB,GAAG,GAAG,IAAI,EAAE,GAAG,cAAc,UAAU,GAAG;CACzE,IAAI,KAAK,YACP,KAAK,KAAK,gBAAgB,OAAO,KAAK,UAAU,EAAE,EAAE;CAItD,OAAO;EAAC,gBAD2B,GAAG,KAAK,IAAI,EAAE;EAC7B,KAAK,KAAK,KAAK;EAAG;CAAI,EAAE,KAAK,IAAI;AACvD;AAEA,SAAgB,yBAAyB,OAA8B;CACrE,MAAM,UAAU,OAAO,QAAQ,MAAM,OAAO,EACzC,KAAK,CAAC,MAAM,SAAS,GAAG,GAAG,IAAI,EAAE,GAAG,KAAK,EACzC,KAAK,GAAG;CAEX,OAAO,UADQ,MAAM,SAAS,WAAW,GACjB,SAAS,GAAG,MAAM,IAAI,EAAE,MAAM,GACpD,MAAM,SACR,EAAE,IAAI,QAAQ;AAChB"}
1
+ {"version":3,"file":"create.js","names":[],"sources":["../../../../../zero-cache/src/db/create.ts"],"sourcesContent":["import {assertValidLiteColumnSpec} from '../types/lite.ts';\nimport {id, idList} from '../types/sql.ts';\nimport {liteIndexPredicateSQL} from './index-predicate.ts';\nimport type {ColumnSpec, LiteIndexSpec, LiteTableSpec} from './specs.ts';\n\n/**\n * `spec` always comes from `mapPostgresToLiteColumn` so we only need to support\n * the output of that function.\n */\nexport function liteColumnDef(spec: ColumnSpec) {\n assertValidLiteColumnSpec(spec);\n\n let def = id(spec.dataType);\n\n if (spec.characterMaximumLength) {\n def += `(${spec.characterMaximumLength})`;\n }\n if (spec.notNull) {\n def += ' NOT NULL';\n }\n if (spec.dflt) {\n def += ` DEFAULT ${spec.dflt}`;\n }\n return def;\n}\n\n/**\n * Constructs a `CREATE TABLE` statement for a {@link TableSpec}.\n */\nexport function createLiteTableStatement(spec: LiteTableSpec): string {\n const defs = Object.entries(spec.columns)\n .sort(([_a, {pos: a}], [_b, {pos: b}]) => a - b)\n .map(([name, columnSpec]) => `${id(name)} ${liteColumnDef(columnSpec)}`);\n if (spec.primaryKey) {\n defs.push(`PRIMARY KEY (${idList(spec.primaryKey)})`);\n }\n\n const createStmt = `CREATE TABLE ${id(spec.name)} (`;\n return [createStmt, defs.join(',\\n'), ');'].join('\\n');\n}\n\nexport function createLiteIndexStatement(index: LiteIndexSpec): string {\n const columns = Object.entries(index.columns)\n .map(([name, dir]) => `${id(name)} ${dir}`)\n .join(',');\n // Partial indexes are never unique on the replica. Their uniqueness is\n // not needed (a partial index cannot serve as a row key), and a UNIQUE\n // partial index would turn any divergence between PostgreSQL's and\n // SQLite's evaluation of the predicate into a replication failure.\n const unique = index.unique && !index.predicate ? 'UNIQUE' : '';\n const predicate = index.predicate\n ? ` WHERE ${liteIndexPredicateSQL(index.predicate)}`\n : '';\n return `CREATE ${unique} INDEX ${id(index.name)} ON ${id(\n index.tableName,\n )} (${columns})${predicate};`;\n}\n"],"mappings":";;;;;;;;AASA,SAAgB,cAAc,MAAkB;CAC9C,0BAA0B,IAAI;CAE9B,IAAI,MAAM,GAAG,KAAK,QAAQ;CAE1B,IAAI,KAAK,wBACP,OAAO,IAAI,KAAK,uBAAuB;CAEzC,IAAI,KAAK,SACP,OAAO;CAET,IAAI,KAAK,MACP,OAAO,YAAY,KAAK;CAE1B,OAAO;AACT;;;;AAKA,SAAgB,yBAAyB,MAA6B;CACpE,MAAM,OAAO,OAAO,QAAQ,KAAK,OAAO,EACrC,MAAM,CAAC,IAAI,EAAC,KAAK,MAAK,CAAC,IAAI,EAAC,KAAK,SAAQ,IAAI,CAAC,EAC9C,KAAK,CAAC,MAAM,gBAAgB,GAAG,GAAG,IAAI,EAAE,GAAG,cAAc,UAAU,GAAG;CACzE,IAAI,KAAK,YACP,KAAK,KAAK,gBAAgB,OAAO,KAAK,UAAU,EAAE,EAAE;CAItD,OAAO;EAAC,gBAD2B,GAAG,KAAK,IAAI,EAAE;EAC7B,KAAK,KAAK,KAAK;EAAG;CAAI,EAAE,KAAK,IAAI;AACvD;AAEA,SAAgB,yBAAyB,OAA8B;CACrE,MAAM,UAAU,OAAO,QAAQ,MAAM,OAAO,EACzC,KAAK,CAAC,MAAM,SAAS,GAAG,GAAG,IAAI,EAAE,GAAG,KAAK,EACzC,KAAK,GAAG;CAKX,MAAM,SAAS,MAAM,UAAU,CAAC,MAAM,YAAY,WAAW;CAC7D,MAAM,YAAY,MAAM,YACpB,UAAU,sBAAsB,MAAM,SAAS,MAC/C;CACJ,OAAO,UAAU,OAAO,SAAS,GAAG,MAAM,IAAI,EAAE,MAAM,GACpD,MAAM,SACR,EAAE,IAAI,QAAQ,GAAG,UAAU;AAC7B"}
@@ -0,0 +1,4 @@
1
+ import type { IndexPredicate } from './specs.ts';
2
+ export declare function liteIndexPredicateSQL(predicate: IndexPredicate): string;
3
+ export declare function mapIndexPredicateColumns(predicate: IndexPredicate, map: (column: string) => string): IndexPredicate;
4
+ //# sourceMappingURL=index-predicate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-predicate.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/db/index-predicate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,cAAc,EAAsB,MAAM,YAAY,CAAC;AAIpE,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,CAiBvE;AAkBD,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,cAAc,EACzB,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,GAC9B,cAAc,CAmBhB"}
@@ -0,0 +1,46 @@
1
+ import { assert } from "../../../shared/src/asserts.js";
2
+ import { id, lit } from "../types/sql.js";
3
+ //#region ../zero-cache/src/db/index-predicate.ts
4
+ var CANONICAL_INTEGER_RE = /^-?(?:0|[1-9]\d*)$/;
5
+ function liteIndexPredicateSQL(predicate) {
6
+ switch (predicate.type) {
7
+ case "and":
8
+ case "or":
9
+ assert(predicate.conditions.length > 0, "empty index predicate");
10
+ return `(${predicate.conditions.map(liteIndexPredicateSQL).join(` ${predicate.type.toUpperCase()} `)})`;
11
+ case "not": return `(NOT ${liteIndexPredicateSQL(predicate.condition)})`;
12
+ case "null-test": return `${id(predicate.column)} ${predicate.op}`;
13
+ case "comparison": return `${id(predicate.column)} ${predicate.op} ${predicateValueSQL(predicate.value)}`;
14
+ }
15
+ }
16
+ function predicateValueSQL(value) {
17
+ switch (value.type) {
18
+ case "boolean": return value.value ? "1" : "0";
19
+ case "integer":
20
+ assert(CANONICAL_INTEGER_RE.test(value.value), "invalid integer predicate");
21
+ return value.value;
22
+ case "string": return lit(value.value);
23
+ }
24
+ }
25
+ function mapIndexPredicateColumns(predicate, map) {
26
+ switch (predicate.type) {
27
+ case "and":
28
+ case "or": return {
29
+ ...predicate,
30
+ conditions: predicate.conditions.map((condition) => mapIndexPredicateColumns(condition, map))
31
+ };
32
+ case "not": return {
33
+ ...predicate,
34
+ condition: mapIndexPredicateColumns(predicate.condition, map)
35
+ };
36
+ case "null-test":
37
+ case "comparison": return {
38
+ ...predicate,
39
+ column: map(predicate.column)
40
+ };
41
+ }
42
+ }
43
+ //#endregion
44
+ export { liteIndexPredicateSQL, mapIndexPredicateColumns };
45
+
46
+ //# sourceMappingURL=index-predicate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-predicate.js","names":[],"sources":["../../../../../zero-cache/src/db/index-predicate.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport {id, lit} from '../types/sql.ts';\nimport type {IndexPredicate, IndexPredicateValue} from './specs.ts';\n\nconst CANONICAL_INTEGER_RE = /^-?(?:0|[1-9]\\d*)$/;\n\nexport function liteIndexPredicateSQL(predicate: IndexPredicate): string {\n switch (predicate.type) {\n case 'and':\n case 'or':\n assert(predicate.conditions.length > 0, 'empty index predicate');\n return `(${predicate.conditions\n .map(liteIndexPredicateSQL)\n .join(` ${predicate.type.toUpperCase()} `)})`;\n case 'not':\n return `(NOT ${liteIndexPredicateSQL(predicate.condition)})`;\n case 'null-test':\n return `${id(predicate.column)} ${predicate.op}`;\n case 'comparison':\n return `${id(predicate.column)} ${predicate.op} ${predicateValueSQL(\n predicate.value,\n )}`;\n }\n}\n\nfunction predicateValueSQL(value: IndexPredicateValue): string {\n switch (value.type) {\n case 'boolean':\n return value.value ? '1' : '0';\n case 'integer':\n // The PostgreSQL translator only constructs canonical decimal integers.\n assert(\n CANONICAL_INTEGER_RE.test(value.value),\n 'invalid integer predicate',\n );\n return value.value;\n case 'string':\n return lit(value.value);\n }\n}\n\nexport function mapIndexPredicateColumns(\n predicate: IndexPredicate,\n map: (column: string) => string,\n): IndexPredicate {\n switch (predicate.type) {\n case 'and':\n case 'or':\n return {\n ...predicate,\n conditions: predicate.conditions.map(condition =>\n mapIndexPredicateColumns(condition, map),\n ),\n };\n case 'not':\n return {\n ...predicate,\n condition: mapIndexPredicateColumns(predicate.condition, map),\n };\n case 'null-test':\n case 'comparison':\n return {...predicate, column: map(predicate.column)};\n }\n}\n"],"mappings":";;;AAIA,IAAM,uBAAuB;AAE7B,SAAgB,sBAAsB,WAAmC;CACvE,QAAQ,UAAU,MAAlB;EACE,KAAK;EACL,KAAK;GACH,OAAO,UAAU,WAAW,SAAS,GAAG,uBAAuB;GAC/D,OAAO,IAAI,UAAU,WAClB,IAAI,qBAAqB,EACzB,KAAK,IAAI,UAAU,KAAK,YAAY,EAAE,EAAE,EAAE;EAC/C,KAAK,OACH,OAAO,QAAQ,sBAAsB,UAAU,SAAS,EAAE;EAC5D,KAAK,aACH,OAAO,GAAG,GAAG,UAAU,MAAM,EAAE,GAAG,UAAU;EAC9C,KAAK,cACH,OAAO,GAAG,GAAG,UAAU,MAAM,EAAE,GAAG,UAAU,GAAG,GAAG,kBAChD,UAAU,KACZ;CACJ;AACF;AAEA,SAAS,kBAAkB,OAAoC;CAC7D,QAAQ,MAAM,MAAd;EACE,KAAK,WACH,OAAO,MAAM,QAAQ,MAAM;EAC7B,KAAK;GAEH,OACE,qBAAqB,KAAK,MAAM,KAAK,GACrC,2BACF;GACA,OAAO,MAAM;EACf,KAAK,UACH,OAAO,IAAI,MAAM,KAAK;CAC1B;AACF;AAEA,SAAgB,yBACd,WACA,KACgB;CAChB,QAAQ,UAAU,MAAlB;EACE,KAAK;EACL,KAAK,MACH,OAAO;GACL,GAAG;GACH,YAAY,UAAU,WAAW,KAAI,cACnC,yBAAyB,WAAW,GAAG,CACzC;EACF;EACF,KAAK,OACH,OAAO;GACL,GAAG;GACH,WAAW,yBAAyB,UAAU,WAAW,GAAG;EAC9D;EACF,KAAK;EACL,KAAK,cACH,OAAO;GAAC,GAAG;GAAW,QAAQ,IAAI,UAAU,MAAM;EAAC;CACvD;AACF"}
@@ -6,7 +6,15 @@ export type LiteTableSpecWithReplicationStatus = LiteTableSpec & {
6
6
  readonly minRowVersion?: string | null;
7
7
  };
8
8
  export declare function listTables(db: Database, useColumnMetadata?: boolean, useTableMetadata?: boolean): LiteTableSpecWithReplicationStatus[];
9
- export declare function listIndexes(db: Database): LiteIndexSpec[];
9
+ /**
10
+ * An index as it exists on the replica. SQLite retains only the DDL text of a
11
+ * partial index, not a structured predicate, so replica indexes report a
12
+ * `partial` flag in place of the {@link LiteIndexSpec.predicate}.
13
+ */
14
+ export type ReplicaIndexSpec = Omit<LiteIndexSpec, 'predicate'> & {
15
+ readonly partial?: boolean | undefined;
16
+ };
17
+ export declare function listIndexes(db: Database): ReplicaIndexSpec[];
10
18
  export type ZqlSpecOptions = {
11
19
  /**
12
20
  * Controls whether to include backfilling columns in the computed
@@ -33,6 +41,6 @@ export type ZqlSpecOptions = {
33
41
  * data types.
34
42
  */
35
43
  export declare function computeZqlSpecs(lc: LogContext, replica: Database, opts: ZqlSpecOptions, tableSpecs?: Map<string, LiteAndZqlSpec>, fullTables?: Map<string, LiteTableSpec>): Map<string, LiteAndZqlSpec>;
36
- export declare function computeZqlSpecsFromLiteSpecs(tables: LiteTableSpecWithReplicationStatus[], indexes: LiteIndexSpec[], { includeBackfillingColumns }: ZqlSpecOptions, tableSpecs?: Map<string, LiteAndZqlSpec>, fullTables?: Map<string, LiteTableSpec>, lc?: LogContext): Map<string, LiteAndZqlSpec>;
44
+ export declare function computeZqlSpecsFromLiteSpecs(tables: LiteTableSpecWithReplicationStatus[], indexes: readonly (LiteIndexSpec | ReplicaIndexSpec)[], { includeBackfillingColumns }: ZqlSpecOptions, tableSpecs?: Map<string, LiteAndZqlSpec>, fullTables?: Map<string, LiteTableSpec>, lc?: LogContext): Map<string, LiteAndZqlSpec>;
37
45
  export declare function mustGetTableSpec(tableSpecs: Map<string, LiteAndZqlSpec>, tableName: string): LiteAndZqlSpec;
38
46
  //# sourceMappingURL=lite-tables.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lite-tables.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/db/lite-tables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAKjD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAC;AAcxD,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EAGd,MAAM,YAAY,CAAC;AAWpB,MAAM,MAAM,kCAAkC,GAAG,aAAa,GAAG;IAC/D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC,CAAC;AAOF,wBAAgB,UAAU,CACxB,EAAE,EAAE,QAAQ,EACZ,iBAAiB,UAAO,EACxB,gBAAgB,UAAO,GACtB,kCAAkC,EAAE,CAwFtC;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,GAAG,aAAa,EAAE,CAyCzD;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;;;OAMG;IACH,yBAAyB,EAAE,OAAO,CAAC;CACpC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,UAAU,EACd,OAAO,EAAE,QAAQ,EACjB,IAAI,EAAE,cAAc,EACpB,UAAU,GAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAa,EACnD,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GACtC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAS7B;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,kCAAkC,EAAE,EAC5C,OAAO,EAAE,aAAa,EAAE,EACxB,EAAC,yBAAyB,EAAC,EAAE,cAAc,EAC3C,UAAU,GAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAa,EACnD,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EACvC,EAAE,CAAC,EAAE,UAAU,GACd,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CA0E7B;AAED,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EACvC,SAAS,EAAE,MAAM,GAChB,cAAc,CAWhB"}
1
+ {"version":3,"file":"lite-tables.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/db/lite-tables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAKjD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,2BAA2B,CAAC;AAcxD,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EAGd,MAAM,YAAY,CAAC;AAWpB,MAAM,MAAM,kCAAkC,GAAG,aAAa,GAAG;IAC/D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC,CAAC;AAOF,wBAAgB,UAAU,CACxB,EAAE,EAAE,QAAQ,EACZ,iBAAiB,UAAO,EACxB,gBAAgB,UAAO,GACtB,kCAAkC,EAAE,CAwFtC;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,GAAG;IAChE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACxC,CAAC;AAMF,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,GAAG,gBAAgB,EAAE,CAmD5D;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;;;OAMG;IACH,yBAAyB,EAAE,OAAO,CAAC;CACpC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,UAAU,EACd,OAAO,EAAE,QAAQ,EACjB,IAAI,EAAE,cAAc,EACpB,UAAU,GAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAa,EACnD,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GACtC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAS7B;AASD,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,kCAAkC,EAAE,EAC5C,OAAO,EAAE,SAAS,CAAC,aAAa,GAAG,gBAAgB,CAAC,EAAE,EACtD,EAAC,yBAAyB,EAAC,EAAE,cAAc,EAC3C,UAAU,GAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAa,EACnD,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EACvC,EAAE,CAAC,EAAE,UAAU,GACd,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CA8E7B;AAED,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EACvC,SAAS,EAAE,MAAM,GAChB,cAAc,CAWhB"}
@@ -67,6 +67,7 @@ function listIndexes(db) {
67
67
  idx.name as indexName,
68
68
  idx.tbl_name as tableName,
69
69
  info."unique" as "unique",
70
+ info.partial as partial,
70
71
  col.name as column,
71
72
  CASE WHEN col.desc = 0 THEN 'ASC' ELSE 'DESC' END as dir
72
73
  FROM sqlite_master as idx
@@ -77,12 +78,13 @@ function listIndexes(db) {
77
78
  idx.tbl_name NOT LIKE '_zero.%'
78
79
  ORDER BY idx.name, col.seqno ASC`).all();
79
80
  const ret = [];
80
- for (const { indexName: name, tableName, unique, column, dir } of indexes) if (ret.at(-1)?.name === name) must(ret.at(-1)).columns[column] = dir;
81
+ for (const { indexName: name, tableName, unique, partial, column, dir } of indexes) if (ret.at(-1)?.name === name) must(ret.at(-1)).columns[column] = dir;
81
82
  else ret.push({
82
83
  tableName,
83
84
  name,
84
85
  columns: { [column]: dir },
85
- unique: unique !== 0
86
+ unique: unique !== 0,
87
+ ...partial === 0 ? {} : { partial: true }
86
88
  });
87
89
  return ret;
88
90
  }
@@ -104,11 +106,14 @@ function listIndexes(db) {
104
106
  function computeZqlSpecs(lc, replica, opts, tableSpecs = /* @__PURE__ */ new Map(), fullTables) {
105
107
  return computeZqlSpecsFromLiteSpecs(listTables(replica), listIndexes(replica), opts, tableSpecs, fullTables, lc);
106
108
  }
109
+ function isPartialIndex(idx) {
110
+ return "predicate" in idx && idx.predicate !== void 0 || "partial" in idx && idx.partial === true;
111
+ }
107
112
  function computeZqlSpecsFromLiteSpecs(tables, indexes, { includeBackfillingColumns }, tableSpecs = /* @__PURE__ */ new Map(), fullTables, lc) {
108
113
  tableSpecs.clear();
109
114
  fullTables?.clear();
110
115
  const uniqueIndexColumns = /* @__PURE__ */ new Map();
111
- for (const { tableName, columns } of indexes.filter((idx) => idx.unique)) {
116
+ for (const { tableName, columns } of indexes.filter((idx) => idx.unique && !isPartialIndex(idx))) {
112
117
  if (!uniqueIndexColumns.has(tableName)) uniqueIndexColumns.set(tableName, []);
113
118
  uniqueIndexColumns.get(tableName)?.push(Object.keys(columns));
114
119
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lite-tables.js","names":[],"sources":["../../../../../zero-cache/src/db/lite-tables.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {must} from '../../../shared/src/must.ts';\nimport {difference} from '../../../shared/src/set-utils.ts';\nimport * as v from '../../../shared/src/valita.ts';\nimport {primaryKeySchema} from '../../../zero-protocol/src/primary-key.ts';\nimport type {Database} from '../../../zqlite/src/db.ts';\nimport {\n ColumnMetadataStore,\n metadataToLiteTypeString,\n} from '../services/replicator/schema/column-metadata.ts';\nimport {TableMetadataTracker} from '../services/replicator/schema/table-metadata.ts';\nimport {\n isArray,\n isEnum,\n liteTypeToZqlValueType,\n mapLiteDataTypeToZqlSchemaValue,\n nullableUpstream,\n} from '../types/lite.ts';\nimport * as PostgresTypeClass from './postgres-type-class-enum.ts';\nimport type {\n LiteAndZqlSpec,\n LiteIndexSpec,\n LiteTableSpec,\n MutableLiteIndexSpec,\n MutableLiteTableSpec,\n} from './specs.ts';\n\ntype ColumnInfo = {\n table: string;\n name: string;\n type: string;\n notNull: number;\n dflt: string | null;\n keyPos: number;\n};\n\nexport type LiteTableSpecWithReplicationStatus = LiteTableSpec & {\n readonly backfilling?: string[];\n readonly minRowVersion?: string | null;\n};\n\ntype MutableLiteTableSpecWithReplicationStatus = MutableLiteTableSpec & {\n backfilling: string[];\n minRowVersion: string | null;\n};\n\nexport function listTables(\n db: Database,\n useColumnMetadata = true,\n useTableMetadata = true,\n): LiteTableSpecWithReplicationStatus[] {\n const columns = db\n .prepare(\n `\n SELECT\n m.name as \"table\",\n p.name as name,\n p.type as type,\n p.\"notnull\" as \"notNull\",\n p.dflt_value as \"dflt\",\n p.pk as keyPos\n FROM sqlite_master as m\n LEFT JOIN pragma_table_info(m.name) as p\n WHERE m.type = 'table'\n AND m.name NOT LIKE 'sqlite_%'\n AND m.name NOT LIKE '_zero.%'\n AND m.name NOT LIKE '_litestream_%'\n `,\n )\n .all() as ColumnInfo[];\n\n const minRowVersions = useTableMetadata\n ? new TableMetadataTracker(db).getMinRowVersions()\n : new Map();\n const tables: LiteTableSpecWithReplicationStatus[] = [];\n let table: MutableLiteTableSpecWithReplicationStatus | undefined;\n\n columns.forEach(col => {\n if (col.table !== table?.name) {\n // New table\n table = {\n name: col.table,\n columns: {},\n backfilling: [],\n minRowVersion: minRowVersions.get(col.table) ?? null,\n };\n tables.push(table);\n }\n\n // Try to read from metadata table first, fall back to SQLite column type\n let dataType: string;\n let elemPgTypeClass:\n | typeof PostgresTypeClass.Base\n | typeof PostgresTypeClass.Enum\n | null;\n\n const metadata = useColumnMetadata\n ? ColumnMetadataStore.getInstance(db)?.getColumn(col.table, col.name)\n : undefined;\n if (metadata) {\n // Read from metadata table and convert to pipe notation\n dataType = metadataToLiteTypeString(metadata);\n elemPgTypeClass = metadata.isArray\n ? metadata.isEnum\n ? PostgresTypeClass.Enum\n : PostgresTypeClass.Base\n : null;\n } else {\n // Fall back to reading from SQLite column type (pipe notation)\n dataType = col.type;\n elemPgTypeClass = isArray(col.type)\n ? isEnum(col.type)\n ? PostgresTypeClass.Enum\n : PostgresTypeClass.Base\n : null;\n }\n\n table.columns[col.name] = {\n pos: Object.keys(table.columns).length + 1,\n dataType,\n characterMaximumLength: null,\n notNull: col.notNull !== 0,\n dflt: col.dflt,\n elemPgTypeClass,\n };\n if (metadata?.isBackfilling) {\n table.backfilling.push(col.name);\n }\n if (col.keyPos) {\n table.primaryKey ??= [];\n while (table.primaryKey.length < col.keyPos) {\n table.primaryKey.push('');\n }\n table.primaryKey[col.keyPos - 1] = col.name;\n }\n });\n\n return tables;\n}\n\nexport function listIndexes(db: Database): LiteIndexSpec[] {\n const indexes = db\n .prepare(\n `SELECT \n idx.name as indexName, \n idx.tbl_name as tableName, \n info.\"unique\" as \"unique\",\n col.name as column,\n CASE WHEN col.desc = 0 THEN 'ASC' ELSE 'DESC' END as dir\n FROM sqlite_master as idx\n JOIN pragma_index_list(idx.tbl_name) AS info ON info.name = idx.name\n JOIN pragma_index_xinfo(idx.name) as col\n WHERE idx.type = 'index' AND \n col.key = 1 AND\n idx.tbl_name NOT LIKE '_zero.%'\n ORDER BY idx.name, col.seqno ASC`,\n )\n .all() as {\n indexName: string;\n tableName: string;\n unique: number;\n column: string;\n dir: 'ASC' | 'DESC';\n }[];\n\n const ret: MutableLiteIndexSpec[] = [];\n for (const {indexName: name, tableName, unique, column, dir} of indexes) {\n if (ret.at(-1)?.name === name) {\n // Aggregate multiple column names into the array.\n must(ret.at(-1)).columns[column] = dir;\n } else {\n ret.push({\n tableName,\n name,\n columns: {[column]: dir},\n unique: unique !== 0,\n });\n }\n }\n\n return ret;\n}\n\nexport type ZqlSpecOptions = {\n /**\n * Controls whether to include backfilling columns in the computed\n * LiteAndZqlSpec. In general, backfilling columns should be include\n * in \"replication\" logic (copying data from upstream to the replica),\n * and excluded from \"sync\" logic (sending data from the replica to\n * clients).\n */\n includeBackfillingColumns: boolean;\n};\n\n/**\n * Computes a TableSpec \"view\" of the replicated data that is\n * suitable for processing / consumption for the client. This\n * includes:\n * * excluding tables without a PRIMARY KEY or UNIQUE INDEX\n * * excluding columns with types that are not supported by ZQL\n * * choosing columns to use as the primary key amongst those\n * in unique indexes\n *\n * @param tableSpecs an optional map to reset and populate\n * @param fullTables an optional map to receive the full table specs,\n * which may include tables and columns that are not synced to\n * the client because they lack a primary key or are of unsupported\n * data types.\n */\nexport function computeZqlSpecs(\n lc: LogContext,\n replica: Database,\n opts: ZqlSpecOptions,\n tableSpecs: Map<string, LiteAndZqlSpec> = new Map(),\n fullTables?: Map<string, LiteTableSpec>,\n): Map<string, LiteAndZqlSpec> {\n return computeZqlSpecsFromLiteSpecs(\n listTables(replica),\n listIndexes(replica),\n opts,\n tableSpecs,\n fullTables,\n lc,\n );\n}\n\nexport function computeZqlSpecsFromLiteSpecs(\n tables: LiteTableSpecWithReplicationStatus[],\n indexes: LiteIndexSpec[],\n {includeBackfillingColumns}: ZqlSpecOptions,\n tableSpecs: Map<string, LiteAndZqlSpec> = new Map(),\n fullTables?: Map<string, LiteTableSpec>,\n lc?: LogContext,\n): Map<string, LiteAndZqlSpec> {\n tableSpecs.clear();\n fullTables?.clear();\n\n const uniqueIndexColumns = new Map<string, string[][]>();\n for (const {tableName, columns} of indexes.filter(idx => idx.unique)) {\n if (!uniqueIndexColumns.has(tableName)) {\n uniqueIndexColumns.set(tableName, []);\n }\n uniqueIndexColumns.get(tableName)?.push(Object.keys(columns));\n }\n\n tables.forEach(fullTable => {\n fullTables?.set(fullTable.name, fullTable);\n\n const backfilling = new Set(fullTable.backfilling);\n // Only include columns that:\n // - have a defined ZQL Value\n // - aren't backfilling if `includeBackfillingColumns` is false\n const visibleColumns = Object.entries(fullTable.columns).filter(\n ([col, {dataType}]) =>\n liteTypeToZqlValueType(dataType) &&\n (includeBackfillingColumns || !backfilling.has(col)),\n );\n const notNullColumns = new Set(\n visibleColumns\n .filter(\n ([col, {dataType}]) =>\n !nullableUpstream(dataType) || fullTable.primaryKey?.includes(col),\n )\n .map(([col]) => col),\n );\n\n const uniqueKeys = uniqueIndexColumns.get(fullTable.name) ?? [];\n // Examine all column combinations that can serve as a primary key,\n // i.e. excluding indexes over nullable or unsynced columns.\n const keys = uniqueKeys.filter(\n key => difference(new Set(key), notNullColumns).size === 0,\n );\n if (keys.length === 0) {\n // Only include tables with a row key.\n //\n // Note that this will automatically exclude tables that are being\n // backfilled (when includeBackfillingColumns is `false`) since candidate\n // keys only include visible columns.\n lc?.debug?.(\n `not syncing table ${fullTable.name} because it ` +\n (backfilling.size ? 'is being backfilled' : 'has no primary key'),\n );\n return;\n }\n // Pick the \"best\" (i.e. shortest) key for default IVM operations.\n const primaryKey = keys.sort(keyCmp)[0];\n\n const tableSpec = {\n ...fullTable,\n columns: Object.fromEntries(visibleColumns),\n primaryKey: v.parse(primaryKey, primaryKeySchema),\n uniqueKeys: uniqueKeys.map(key => v.parse(key, primaryKeySchema)),\n allPotentialPrimaryKeys: keys.map(key => v.parse(key, primaryKeySchema)),\n minRowVersion: fullTable.minRowVersion ?? null,\n };\n\n tableSpecs.set(tableSpec.name, {\n tableSpec,\n zqlSpec: Object.fromEntries(\n Object.entries(tableSpec.columns).map(([name, {dataType}]) => [\n name,\n mapLiteDataTypeToZqlSchemaValue(dataType),\n ]),\n ),\n });\n });\n return tableSpecs;\n}\n\nexport function mustGetTableSpec(\n tableSpecs: Map<string, LiteAndZqlSpec>,\n tableName: string,\n): LiteAndZqlSpec {\n const tableSpec = tableSpecs.get(tableName);\n if (!tableSpec) {\n throw new Error(\n `table '${tableName}' is not one of: ${[...tableSpecs.keys()]\n .filter(t => !t.includes('.') && !t.startsWith('_litestream_'))\n .sort()}. ` +\n `Check the spelling and ensure that the table has a primary key.`,\n );\n }\n return tableSpec;\n}\n\n// Deterministic comparator for favoring shorter row keys.\nfunction keyCmp(a: string[], b: string[]) {\n if (a.length !== b.length) {\n return a.length - b.length; // Fewer columns are better.\n }\n for (let i = 0; i < a.length; i++) {\n if (a[i] < b[i]) {\n return -1;\n }\n if (a[i] > b[i]) {\n return 1;\n }\n }\n return 0;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"lite-tables.js","names":[],"sources":["../../../../../zero-cache/src/db/lite-tables.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {must} from '../../../shared/src/must.ts';\nimport {difference} from '../../../shared/src/set-utils.ts';\nimport * as v from '../../../shared/src/valita.ts';\nimport {primaryKeySchema} from '../../../zero-protocol/src/primary-key.ts';\nimport type {Database} from '../../../zqlite/src/db.ts';\nimport {\n ColumnMetadataStore,\n metadataToLiteTypeString,\n} from '../services/replicator/schema/column-metadata.ts';\nimport {TableMetadataTracker} from '../services/replicator/schema/table-metadata.ts';\nimport {\n isArray,\n isEnum,\n liteTypeToZqlValueType,\n mapLiteDataTypeToZqlSchemaValue,\n nullableUpstream,\n} from '../types/lite.ts';\nimport * as PostgresTypeClass from './postgres-type-class-enum.ts';\nimport type {\n LiteAndZqlSpec,\n LiteIndexSpec,\n LiteTableSpec,\n MutableLiteIndexSpec,\n MutableLiteTableSpec,\n} from './specs.ts';\n\ntype ColumnInfo = {\n table: string;\n name: string;\n type: string;\n notNull: number;\n dflt: string | null;\n keyPos: number;\n};\n\nexport type LiteTableSpecWithReplicationStatus = LiteTableSpec & {\n readonly backfilling?: string[];\n readonly minRowVersion?: string | null;\n};\n\ntype MutableLiteTableSpecWithReplicationStatus = MutableLiteTableSpec & {\n backfilling: string[];\n minRowVersion: string | null;\n};\n\nexport function listTables(\n db: Database,\n useColumnMetadata = true,\n useTableMetadata = true,\n): LiteTableSpecWithReplicationStatus[] {\n const columns = db\n .prepare(\n `\n SELECT\n m.name as \"table\",\n p.name as name,\n p.type as type,\n p.\"notnull\" as \"notNull\",\n p.dflt_value as \"dflt\",\n p.pk as keyPos\n FROM sqlite_master as m\n LEFT JOIN pragma_table_info(m.name) as p\n WHERE m.type = 'table'\n AND m.name NOT LIKE 'sqlite_%'\n AND m.name NOT LIKE '_zero.%'\n AND m.name NOT LIKE '_litestream_%'\n `,\n )\n .all() as ColumnInfo[];\n\n const minRowVersions = useTableMetadata\n ? new TableMetadataTracker(db).getMinRowVersions()\n : new Map();\n const tables: LiteTableSpecWithReplicationStatus[] = [];\n let table: MutableLiteTableSpecWithReplicationStatus | undefined;\n\n columns.forEach(col => {\n if (col.table !== table?.name) {\n // New table\n table = {\n name: col.table,\n columns: {},\n backfilling: [],\n minRowVersion: minRowVersions.get(col.table) ?? null,\n };\n tables.push(table);\n }\n\n // Try to read from metadata table first, fall back to SQLite column type\n let dataType: string;\n let elemPgTypeClass:\n | typeof PostgresTypeClass.Base\n | typeof PostgresTypeClass.Enum\n | null;\n\n const metadata = useColumnMetadata\n ? ColumnMetadataStore.getInstance(db)?.getColumn(col.table, col.name)\n : undefined;\n if (metadata) {\n // Read from metadata table and convert to pipe notation\n dataType = metadataToLiteTypeString(metadata);\n elemPgTypeClass = metadata.isArray\n ? metadata.isEnum\n ? PostgresTypeClass.Enum\n : PostgresTypeClass.Base\n : null;\n } else {\n // Fall back to reading from SQLite column type (pipe notation)\n dataType = col.type;\n elemPgTypeClass = isArray(col.type)\n ? isEnum(col.type)\n ? PostgresTypeClass.Enum\n : PostgresTypeClass.Base\n : null;\n }\n\n table.columns[col.name] = {\n pos: Object.keys(table.columns).length + 1,\n dataType,\n characterMaximumLength: null,\n notNull: col.notNull !== 0,\n dflt: col.dflt,\n elemPgTypeClass,\n };\n if (metadata?.isBackfilling) {\n table.backfilling.push(col.name);\n }\n if (col.keyPos) {\n table.primaryKey ??= [];\n while (table.primaryKey.length < col.keyPos) {\n table.primaryKey.push('');\n }\n table.primaryKey[col.keyPos - 1] = col.name;\n }\n });\n\n return tables;\n}\n\n/**\n * An index as it exists on the replica. SQLite retains only the DDL text of a\n * partial index, not a structured predicate, so replica indexes report a\n * `partial` flag in place of the {@link LiteIndexSpec.predicate}.\n */\nexport type ReplicaIndexSpec = Omit<LiteIndexSpec, 'predicate'> & {\n readonly partial?: boolean | undefined;\n};\n\ntype MutableReplicaIndexSpec = Omit<MutableLiteIndexSpec, 'predicate'> & {\n partial?: boolean | undefined;\n};\n\nexport function listIndexes(db: Database): ReplicaIndexSpec[] {\n const indexes = db\n .prepare(\n `SELECT \n idx.name as indexName, \n idx.tbl_name as tableName, \n info.\"unique\" as \"unique\",\n info.partial as partial,\n col.name as column,\n CASE WHEN col.desc = 0 THEN 'ASC' ELSE 'DESC' END as dir\n FROM sqlite_master as idx\n JOIN pragma_index_list(idx.tbl_name) AS info ON info.name = idx.name\n JOIN pragma_index_xinfo(idx.name) as col\n WHERE idx.type = 'index' AND \n col.key = 1 AND\n idx.tbl_name NOT LIKE '_zero.%'\n ORDER BY idx.name, col.seqno ASC`,\n )\n .all() as {\n indexName: string;\n tableName: string;\n unique: number;\n partial: number;\n column: string;\n dir: 'ASC' | 'DESC';\n }[];\n\n const ret: MutableReplicaIndexSpec[] = [];\n for (const {\n indexName: name,\n tableName,\n unique,\n partial,\n column,\n dir,\n } of indexes) {\n if (ret.at(-1)?.name === name) {\n // Aggregate multiple column names into the array.\n must(ret.at(-1)).columns[column] = dir;\n } else {\n ret.push({\n tableName,\n name,\n columns: {[column]: dir},\n unique: unique !== 0,\n ...(partial === 0 ? {} : {partial: true}),\n });\n }\n }\n\n return ret;\n}\n\nexport type ZqlSpecOptions = {\n /**\n * Controls whether to include backfilling columns in the computed\n * LiteAndZqlSpec. In general, backfilling columns should be include\n * in \"replication\" logic (copying data from upstream to the replica),\n * and excluded from \"sync\" logic (sending data from the replica to\n * clients).\n */\n includeBackfillingColumns: boolean;\n};\n\n/**\n * Computes a TableSpec \"view\" of the replicated data that is\n * suitable for processing / consumption for the client. This\n * includes:\n * * excluding tables without a PRIMARY KEY or UNIQUE INDEX\n * * excluding columns with types that are not supported by ZQL\n * * choosing columns to use as the primary key amongst those\n * in unique indexes\n *\n * @param tableSpecs an optional map to reset and populate\n * @param fullTables an optional map to receive the full table specs,\n * which may include tables and columns that are not synced to\n * the client because they lack a primary key or are of unsupported\n * data types.\n */\nexport function computeZqlSpecs(\n lc: LogContext,\n replica: Database,\n opts: ZqlSpecOptions,\n tableSpecs: Map<string, LiteAndZqlSpec> = new Map(),\n fullTables?: Map<string, LiteTableSpec>,\n): Map<string, LiteAndZqlSpec> {\n return computeZqlSpecsFromLiteSpecs(\n listTables(replica),\n listIndexes(replica),\n opts,\n tableSpecs,\n fullTables,\n lc,\n );\n}\n\nfunction isPartialIndex(idx: LiteIndexSpec | ReplicaIndexSpec): boolean {\n return (\n ('predicate' in idx && idx.predicate !== undefined) ||\n ('partial' in idx && idx.partial === true)\n );\n}\n\nexport function computeZqlSpecsFromLiteSpecs(\n tables: LiteTableSpecWithReplicationStatus[],\n indexes: readonly (LiteIndexSpec | ReplicaIndexSpec)[],\n {includeBackfillingColumns}: ZqlSpecOptions,\n tableSpecs: Map<string, LiteAndZqlSpec> = new Map(),\n fullTables?: Map<string, LiteTableSpec>,\n lc?: LogContext,\n): Map<string, LiteAndZqlSpec> {\n tableSpecs.clear();\n fullTables?.clear();\n\n const uniqueIndexColumns = new Map<string, string[][]>();\n // A partial unique index only constrains the rows matching its predicate,\n // so it cannot serve as a row key.\n for (const {tableName, columns} of indexes.filter(\n idx => idx.unique && !isPartialIndex(idx),\n )) {\n if (!uniqueIndexColumns.has(tableName)) {\n uniqueIndexColumns.set(tableName, []);\n }\n uniqueIndexColumns.get(tableName)?.push(Object.keys(columns));\n }\n\n tables.forEach(fullTable => {\n fullTables?.set(fullTable.name, fullTable);\n\n const backfilling = new Set(fullTable.backfilling);\n // Only include columns that:\n // - have a defined ZQL Value\n // - aren't backfilling if `includeBackfillingColumns` is false\n const visibleColumns = Object.entries(fullTable.columns).filter(\n ([col, {dataType}]) =>\n liteTypeToZqlValueType(dataType) &&\n (includeBackfillingColumns || !backfilling.has(col)),\n );\n const notNullColumns = new Set(\n visibleColumns\n .filter(\n ([col, {dataType}]) =>\n !nullableUpstream(dataType) || fullTable.primaryKey?.includes(col),\n )\n .map(([col]) => col),\n );\n\n const uniqueKeys = uniqueIndexColumns.get(fullTable.name) ?? [];\n // Examine all column combinations that can serve as a primary key,\n // i.e. excluding indexes over nullable or unsynced columns.\n const keys = uniqueKeys.filter(\n key => difference(new Set(key), notNullColumns).size === 0,\n );\n if (keys.length === 0) {\n // Only include tables with a row key.\n //\n // Note that this will automatically exclude tables that are being\n // backfilled (when includeBackfillingColumns is `false`) since candidate\n // keys only include visible columns.\n lc?.debug?.(\n `not syncing table ${fullTable.name} because it ` +\n (backfilling.size ? 'is being backfilled' : 'has no primary key'),\n );\n return;\n }\n // Pick the \"best\" (i.e. shortest) key for default IVM operations.\n const primaryKey = keys.sort(keyCmp)[0];\n\n const tableSpec = {\n ...fullTable,\n columns: Object.fromEntries(visibleColumns),\n primaryKey: v.parse(primaryKey, primaryKeySchema),\n uniqueKeys: uniqueKeys.map(key => v.parse(key, primaryKeySchema)),\n allPotentialPrimaryKeys: keys.map(key => v.parse(key, primaryKeySchema)),\n minRowVersion: fullTable.minRowVersion ?? null,\n };\n\n tableSpecs.set(tableSpec.name, {\n tableSpec,\n zqlSpec: Object.fromEntries(\n Object.entries(tableSpec.columns).map(([name, {dataType}]) => [\n name,\n mapLiteDataTypeToZqlSchemaValue(dataType),\n ]),\n ),\n });\n });\n return tableSpecs;\n}\n\nexport function mustGetTableSpec(\n tableSpecs: Map<string, LiteAndZqlSpec>,\n tableName: string,\n): LiteAndZqlSpec {\n const tableSpec = tableSpecs.get(tableName);\n if (!tableSpec) {\n throw new Error(\n `table '${tableName}' is not one of: ${[...tableSpecs.keys()]\n .filter(t => !t.includes('.') && !t.startsWith('_litestream_'))\n .sort()}. ` +\n `Check the spelling and ensure that the table has a primary key.`,\n );\n }\n return tableSpec;\n}\n\n// Deterministic comparator for favoring shorter row keys.\nfunction keyCmp(a: string[], b: string[]) {\n if (a.length !== b.length) {\n return a.length - b.length; // Fewer columns are better.\n }\n for (let i = 0; i < a.length; i++) {\n if (a[i] < b[i]) {\n return -1;\n }\n if (a[i] > b[i]) {\n return 1;\n }\n }\n return 0;\n}\n"],"mappings":"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"}
@@ -13,6 +13,17 @@ export declare const columnSpec: v.ObjectType<{
13
13
  dflt: v.Optional<string | null>;
14
14
  }, undefined>;
15
15
  export type ColumnSpec = Readonly<v.Infer<typeof columnSpec>>;
16
+ export declare const publishedColumnSpec: v.ObjectType<Omit<{
17
+ pos: v.Type<number>;
18
+ dataType: v.Type<string>;
19
+ pgTypeClass: v.Optional<"e" | "d" | "b" | "c" | "p" | "r" | "m">;
20
+ elemPgTypeClass: v.Optional<"e" | "d" | "b" | "c" | "p" | "r" | "m" | null>;
21
+ characterMaximumLength: v.Optional<number | null>;
22
+ notNull: v.Optional<boolean | null>;
23
+ dflt: v.Optional<string | null>;
24
+ }, "typeOID"> & {
25
+ typeOID: v.Type<number>;
26
+ }, undefined>;
16
27
  export declare const liteTableSpec: v.ObjectType<{
17
28
  name: v.Type<string>;
18
29
  columns: v.Type<Record<string, {
@@ -106,11 +117,39 @@ export type LiteAndZqlSpec = {
106
117
  export type TableSpec = Readonly<v.Infer<typeof tableSpec>>;
107
118
  export type PublishedTableSpec = Readonly<v.Infer<typeof publishedTableSpec>>;
108
119
  export declare const directionSchema: v.Type<"ASC" | "DESC">;
120
+ export type IndexPredicateValue = {
121
+ readonly type: 'boolean';
122
+ readonly value: boolean;
123
+ } | {
124
+ readonly type: 'integer';
125
+ readonly value: string;
126
+ } | {
127
+ readonly type: 'string';
128
+ readonly value: string;
129
+ };
130
+ export type IndexPredicate = {
131
+ readonly type: 'and' | 'or';
132
+ readonly conditions: readonly IndexPredicate[];
133
+ } | {
134
+ readonly type: 'not';
135
+ readonly condition: IndexPredicate;
136
+ } | {
137
+ readonly type: 'null-test';
138
+ readonly column: string;
139
+ readonly op: 'IS NULL' | 'IS NOT NULL';
140
+ } | {
141
+ readonly type: 'comparison';
142
+ readonly column: string;
143
+ readonly op: '=' | '<>' | '<' | '<=' | '>' | '>=';
144
+ readonly value: IndexPredicateValue;
145
+ };
146
+ export declare const indexPredicateSchema: v.Type<IndexPredicate>;
109
147
  export declare const liteIndexSpec: v.ObjectType<{
110
148
  name: v.Type<string>;
111
149
  tableName: v.Type<string>;
112
150
  unique: v.Type<boolean>;
113
151
  columns: v.Type<Record<string, "ASC" | "DESC">>;
152
+ predicate: v.Optional<IndexPredicate>;
114
153
  }, undefined>;
115
154
  export type MutableLiteIndexSpec = v.Infer<typeof liteIndexSpec>;
116
155
  export type LiteIndexSpec = Readonly<MutableLiteIndexSpec>;
@@ -119,6 +158,7 @@ export declare const indexSpec: v.ObjectType<Omit<{
119
158
  tableName: v.Type<string>;
120
159
  unique: v.Type<boolean>;
121
160
  columns: v.Type<Record<string, "ASC" | "DESC">>;
161
+ predicate: v.Optional<IndexPredicate>;
122
162
  }, "schema"> & {
123
163
  schema: v.Type<string>;
124
164
  }, undefined>;
@@ -128,6 +168,7 @@ export declare const publishedIndexSpec: v.ObjectType<Omit<Omit<{
128
168
  tableName: v.Type<string>;
129
169
  unique: v.Type<boolean>;
130
170
  columns: v.Type<Record<string, "ASC" | "DESC">>;
171
+ predicate: v.Optional<IndexPredicate>;
131
172
  }, "schema"> & {
132
173
  schema: v.Type<string>;
133
174
  }, "isReplicaIdentity" | "isPrimaryKey" | "isImmediate"> & {
@@ -1 +1 @@
1
- {"version":3,"file":"specs.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/db/specs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,CAAC,MAAM,+BAA+B,CAAC;AACnD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2CAA2C,CAAC;AAC1E,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,0CAA0C,CAAC;AAI1E,eAAO,MAAM,iBAAiB,iDAQ7B,CAAC;AASF,eAAO,MAAM,UAAU;;;;;;;;aAarB,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC;AAM9D,eAAO,MAAM,aAAa;;;;;;;;;;;;aAIxB,CAAC;AAEH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;aAEpB,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAQ7B,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEjE,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AAE3D,MAAM,MAAM,+BAA+B,GAAG,IAAI,CAChD,aAAa,EACb,YAAY,CACb,GAAG;IACF;;;OAGG;IACH,UAAU,EAAE,UAAU,EAAE,CAAC;IAEzB;;;;OAIG;IACH,UAAU,EAAE,UAAU,CAAC;IAEvB;;;OAGG;IACH,uBAAuB,EAAE,UAAU,EAAE,CAAC;IAEtC;;;;OAIG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,+BAA+B,CAAC;IAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC;AAE5D,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC,CAAC;AAE9E,eAAO,MAAM,eAAe,wBAAgC,CAAC;AAE7D,eAAO,MAAM,aAAa;;;;;aAKxB,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEjE,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AAE3D,eAAO,MAAM,SAAS;;;;;;;aAEpB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC;AAEhE,eAAO,MAAM,kBAAkB;;;;;;;;;;;aAI7B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,YAAY,CAC3C,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CACnC,CAAC"}
1
+ {"version":3,"file":"specs.d.ts","sourceRoot":"","sources":["../../../../../zero-cache/src/db/specs.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { literalUnion, valita_exports } from "../../../shared/src/valita.js";
1
+ import { literalUnion, readonlyArray, readonlyObject, valita_exports } from "../../../shared/src/valita.js";
2
2
  //#region ../zero-cache/src/db/specs.ts
3
3
  var pgTypeClassSchema = literalUnion("b", "c", "d", "e", "p", "r", "m");
4
4
  var pgReplicaIdentitySchema = literalUnion("d", "n", "f", "i");
@@ -25,11 +25,38 @@ var publishedTableSpec = tableSpec.extend({
25
25
  publications: valita_exports.record(valita_exports.object({ rowFilter: valita_exports.string().nullable() }))
26
26
  });
27
27
  var directionSchema = literalUnion("ASC", "DESC");
28
+ var indexPredicateValueSchema = valita_exports.union(readonlyObject({
29
+ type: valita_exports.literal("boolean"),
30
+ value: valita_exports.boolean()
31
+ }), readonlyObject({
32
+ type: valita_exports.literal("integer"),
33
+ value: valita_exports.string()
34
+ }), readonlyObject({
35
+ type: valita_exports.literal("string"),
36
+ value: valita_exports.string()
37
+ }));
38
+ var indexPredicateSchema = valita_exports.lazy(() => valita_exports.union(readonlyObject({
39
+ type: literalUnion("and", "or"),
40
+ conditions: readonlyArray(indexPredicateSchema)
41
+ }), readonlyObject({
42
+ type: valita_exports.literal("not"),
43
+ condition: indexPredicateSchema
44
+ }), readonlyObject({
45
+ type: valita_exports.literal("null-test"),
46
+ column: valita_exports.string(),
47
+ op: literalUnion("IS NULL", "IS NOT NULL")
48
+ }), readonlyObject({
49
+ type: valita_exports.literal("comparison"),
50
+ column: valita_exports.string(),
51
+ op: literalUnion("=", "<>", "<", "<=", ">", ">="),
52
+ value: indexPredicateValueSchema
53
+ })));
28
54
  var indexSpec = valita_exports.object({
29
55
  name: valita_exports.string(),
30
56
  tableName: valita_exports.string(),
31
57
  unique: valita_exports.boolean(),
32
- columns: valita_exports.record(directionSchema)
58
+ columns: valita_exports.record(directionSchema),
59
+ predicate: indexPredicateSchema.optional()
33
60
  }).extend({ schema: valita_exports.string() });
34
61
  var publishedIndexSpec = indexSpec.extend({
35
62
  isReplicaIdentity: valita_exports.boolean().optional(),
@@ -37,6 +64,6 @@ var publishedIndexSpec = indexSpec.extend({
37
64
  isImmediate: valita_exports.boolean().optional()
38
65
  });
39
66
  //#endregion
40
- export { columnSpec, indexSpec, publishedIndexSpec, publishedTableSpec, tableSpec };
67
+ export { columnSpec, indexSpec, publishedColumnSpec, publishedIndexSpec, publishedTableSpec, tableSpec };
41
68
 
42
69
  //# sourceMappingURL=specs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"specs.js","names":[],"sources":["../../../../../zero-cache/src/db/specs.ts"],"sourcesContent":["import type {DeepReadonly} from '../../../shared/src/json.ts';\nimport * as v from '../../../shared/src/valita.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport type {SchemaValue} from '../../../zero-schema/src/table-schema.ts';\nimport * as PostgresReplicaIdentity from './postgres-replica-identity-enum.ts';\nimport * as PostgresTypeClass from './postgres-type-class-enum.ts';\n\nexport const pgTypeClassSchema = v.literalUnion(\n PostgresTypeClass.Base,\n PostgresTypeClass.Composite,\n PostgresTypeClass.Domain,\n PostgresTypeClass.Enum,\n PostgresTypeClass.Pseudo,\n PostgresTypeClass.Range,\n PostgresTypeClass.Multirange,\n);\n\nconst pgReplicaIdentitySchema = v.literalUnion(\n PostgresReplicaIdentity.Default,\n PostgresReplicaIdentity.Nothing,\n PostgresReplicaIdentity.Full,\n PostgresReplicaIdentity.Index,\n);\n\nexport const columnSpec = v.object({\n pos: v.number(),\n dataType: v.string(),\n pgTypeClass: pgTypeClassSchema.optional(),\n\n // If the column is an array, this will be the type of the\n // elements in the array. If the column is not an array,\n // this will be null.\n elemPgTypeClass: pgTypeClassSchema.nullable().optional(),\n\n characterMaximumLength: v.number().nullable().optional(),\n notNull: v.boolean().nullable().optional(),\n dflt: v.string().nullable().optional(),\n});\n\nexport type ColumnSpec = Readonly<v.Infer<typeof columnSpec>>;\n\nconst publishedColumnSpec = columnSpec.extend({\n typeOID: v.number(),\n});\n\nexport const liteTableSpec = v.object({\n name: v.string(),\n columns: v.record(columnSpec),\n primaryKey: v.array(v.string()).optional(),\n});\n\nexport const tableSpec = liteTableSpec.extend({\n schema: v.string(),\n});\n\nexport const publishedTableSpec = tableSpec.extend({\n oid: v.number(),\n // Always present for new instances (e.g. from DDL triggers), but\n // may from `initialSchema` object stored in the `replicas` table.\n schemaOID: v.number().optional(),\n columns: v.record(publishedColumnSpec),\n replicaIdentity: pgReplicaIdentitySchema.optional(),\n publications: v.record(v.object({rowFilter: v.string().nullable()})),\n});\n\nexport type MutableLiteTableSpec = v.Infer<typeof liteTableSpec>;\n\nexport type LiteTableSpec = Readonly<MutableLiteTableSpec>;\n\nexport type LiteTableSpecWithKeysAndVersion = Omit<\n LiteTableSpec,\n 'primaryKey'\n> & {\n /**\n * All keys associated with a unique index. Includes indexes with\n * nullable columns.\n */\n uniqueKeys: PrimaryKey[];\n\n /**\n * The key selected to act as the \"primary key\". Primary keys\n * are not explicitly set on the replica, but an appropriate\n * unique index is required.\n */\n primaryKey: PrimaryKey; // note: required\n\n /**\n * All keys associated with a unique index over non-null\n * columns, i.e. suitable as a primary key.\n */\n allPotentialPrimaryKeys: PrimaryKey[];\n\n /**\n * The minimum `_0_version` value for every row in the table. If this is\n * present, `_0_version` value in the row itself should only be used if\n * it is greater (i.e. later) than the `minRowVersion`.\n */\n minRowVersion: string | null;\n};\n\nexport type LiteAndZqlSpec = {\n tableSpec: LiteTableSpecWithKeysAndVersion;\n zqlSpec: Record<string, SchemaValue>;\n};\n\nexport type TableSpec = Readonly<v.Infer<typeof tableSpec>>;\n\nexport type PublishedTableSpec = Readonly<v.Infer<typeof publishedTableSpec>>;\n\nexport const directionSchema = v.literalUnion('ASC', 'DESC');\n\nexport const liteIndexSpec = v.object({\n name: v.string(),\n tableName: v.string(),\n unique: v.boolean(),\n columns: v.record(directionSchema),\n});\n\nexport type MutableLiteIndexSpec = v.Infer<typeof liteIndexSpec>;\n\nexport type LiteIndexSpec = Readonly<MutableLiteIndexSpec>;\n\nexport const indexSpec = liteIndexSpec.extend({\n schema: v.string(),\n});\n\nexport type IndexSpec = DeepReadonly<v.Infer<typeof indexSpec>>;\n\nexport const publishedIndexSpec = indexSpec.extend({\n isReplicaIdentity: v.boolean().optional(),\n isPrimaryKey: v.boolean().optional(),\n isImmediate: v.boolean().optional(),\n});\n\nexport type PublishedIndexSpec = DeepReadonly<\n v.Infer<typeof publishedIndexSpec>\n>;\n"],"mappings":";;AAOA,IAAa,oBAAoB,aAC/B,KACA,KACA,KACA,KACA,KACA,KACA,GACF;AAEA,IAAM,0BAA0B,aAC9B,KACA,KACA,KACA,GACF;AAEA,IAAa,aAAa,eAAE,OAAO;CACjC,KAAK,eAAE,OAAO;CACd,UAAU,eAAE,OAAO;CACnB,aAAa,kBAAkB,SAAS;CAKxC,iBAAiB,kBAAkB,SAAS,EAAE,SAAS;CAEvD,wBAAwB,eAAE,OAAO,EAAE,SAAS,EAAE,SAAS;CACvD,SAAS,eAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;CACzC,MAAM,eAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AACvC,CAAC;AAID,IAAM,sBAAsB,WAAW,OAAO,EAC5C,SAAS,eAAE,OAAO,EACpB,CAAC;AAQD,IAAa,YANgB,eAAE,OAAO;CACpC,MAAM,eAAE,OAAO;CACf,SAAS,eAAE,OAAO,UAAU;CAC5B,YAAY,eAAE,MAAM,eAAE,OAAO,CAAC,EAAE,SAAS;AAC3C,CAEyB,EAAc,OAAO,EAC5C,QAAQ,eAAE,OAAO,EACnB,CAAC;AAED,IAAa,qBAAqB,UAAU,OAAO;CACjD,KAAK,eAAE,OAAO;CAGd,WAAW,eAAE,OAAO,EAAE,SAAS;CAC/B,SAAS,eAAE,OAAO,mBAAmB;CACrC,iBAAiB,wBAAwB,SAAS;CAClD,cAAc,eAAE,OAAO,eAAE,OAAO,EAAC,WAAW,eAAE,OAAO,EAAE,SAAS,EAAC,CAAC,CAAC;AACrE,CAAC;AA8CD,IAAa,kBAAkB,aAAe,OAAO,MAAM;AAa3D,IAAa,YAXgB,eAAE,OAAO;CACpC,MAAM,eAAE,OAAO;CACf,WAAW,eAAE,OAAO;CACpB,QAAQ,eAAE,QAAQ;CAClB,SAAS,eAAE,OAAO,eAAe;AACnC,CAMyB,EAAc,OAAO,EAC5C,QAAQ,eAAE,OAAO,EACnB,CAAC;AAID,IAAa,qBAAqB,UAAU,OAAO;CACjD,mBAAmB,eAAE,QAAQ,EAAE,SAAS;CACxC,cAAc,eAAE,QAAQ,EAAE,SAAS;CACnC,aAAa,eAAE,QAAQ,EAAE,SAAS;AACpC,CAAC"}
1
+ {"version":3,"file":"specs.js","names":[],"sources":["../../../../../zero-cache/src/db/specs.ts"],"sourcesContent":["import type {DeepReadonly} from '../../../shared/src/json.ts';\nimport * as v from '../../../shared/src/valita.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport type {SchemaValue} from '../../../zero-schema/src/table-schema.ts';\nimport * as PostgresReplicaIdentity from './postgres-replica-identity-enum.ts';\nimport * as PostgresTypeClass from './postgres-type-class-enum.ts';\n\nexport const pgTypeClassSchema = v.literalUnion(\n PostgresTypeClass.Base,\n PostgresTypeClass.Composite,\n PostgresTypeClass.Domain,\n PostgresTypeClass.Enum,\n PostgresTypeClass.Pseudo,\n PostgresTypeClass.Range,\n PostgresTypeClass.Multirange,\n);\n\nconst pgReplicaIdentitySchema = v.literalUnion(\n PostgresReplicaIdentity.Default,\n PostgresReplicaIdentity.Nothing,\n PostgresReplicaIdentity.Full,\n PostgresReplicaIdentity.Index,\n);\n\nexport const columnSpec = v.object({\n pos: v.number(),\n dataType: v.string(),\n pgTypeClass: pgTypeClassSchema.optional(),\n\n // If the column is an array, this will be the type of the\n // elements in the array. If the column is not an array,\n // this will be null.\n elemPgTypeClass: pgTypeClassSchema.nullable().optional(),\n\n characterMaximumLength: v.number().nullable().optional(),\n notNull: v.boolean().nullable().optional(),\n dflt: v.string().nullable().optional(),\n});\n\nexport type ColumnSpec = Readonly<v.Infer<typeof columnSpec>>;\n\nexport const publishedColumnSpec = columnSpec.extend({\n typeOID: v.number(),\n});\n\nexport const liteTableSpec = v.object({\n name: v.string(),\n columns: v.record(columnSpec),\n primaryKey: v.array(v.string()).optional(),\n});\n\nexport const tableSpec = liteTableSpec.extend({\n schema: v.string(),\n});\n\nexport const publishedTableSpec = tableSpec.extend({\n oid: v.number(),\n // Always present for new instances (e.g. from DDL triggers), but\n // may from `initialSchema` object stored in the `replicas` table.\n schemaOID: v.number().optional(),\n columns: v.record(publishedColumnSpec),\n replicaIdentity: pgReplicaIdentitySchema.optional(),\n publications: v.record(v.object({rowFilter: v.string().nullable()})),\n});\n\nexport type MutableLiteTableSpec = v.Infer<typeof liteTableSpec>;\n\nexport type LiteTableSpec = Readonly<MutableLiteTableSpec>;\n\nexport type LiteTableSpecWithKeysAndVersion = Omit<\n LiteTableSpec,\n 'primaryKey'\n> & {\n /**\n * All keys associated with a unique index. Includes indexes with\n * nullable columns.\n */\n uniqueKeys: PrimaryKey[];\n\n /**\n * The key selected to act as the \"primary key\". Primary keys\n * are not explicitly set on the replica, but an appropriate\n * unique index is required.\n */\n primaryKey: PrimaryKey; // note: required\n\n /**\n * All keys associated with a unique index over non-null\n * columns, i.e. suitable as a primary key.\n */\n allPotentialPrimaryKeys: PrimaryKey[];\n\n /**\n * The minimum `_0_version` value for every row in the table. If this is\n * present, `_0_version` value in the row itself should only be used if\n * it is greater (i.e. later) than the `minRowVersion`.\n */\n minRowVersion: string | null;\n};\n\nexport type LiteAndZqlSpec = {\n tableSpec: LiteTableSpecWithKeysAndVersion;\n zqlSpec: Record<string, SchemaValue>;\n};\n\nexport type TableSpec = Readonly<v.Infer<typeof tableSpec>>;\n\nexport type PublishedTableSpec = Readonly<v.Infer<typeof publishedTableSpec>>;\n\nexport const directionSchema = v.literalUnion('ASC', 'DESC');\n\nexport type IndexPredicateValue =\n | {readonly type: 'boolean'; readonly value: boolean}\n | {readonly type: 'integer'; readonly value: string}\n | {readonly type: 'string'; readonly value: string};\n\nexport type IndexPredicate =\n | {\n readonly type: 'and' | 'or';\n readonly conditions: readonly IndexPredicate[];\n }\n | {readonly type: 'not'; readonly condition: IndexPredicate}\n | {\n readonly type: 'null-test';\n readonly column: string;\n readonly op: 'IS NULL' | 'IS NOT NULL';\n }\n | {\n readonly type: 'comparison';\n readonly column: string;\n readonly op: '=' | '<>' | '<' | '<=' | '>' | '>=';\n readonly value: IndexPredicateValue;\n };\n\nconst indexPredicateValueSchema: v.Type<IndexPredicateValue> = v.union(\n v.readonlyObject({type: v.literal('boolean'), value: v.boolean()}),\n v.readonlyObject({type: v.literal('integer'), value: v.string()}),\n v.readonlyObject({type: v.literal('string'), value: v.string()}),\n);\n\nexport const indexPredicateSchema: v.Type<IndexPredicate> = v.lazy(() =>\n v.union(\n v.readonlyObject({\n type: v.literalUnion('and', 'or'),\n conditions: v.readonlyArray(indexPredicateSchema),\n }),\n v.readonlyObject({\n type: v.literal('not'),\n condition: indexPredicateSchema,\n }),\n v.readonlyObject({\n type: v.literal('null-test'),\n column: v.string(),\n op: v.literalUnion('IS NULL', 'IS NOT NULL'),\n }),\n v.readonlyObject({\n type: v.literal('comparison'),\n column: v.string(),\n op: v.literalUnion('=', '<>', '<', '<=', '>', '>='),\n value: indexPredicateValueSchema,\n }),\n ),\n);\n\nexport const liteIndexSpec = v.object({\n name: v.string(),\n tableName: v.string(),\n unique: v.boolean(),\n columns: v.record(directionSchema),\n predicate: indexPredicateSchema.optional(),\n});\n\nexport type MutableLiteIndexSpec = v.Infer<typeof liteIndexSpec>;\n\nexport type LiteIndexSpec = Readonly<MutableLiteIndexSpec>;\n\nexport const indexSpec = liteIndexSpec.extend({\n schema: v.string(),\n});\n\nexport type IndexSpec = DeepReadonly<v.Infer<typeof indexSpec>>;\n\nexport const publishedIndexSpec = indexSpec.extend({\n isReplicaIdentity: v.boolean().optional(),\n isPrimaryKey: v.boolean().optional(),\n isImmediate: v.boolean().optional(),\n});\n\nexport type PublishedIndexSpec = DeepReadonly<\n v.Infer<typeof publishedIndexSpec>\n>;\n"],"mappings":";;AAOA,IAAa,oBAAoB,aAC/B,KACA,KACA,KACA,KACA,KACA,KACA,GACF;AAEA,IAAM,0BAA0B,aAC9B,KACA,KACA,KACA,GACF;AAEA,IAAa,aAAa,eAAE,OAAO;CACjC,KAAK,eAAE,OAAO;CACd,UAAU,eAAE,OAAO;CACnB,aAAa,kBAAkB,SAAS;CAKxC,iBAAiB,kBAAkB,SAAS,EAAE,SAAS;CAEvD,wBAAwB,eAAE,OAAO,EAAE,SAAS,EAAE,SAAS;CACvD,SAAS,eAAE,QAAQ,EAAE,SAAS,EAAE,SAAS;CACzC,MAAM,eAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AACvC,CAAC;AAID,IAAa,sBAAsB,WAAW,OAAO,EACnD,SAAS,eAAE,OAAO,EACpB,CAAC;AAQD,IAAa,YANgB,eAAE,OAAO;CACpC,MAAM,eAAE,OAAO;CACf,SAAS,eAAE,OAAO,UAAU;CAC5B,YAAY,eAAE,MAAM,eAAE,OAAO,CAAC,EAAE,SAAS;AAC3C,CAEyB,EAAc,OAAO,EAC5C,QAAQ,eAAE,OAAO,EACnB,CAAC;AAED,IAAa,qBAAqB,UAAU,OAAO;CACjD,KAAK,eAAE,OAAO;CAGd,WAAW,eAAE,OAAO,EAAE,SAAS;CAC/B,SAAS,eAAE,OAAO,mBAAmB;CACrC,iBAAiB,wBAAwB,SAAS;CAClD,cAAc,eAAE,OAAO,eAAE,OAAO,EAAC,WAAW,eAAE,OAAO,EAAE,SAAS,EAAC,CAAC,CAAC;AACrE,CAAC;AA8CD,IAAa,kBAAkB,aAAe,OAAO,MAAM;AAyB3D,IAAM,4BAAyD,eAAE,MAC/D,eAAiB;CAAC,MAAM,eAAE,QAAQ,SAAS;CAAG,OAAO,eAAE,QAAQ;AAAC,CAAC,GACjE,eAAiB;CAAC,MAAM,eAAE,QAAQ,SAAS;CAAG,OAAO,eAAE,OAAO;AAAC,CAAC,GAChE,eAAiB;CAAC,MAAM,eAAE,QAAQ,QAAQ;CAAG,OAAO,eAAE,OAAO;AAAC,CAAC,CACjE;AAEA,IAAa,uBAA+C,eAAE,WAC5D,eAAE,MACA,eAAiB;CACf,MAAM,aAAe,OAAO,IAAI;CAChC,YAAY,cAAgB,oBAAoB;AAClD,CAAC,GACD,eAAiB;CACf,MAAM,eAAE,QAAQ,KAAK;CACrB,WAAW;AACb,CAAC,GACD,eAAiB;CACf,MAAM,eAAE,QAAQ,WAAW;CAC3B,QAAQ,eAAE,OAAO;CACjB,IAAI,aAAe,WAAW,aAAa;AAC7C,CAAC,GACD,eAAiB;CACf,MAAM,eAAE,QAAQ,YAAY;CAC5B,QAAQ,eAAE,OAAO;CACjB,IAAI,aAAe,KAAK,MAAM,KAAK,MAAM,KAAK,IAAI;CAClD,OAAO;AACT,CAAC,CACH,CACF;AAcA,IAAa,YAZgB,eAAE,OAAO;CACpC,MAAM,eAAE,OAAO;CACf,WAAW,eAAE,OAAO;CACpB,QAAQ,eAAE,QAAQ;CAClB,SAAS,eAAE,OAAO,eAAe;CACjC,WAAW,qBAAqB,SAAS;AAC3C,CAMyB,EAAc,OAAO,EAC5C,QAAQ,eAAE,OAAO,EACnB,CAAC;AAID,IAAa,qBAAqB,UAAU,OAAO;CACjD,mBAAmB,eAAE,QAAQ,EAAE,SAAS;CACxC,cAAc,eAAE,QAAQ,EAAE,SAAS;CACnC,aAAa,eAAE,QAAQ,EAAE,SAAS;AACpC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import type { LogContext } from '@rocicorp/logger';
2
2
  import * as v from '../../../../../shared/src/valita.ts';
3
- import type { PublishedTableSpec } from '../../../db/specs.ts';
3
+ import type { PublishedIndexSpec, PublishedTableSpec } from '../../../db/specs.ts';
4
4
  import { type LexiVersion } from '../../../types/lexi-version.ts';
5
5
  import { type PostgresDB } from '../../../types/pg.ts';
6
6
  import { type ShardConfig, type ShardID } from '../../../types/shards.ts';
@@ -14,6 +14,7 @@ import { streamBackfill } from './backfill-stream.ts';
14
14
  import { type InitialSyncOptions, type ReplicaOptions, type ServerContext } from './initial-sync.ts';
15
15
  import type { MessageMessage, MessageRelation as PostgresRelation } from './logical-replication/pgoutput.types.ts';
16
16
  import { subscribe } from './logical-replication/stream.ts';
17
+ import { type PublishedTableWithReplicaIdentity } from './schema/published.ts';
17
18
  import { type BackupOptions, type InternalShardConfig, type Replica } from './schema/shard.ts';
18
19
  interface PurgeLock {
19
20
  release(): Promise<void>;
@@ -88,5 +89,14 @@ export declare class LagReporter {
88
89
  processLagReportMessage(msg: MessageMessage): DownstreamStatusMessage;
89
90
  }
90
91
  export declare function relationDifferent(a: PublishedTableSpec, b: PostgresRelation): boolean;
92
+ /**
93
+ * Determines if an index was structurally changed (e.g. constraint dropped
94
+ * and recreated with different columns) vs cosmetically changed (e.g. the
95
+ * index spec changed because the table or a column was renamed).
96
+ *
97
+ * Compares boolean properties directly and resolves column names to their
98
+ * stable attnums (pg_attribute `attnum`) for the column comparison.
99
+ */
100
+ export declare function isIndexStructurallyChanged(prev: PublishedIndexSpec, next: PublishedIndexSpec, prevTables: Map<number, PublishedTableWithReplicaIdentity>, nextTables: Map<number, PublishedTableWithReplicaIdentity>): boolean;
91
101
  export {};
92
102
  //# sourceMappingURL=change-source.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"change-source.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/pg/change-source.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"change-source.d.ts","sourceRoot":"","sources":["../../../../../../../zero-cache/src/services/change-source/pg/change-source.ts"],"names":[],"mappings":"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"}
@@ -15,11 +15,12 @@ import { StatementRunner } from "../../../db/statements.js";
15
15
  import { connectPgClient, isPostgresError, pgClient } from "../../../types/pg.js";
16
16
  import { majorVersionFromString, majorVersionToString } from "../../../types/state-version.js";
17
17
  import { fromBigInt, toBigInt, toStateVersionString } from "./lsn.js";
18
- import { getPublicationInfo } from "./schema/published.js";
18
+ import { getPublicationInfo, warnForSkippedIndexes } from "./schema/published.js";
19
19
  import { replicationEventSchema } from "./schema/ddl.js";
20
20
  import { validate } from "./schema/validation.js";
21
21
  import { dropShard, getActiveReplicas, getInternalShardConfig, getReplicaAtVersion, internalPublicationPrefix, replicaIdentitiesForTablesWithoutPrimaryKeys, replicationSlotPrefix } from "./schema/shard.js";
22
22
  import { AutoResetSignal } from "../../change-streamer/schema/tables.js";
23
+ import { mapIndexPredicateColumns } from "../../../db/index-predicate.js";
23
24
  import { restoreReplica } from "../common/replica-restore.js";
24
25
  import { initReplica } from "../common/replica-schema.js";
25
26
  import "../../../types/pg-versions.js";
@@ -558,6 +559,7 @@ var ChangeMaker = class {
558
559
  #db;
559
560
  #replicaIdentityTimer;
560
561
  #error;
562
+ #skippedIndexWarnings = /* @__PURE__ */ new Set();
561
563
  constructor({ appID, shardNum }, shardConfig, db, initialSchema) {
562
564
  this.#shardPrefix = `${appID}/${shardNum}`;
563
565
  this.#shardConfig = shardConfig;
@@ -673,6 +675,8 @@ var ChangeMaker = class {
673
675
  #handleDdlMessage(lc, lsn, msg) {
674
676
  const event = parseLogicalMessageContent(lc, msg, replicationEventSchema);
675
677
  lc = lc.withContext("lsn", fromBigInt(lsn)).withContext("tag", event.event.tag).withContext("query", event.context.query);
678
+ if (event.previousSchema) warnForSkippedIndexes(lc, event.previousSchema, this.#skippedIndexWarnings);
679
+ if (event.schema) warnForSkippedIndexes(lc, event.schema, this.#skippedIndexWarnings);
676
680
  clearTimeout(this.#replicaIdentityTimer);
677
681
  const { type } = event;
678
682
  switch (type) {
@@ -961,6 +965,21 @@ function isIndexStructurallyChanged(prev, next, prevTables, nextTables) {
961
965
  const prevTable = findTableBySchemaAndName(prevTables, prev.schema, prev.tableName);
962
966
  const nextTable = findTableBySchemaAndName(nextTables, next.schema, next.tableName);
963
967
  if (!prevTable || !nextTable) return true;
968
+ if (prev.predicate === void 0 !== (next.predicate === void 0)) return true;
969
+ if (prev.predicate && next.predicate) {
970
+ let unresolved = false;
971
+ const prevPredicate = mapIndexPredicateColumns(prev.predicate, (name) => {
972
+ const pos = prevTable.columns[name]?.pos;
973
+ if (pos === void 0) unresolved = true;
974
+ return String(pos);
975
+ });
976
+ const nextPredicate = mapIndexPredicateColumns(next.predicate, (name) => {
977
+ const pos = nextTable.columns[name]?.pos;
978
+ if (pos === void 0) unresolved = true;
979
+ return String(pos);
980
+ });
981
+ if (unresolved || !deepEqual(prevPredicate, nextPredicate)) return true;
982
+ }
964
983
  const prevEntries = Object.entries(prev.columns);
965
984
  const nextEntries = Object.entries(next.columns);
966
985
  if (prevEntries.length !== nextEntries.length) return true;