bazis 0.96.1

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 (513) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +146 -0
  3. package/cli/build.ts +147 -0
  4. package/cli/codegen.ts +40 -0
  5. package/cli/generateModule.ts +187 -0
  6. package/cli/generateProject.ts +183 -0
  7. package/cli/main.ts +125 -0
  8. package/cli/moduleRegistration.ts +127 -0
  9. package/cli/naming.ts +124 -0
  10. package/cli/parseCli.ts +151 -0
  11. package/cli/templates/module.ts +497 -0
  12. package/cli/templates/pack.ts +76 -0
  13. package/cli/templates/passport.ts +178 -0
  14. package/core/agent/AgentContextBuilder.ts +567 -0
  15. package/core/agent/AgentDataDefinition.ts +8 -0
  16. package/core/agent/AgentRegistry.ts +539 -0
  17. package/core/agent/AgentRuntime.ts +47 -0
  18. package/core/agent/AgentToolExecutor.ts +2130 -0
  19. package/core/agent/AgentToolHooks.ts +39 -0
  20. package/core/agent/ModelProvider.ts +21 -0
  21. package/core/agent/README.md +229 -0
  22. package/core/agent/Tool.contract.ts +20 -0
  23. package/core/agent/decorators/Agent.ts +11 -0
  24. package/core/agent/decorators/Prompt.ts +11 -0
  25. package/core/agent/decorators/Task.ts +29 -0
  26. package/core/agent/decorators/Tool.ts +12 -0
  27. package/core/agent/errors.ts +43 -0
  28. package/core/agent/generated/catalog.ts +26 -0
  29. package/core/agent/index.ts +170 -0
  30. package/core/agent/internal/AgentExecutionDriver.ts +1497 -0
  31. package/core/agent/internal/AgentExecutionState.ts +775 -0
  32. package/core/agent/internal/AgentJsonSchema.ts +150 -0
  33. package/core/agent/internal/AgentModelBinding.ts +57 -0
  34. package/core/agent/internal/Schema.contract.ts +36 -0
  35. package/core/agent/internal/ToolAudit.projector.ts +163 -0
  36. package/core/agent/internal/ToolContract.validator.ts +102 -0
  37. package/core/agent/metadata.ts +398 -0
  38. package/core/agent/moduleContributions-v1.ts +113 -0
  39. package/core/agent/semantic.ts +903 -0
  40. package/core/agent/session/codec.ts +33 -0
  41. package/core/agent/session/contracts.ts +96 -0
  42. package/core/agent/session/entities.ts +84 -0
  43. package/core/agent/session/protector.ts +92 -0
  44. package/core/app/index.ts +5 -0
  45. package/core/app/runApp.ts +293 -0
  46. package/core/app/ui/index.ts +29 -0
  47. package/core/app/ui/uiProfileResolver.ts +966 -0
  48. package/core/app/ui/uiSurfaceHosting.ts +38 -0
  49. package/core/app/ui/uiSurfaceHttp.ts +476 -0
  50. package/core/background/BackgroundService.ts +223 -0
  51. package/core/background/backgroundModule.ts +42 -0
  52. package/core/background/decorator.ts +43 -0
  53. package/core/background/delay.ts +27 -0
  54. package/core/background/index.ts +15 -0
  55. package/core/cache/COMPATIBILITY.md +13 -0
  56. package/core/cache/ICache.ts +71 -0
  57. package/core/cache/MemoryCache.ts +394 -0
  58. package/core/cache/README.md +83 -0
  59. package/core/cache/SPEC.md +1355 -0
  60. package/core/cache/cacheModule.ts +21 -0
  61. package/core/cache/decorators/Cacheable.ts +38 -0
  62. package/core/cache/decorators/CacheableRedis.ts +39 -0
  63. package/core/cache/decorators/OutputCache.ts +33 -0
  64. package/core/cache/decorators/OutputRedisCache.ts +33 -0
  65. package/core/cache/decorators/cacheableMetadata.ts +78 -0
  66. package/core/cache/decorators/cacheableRedisMetadata.ts +81 -0
  67. package/core/cache/decorators/outputCacheMetadata.ts +71 -0
  68. package/core/cache/decorators/outputRedisCacheMetadata.ts +77 -0
  69. package/core/cache/di/classProviderHook.ts +26 -0
  70. package/core/cache/distributed/CacheCodec.ts +5 -0
  71. package/core/cache/distributed/DistributedCache.ts +403 -0
  72. package/core/cache/distributed/DistributedCacheDriver.ts +83 -0
  73. package/core/cache/distributed/DistributedCacheStores.ts +28 -0
  74. package/core/cache/distributed/IDistributedCache.ts +40 -0
  75. package/core/cache/distributed/NamedCacheRegistry.ts +23 -0
  76. package/core/cache/distributed/codecs.ts +32 -0
  77. package/core/cache/distributed/index.ts +19 -0
  78. package/core/cache/errors/CacheError.ts +16 -0
  79. package/core/cache/http/CachedHttpPayload.ts +213 -0
  80. package/core/cache/http/applyClientCacheHeaders.ts +61 -0
  81. package/core/cache/http/buildOutputCacheKey.ts +154 -0
  82. package/core/cache/http/buildRedisOutputCacheKey.ts +16 -0
  83. package/core/cache/http/composeOutputCache.ts +130 -0
  84. package/core/cache/http/outputCacheMiddleware.ts +111 -0
  85. package/core/cache/http/outputCacheSecurityWarning.ts +58 -0
  86. package/core/cache/http/outputRedisCacheMiddleware.ts +118 -0
  87. package/core/cache/index.ts +97 -0
  88. package/core/cache/internal/AutomaticCacheKey.ts +106 -0
  89. package/core/cache/internal/CacheKeyGuard.ts +56 -0
  90. package/core/cache/internal/buildCacheProviders.ts +146 -0
  91. package/core/cache/internal/normalizeCacheKey.ts +9 -0
  92. package/core/cache/internal/resolveCachePolicy.ts +32 -0
  93. package/core/cache/internal/resolveCacheableRedisPolicy.ts +17 -0
  94. package/core/cache/internal/resolveOutputRedisCachePolicy.ts +17 -0
  95. package/core/cache/providers/cachedProviders.ts +68 -0
  96. package/core/cache/services/cacheProxy.ts +243 -0
  97. package/core/cache/tokens/CACHE_POLICIES.ts +5 -0
  98. package/core/cache/tokens/DISTRIBUTED_CACHE.ts +30 -0
  99. package/core/cache/types/CacheEntry.ts +7 -0
  100. package/core/cache/types/CacheOptions.ts +60 -0
  101. package/core/cache/types/CachePolicy.ts +74 -0
  102. package/core/cache/types/CacheableRedisOptions.ts +23 -0
  103. package/core/cache/types/OutputRedisCacheOptions.ts +25 -0
  104. package/core/di/README.md +104 -0
  105. package/core/di/ServiceCollection.ts +185 -0
  106. package/core/di/ServiceProvider.ts +689 -0
  107. package/core/di/ServiceScope.ts +61 -0
  108. package/core/di/container.ts +38 -0
  109. package/core/di/errors/AmbiguousNamedDependencyError.ts +10 -0
  110. package/core/di/errors/AsyncResolutionRequiredError.ts +12 -0
  111. package/core/di/errors/CircularDependencyError.ts +10 -0
  112. package/core/di/errors/ClassDependenciesMismatchError.ts +15 -0
  113. package/core/di/errors/DiError.ts +6 -0
  114. package/core/di/errors/InvalidProviderError.ts +9 -0
  115. package/core/di/errors/ModuleEncapsulationError.ts +7 -0
  116. package/core/di/errors/ModuleOwnedProviderConflictError.ts +8 -0
  117. package/core/di/errors/NamedDependencyNotFoundError.ts +7 -0
  118. package/core/di/errors/OptionsValidationError.ts +7 -0
  119. package/core/di/errors/ProviderNotFoundError.ts +10 -0
  120. package/core/di/errors/ScopeDisposedError.ts +7 -0
  121. package/core/di/errors/ScopedServiceFromRootError.ts +9 -0
  122. package/core/di/errors/ServiceValidationError.ts +7 -0
  123. package/core/di/errors/index.ts +14 -0
  124. package/core/di/extensions/activator.ts +39 -0
  125. package/core/di/extensions/application.ts +117 -0
  126. package/core/di/extensions/hosted-service.ts +124 -0
  127. package/core/di/extensions/index.ts +23 -0
  128. package/core/di/extensions/options-reloadable.ts +137 -0
  129. package/core/di/extensions/options.ts +91 -0
  130. package/core/di/extensions/service-provider-token.ts +21 -0
  131. package/core/di/index.ts +97 -0
  132. package/core/di/internal/GraphValidator.ts +119 -0
  133. package/core/di/internal/HostedServicePlan.ts +158 -0
  134. package/core/di/internal/NamedTokenIndex.ts +55 -0
  135. package/core/di/internal/OpenGenericRegistration.ts +14 -0
  136. package/core/di/internal/ResolutionPlan.ts +18 -0
  137. package/core/di/internal/ResolutionScopeState.ts +19 -0
  138. package/core/di/internal/ResolutionTracker.ts +153 -0
  139. package/core/di/internal/ScopeLifecycle.ts +159 -0
  140. package/core/di/internal/ServiceRegistration.ts +14 -0
  141. package/core/di/internal/ServiceRegistry.ts +252 -0
  142. package/core/di/internal/classDeps.ts +38 -0
  143. package/core/di/internal/disposal.ts +58 -0
  144. package/core/di/internal/providerDeps.ts +26 -0
  145. package/core/di/module/DI.ts +146 -0
  146. package/core/di/module/Global.ts +25 -0
  147. package/core/di/module/Module.ts +44 -0
  148. package/core/di/module/ModuleRegistrar.ts +69 -0
  149. package/core/di/module/autoDeps.ts +39 -0
  150. package/core/di/module/classProviderHooks.ts +66 -0
  151. package/core/di/module/collectModuleConfigs.ts +57 -0
  152. package/core/di/module/collectModuleControllers.ts +53 -0
  153. package/core/di/module/collectModuleUiProfiles.ts +53 -0
  154. package/core/di/module/createContainer.ts +261 -0
  155. package/core/di/module/encapsulation.ts +416 -0
  156. package/core/di/module/encapsulationHooks.ts +36 -0
  157. package/core/di/module/generatedProviderAttachments.ts +102 -0
  158. package/core/di/module/index.ts +41 -0
  159. package/core/di/module/moduleExtensions.ts +35 -0
  160. package/core/di/module/moduleNameBinding.ts +136 -0
  161. package/core/di/module/moduleOwnedProviderContributors.ts +409 -0
  162. package/core/di/module/providerSelection.ts +90 -0
  163. package/core/di/module/shortcuts.ts +111 -0
  164. package/core/di/module/types/BazisModule.ts +71 -0
  165. package/core/di/module/types/DiRegistrar.ts +24 -0
  166. package/core/di/module/types/index.ts +2 -0
  167. package/core/di/provider/index.ts +26 -0
  168. package/core/di/provider/providerGuards.ts +17 -0
  169. package/core/di/provider/types/AsyncFactoryProvider.ts +15 -0
  170. package/core/di/provider/types/ClassProvider.ts +18 -0
  171. package/core/di/provider/types/FactoryProvider.ts +20 -0
  172. package/core/di/provider/types/KeyedDependency.ts +20 -0
  173. package/core/di/provider/types/LazyDependency.ts +31 -0
  174. package/core/di/provider/types/NamedDependency.ts +16 -0
  175. package/core/di/provider/types/Provider.ts +10 -0
  176. package/core/di/provider/types/ProviderDefinition.ts +11 -0
  177. package/core/di/provider/types/ProviderDependencyList.ts +11 -0
  178. package/core/di/provider/types/ProviderLifetime.ts +1 -0
  179. package/core/di/provider/types/ProviderOwnership.ts +7 -0
  180. package/core/di/provider/types/ResolvedDeps.ts +18 -0
  181. package/core/di/provider/types/ValueProvider.ts +6 -0
  182. package/core/di/provider/types/index.ts +13 -0
  183. package/core/di/token.ts +84 -0
  184. package/core/di/types/BuildServiceProviderOptions.ts +4 -0
  185. package/core/di/types/ServiceKey.ts +1 -0
  186. package/core/di/types/ServiceResolver.ts +16 -0
  187. package/core/di/types/index.ts +3 -0
  188. package/core/generatedFingerprint.ts +60 -0
  189. package/core/generatedRuntime.ts +187 -0
  190. package/core/grpc/Grpc.module.ts +23 -0
  191. package/core/grpc/GrpcBinding.contract.ts +35 -0
  192. package/core/grpc/GrpcCall.ts +73 -0
  193. package/core/grpc/GrpcClient.ts +172 -0
  194. package/core/grpc/GrpcClientCall.ts +267 -0
  195. package/core/grpc/GrpcError.ts +19 -0
  196. package/core/grpc/GrpcRequest.binding.ts +45 -0
  197. package/core/grpc/GrpcServer.ts +204 -0
  198. package/core/grpc/GrpcStatus.ts +8 -0
  199. package/core/grpc/GrpcTransport.ts +174 -0
  200. package/core/grpc/Metadata.ts +73 -0
  201. package/core/grpc/ProtoCodec.ts +225 -0
  202. package/core/grpc/ProtoParser.ts +192 -0
  203. package/core/grpc/ProtoReader.ts +34 -0
  204. package/core/grpc/ProtoSchema.ts +52 -0
  205. package/core/grpc/ServerCredentials.ts +30 -0
  206. package/core/grpc/clientContracts.ts +39 -0
  207. package/core/grpc/contracts.ts +45 -0
  208. package/core/grpc/decorators.ts +82 -0
  209. package/core/grpc/grpcClientProvider.ts +9 -0
  210. package/core/grpc/index.ts +17 -0
  211. package/core/grpc/moduleControllers.ts +38 -0
  212. package/core/grpc/protobuf.ts +80 -0
  213. package/core/grpc/serviceDefinition.ts +20 -0
  214. package/core/http/Authorization/Authorize.ts +52 -0
  215. package/core/http/Authorization/authorizeComposer.ts +31 -0
  216. package/core/http/Authorization/metadata.ts +158 -0
  217. package/core/http/Binding/ParameterBinder.ts +109 -0
  218. package/core/http/Binding/RequestModel.ts +27 -0
  219. package/core/http/Binding/autoBindings.ts +125 -0
  220. package/core/http/Binding/bindings.ts +19 -0
  221. package/core/http/Binding/convert.ts +48 -0
  222. package/core/http/Binding/generatedSpec.ts +18 -0
  223. package/core/http/Binding/listModelRegistry.ts +47 -0
  224. package/core/http/Binding/modelBinder.ts +345 -0
  225. package/core/http/Binding/modelValidator.ts +30 -0
  226. package/core/http/Binding/requestModelRegistry.ts +117 -0
  227. package/core/http/Decorators/attributes.ts +92 -0
  228. package/core/http/Decorators/controller.ts +24 -0
  229. package/core/http/Decorators/metadata.ts +107 -0
  230. package/core/http/Decorators/routes.ts +131 -0
  231. package/core/http/Errors/HttpError.ts +92 -0
  232. package/core/http/HttpContext/HttpContext.ts +148 -0
  233. package/core/http/HttpContext/ResponseBuilder.ts +37 -0
  234. package/core/http/HttpContext/inspectableRedirects.ts +47 -0
  235. package/core/http/HttpContext/principal.ts +24 -0
  236. package/core/http/HttpContext/responseLifetime.ts +45 -0
  237. package/core/http/HttpServer.ts +627 -0
  238. package/core/http/Middleware/accessLog.ts +90 -0
  239. package/core/http/Middleware/cors.ts +160 -0
  240. package/core/http/Middleware/errorHandler.ts +100 -0
  241. package/core/http/Middleware/pipeline.ts +21 -0
  242. package/core/http/Middleware/rateLimit.ts +104 -0
  243. package/core/http/Middleware/securityHeaders.ts +118 -0
  244. package/core/http/Middleware/types.ts +19 -0
  245. package/core/http/OpenApi/generatedOpenApiRegistry.ts +102 -0
  246. package/core/http/OpenApi/openApiDocs.ts +75 -0
  247. package/core/http/OpenApi/openApiDocument.ts +356 -0
  248. package/core/http/README.md +139 -0
  249. package/core/http/Results/HttpResult.ts +19 -0
  250. package/core/http/Results/normalize.ts +93 -0
  251. package/core/http/Results/results.ts +70 -0
  252. package/core/http/Routing/Router.ts +201 -0
  253. package/core/http/Routing/RouterBuilder.ts +184 -0
  254. package/core/http/Routing/template.ts +112 -0
  255. package/core/http/SPEC.md +981 -0
  256. package/core/http/Versioning/VersionReader.ts +20 -0
  257. package/core/http/WebSocketUpgrade.ts +29 -0
  258. package/core/http/composeRouteMiddlewareComposers.ts +21 -0
  259. package/core/http/correlation/createCorrelationIdMiddleware.ts +79 -0
  260. package/core/http/httpModule.ts +48 -0
  261. package/core/http/index.ts +140 -0
  262. package/core/http/middlewareTokens.ts +48 -0
  263. package/core/http/options.ts +134 -0
  264. package/core/http-client/index.ts +105 -0
  265. package/core/infra/Infra.ts +158 -0
  266. package/core/infra/InfraConnector.ts +86 -0
  267. package/core/infra/InfraLifecycle.ts +86 -0
  268. package/core/infra/cache/RedisDistributedCacheBackend.ts +88 -0
  269. package/core/infra/cache/RedisDistributedCacheDriver.ts +186 -0
  270. package/core/infra/cache/index.ts +7 -0
  271. package/core/infra/connectorConfig.ts +29 -0
  272. package/core/infra/connectorIdentity.ts +39 -0
  273. package/core/infra/connectors/codex/CodexAppServer.ts +146 -0
  274. package/core/infra/connectors/codex/CodexAppServerClient.ts +258 -0
  275. package/core/infra/connectors/codex/CodexPolicy.ts +114 -0
  276. package/core/infra/connectors/codex/CodexTurn.ts +133 -0
  277. package/core/infra/connectors/codex/contracts.ts +82 -0
  278. package/core/infra/connectors/codex.ts +26 -0
  279. package/core/infra/connectors/llm.ts +78 -0
  280. package/core/infra/connectors/llmRouter.ts +443 -0
  281. package/core/infra/connectors/openaiCompatible.ts +590 -0
  282. package/core/infra/connectors/openaiTextStream.ts +134 -0
  283. package/core/infra/connectors/opensearch.ts +307 -0
  284. package/core/infra/connectors/postgres.ts +105 -0
  285. package/core/infra/connectors/redis.ts +132 -0
  286. package/core/infra/index.ts +58 -0
  287. package/core/kernel/ApplicationLifetime.ts +91 -0
  288. package/core/kernel/Bazis.ts +73 -0
  289. package/core/kernel/Environment.ts +53 -0
  290. package/core/kernel/Kernel.ts +391 -0
  291. package/core/kernel/KernelBuilder.ts +172 -0
  292. package/core/kernel/LifecycleCoordinator.ts +204 -0
  293. package/core/kernel/README.md +66 -0
  294. package/core/kernel/SupervisedHostedService.ts +147 -0
  295. package/core/kernel/config/ConfigRegistry.ts +48 -0
  296. package/core/kernel/config/Configuration.ts +110 -0
  297. package/core/kernel/config/README.md +62 -0
  298. package/core/kernel/config/Secret.ts +29 -0
  299. package/core/kernel/config/addConfigOptions.ts +63 -0
  300. package/core/kernel/config/defineConfig.ts +211 -0
  301. package/core/kernel/config/sources.ts +123 -0
  302. package/core/kernel/correlation/requestContext.ts +57 -0
  303. package/core/kernel/errors/ConfigKeyMissingError.ts +7 -0
  304. package/core/kernel/errors/KernelError.ts +7 -0
  305. package/core/kernel/errors/ShutdownTimeoutError.ts +7 -0
  306. package/core/kernel/errors/StartupAbortedError.ts +7 -0
  307. package/core/kernel/errors/StartupTimeoutError.ts +7 -0
  308. package/core/kernel/errors/index.ts +5 -0
  309. package/core/kernel/events/EventBus.ts +140 -0
  310. package/core/kernel/events/EventToken.ts +17 -0
  311. package/core/kernel/events/eventSubscribers.ts +126 -0
  312. package/core/kernel/events/kernelEvents.ts +16 -0
  313. package/core/kernel/events/onEvent.ts +32 -0
  314. package/core/kernel/health/HealthCheckContracts.ts +42 -0
  315. package/core/kernel/health/HealthService.ts +93 -0
  316. package/core/kernel/index.ts +96 -0
  317. package/core/kernel/internal/awaitAbortable.ts +18 -0
  318. package/core/kernel/internal/awaitShutdown.ts +21 -0
  319. package/core/kernel/internal/reportDiagnosticFailure.ts +8 -0
  320. package/core/kernel/internal/validateTimeout.ts +8 -0
  321. package/core/kernel/lifecycleHooks.ts +18 -0
  322. package/core/kernel/logging/ConsoleLogger.ts +68 -0
  323. package/core/kernel/logging/Logger.ts +22 -0
  324. package/core/kernel/types/ConfigSource.ts +9 -0
  325. package/core/kernel/types/EnvironmentName.ts +1 -0
  326. package/core/kernel/types/KernelOptions.ts +23 -0
  327. package/core/kernel/types/LifecycleHook.ts +18 -0
  328. package/core/kernel/types/index.ts +4 -0
  329. package/core/orm/DATABASE_PROVIDER.ts +5 -0
  330. package/core/orm/OrmHostedPlan.validator.ts +55 -0
  331. package/core/orm/OrmLifecycle.ts +146 -0
  332. package/core/orm/OrmOwnedStoreLifecycle.ts +96 -0
  333. package/core/orm/buildOrmProviders.ts +152 -0
  334. package/core/orm/databaseConnector.ts +108 -0
  335. package/core/orm/encapsulationHook.ts +19 -0
  336. package/core/orm/index.ts +95 -0
  337. package/core/orm/listQuery.ts +198 -0
  338. package/core/orm/ormModule.ts +173 -0
  339. package/core/orm/ownedStoreContributions.ts +195 -0
  340. package/core/orm/registerRepositories.ts +27 -0
  341. package/core/orm/repository.ts +45 -0
  342. package/core/orm/strictSchemaHostedIdentity.ts +17 -0
  343. package/core/scripts/agent-codegen.ts +1166 -0
  344. package/core/scripts/di-generate-target.ts +90 -0
  345. package/core/scripts/di-generate.ts +1837 -0
  346. package/core/scripts/orm-predicate-codegen.ts +33 -0
  347. package/core/scripts/request-model-codegen.ts +326 -0
  348. package/core/websocket/DESIGN.md +297 -0
  349. package/core/websocket/WsRateLimiter.ts +101 -0
  350. package/core/websocket/adapter/adapter.interface.ts +45 -0
  351. package/core/websocket/adapter/in-memory.adapter.ts +190 -0
  352. package/core/websocket/adapter/redis-delivery-scripts.ts +135 -0
  353. package/core/websocket/adapter/redis-delivery-store.ts +86 -0
  354. package/core/websocket/adapter/redis-operations.ts +33 -0
  355. package/core/websocket/adapter/redis.adapter.ts +218 -0
  356. package/core/websocket/codec/binary.codec.ts +87 -0
  357. package/core/websocket/codec/json.codec.ts +34 -0
  358. package/core/websocket/codec/packet-codec.interface.ts +17 -0
  359. package/core/websocket/decorators.ts +165 -0
  360. package/core/websocket/explorer.ts +126 -0
  361. package/core/websocket/index.ts +78 -0
  362. package/core/websocket/middleware.ts +146 -0
  363. package/core/websocket/packet-codec.ts +75 -0
  364. package/core/websocket/reliable-delivery.ts +56 -0
  365. package/core/websocket/session-creation.ts +16 -0
  366. package/core/websocket/session-manager.ts +856 -0
  367. package/core/websocket/socket-wrapper.ts +314 -0
  368. package/core/websocket/topic-cache.ts +59 -0
  369. package/core/websocket/types.ts +122 -0
  370. package/core/websocket/websocketModule.ts +96 -0
  371. package/core/websocket/ws-dispatch.ts +123 -0
  372. package/core/websocket/ws-server.ts +1707 -0
  373. package/index.ts +281 -0
  374. package/library/boundary/diagnostics-v1.ts +136 -0
  375. package/library/boundary/index.ts +73 -0
  376. package/library/boundary/json/decodeBoundedJsonV1.ts +518 -0
  377. package/library/boundary/json/limits-v1.ts +46 -0
  378. package/library/boundary/json/normalizeBoundedJsonV1.ts +256 -0
  379. package/library/boundary/json/types-v1.ts +11 -0
  380. package/library/boundary/schema/boundarySchemaHashV1.ts +6 -0
  381. package/library/boundary/schema/collectBoundaryValueDiagnosticsV1.ts +325 -0
  382. package/library/boundary/schema/decodeBoundarySchemaV1.ts +646 -0
  383. package/library/boundary/schema/index.ts +8 -0
  384. package/library/boundary/schema/types-v1.ts +99 -0
  385. package/library/boundary/schema/validateBoundaryValueV1.ts +58 -0
  386. package/library/boundary/serialization/canonicalJsonV1.ts +66 -0
  387. package/library/http-client/HttpClient.ts +969 -0
  388. package/library/http-client/HttpClientFactory.ts +45 -0
  389. package/library/http-client/errors.ts +68 -0
  390. package/library/http-client/index.ts +43 -0
  391. package/library/http-client/interceptors.ts +40 -0
  392. package/library/http-client/progress.ts +62 -0
  393. package/library/http-client/redirectProtocol.ts +6 -0
  394. package/library/http-client/serialize.ts +133 -0
  395. package/library/http-client/types.ts +174 -0
  396. package/library/jsonapi/ListQueryError.ts +25 -0
  397. package/library/jsonapi/ListRequest.ts +37 -0
  398. package/library/jsonapi/decorators.ts +161 -0
  399. package/library/jsonapi/document.ts +124 -0
  400. package/library/jsonapi/index.ts +40 -0
  401. package/library/jsonapi/parseListQuery.ts +291 -0
  402. package/library/jsonapi/types.ts +125 -0
  403. package/library/jwt/JwtEncoder.ts +40 -0
  404. package/library/jwt/JwtKeyRing.ts +164 -0
  405. package/library/jwt/JwtValidator.ts +210 -0
  406. package/library/jwt/TokenIssuer.ts +149 -0
  407. package/library/jwt/TokenService.ts +51 -0
  408. package/library/jwt/base64url.ts +61 -0
  409. package/library/jwt/claims.ts +36 -0
  410. package/library/jwt/errors.ts +44 -0
  411. package/library/jwt/index.ts +59 -0
  412. package/library/jwt/limits.ts +8 -0
  413. package/library/jwt/signing/Hs256Algorithm.ts +62 -0
  414. package/library/jwt/signing/Rs256Algorithm.ts +133 -0
  415. package/library/jwt/signing/SigningAlgorithm.ts +18 -0
  416. package/library/jwt/signing/pem.ts +30 -0
  417. package/library/openapi/codegen.ts +875 -0
  418. package/library/openapi/document.ts +326 -0
  419. package/library/openapi/index.ts +13 -0
  420. package/library/openapi/types.ts +69 -0
  421. package/library/openapi/ui.ts +182 -0
  422. package/library/orm/DatabaseFacade.ts +209 -0
  423. package/library/orm/DbContext.ts +107 -0
  424. package/library/orm/DbContextFactory.ts +25 -0
  425. package/library/orm/DbContextOptions.ts +33 -0
  426. package/library/orm/Metadata/DynamicModelBuilder.ts +497 -0
  427. package/library/orm/Metadata/KeyTuple.ts +36 -0
  428. package/library/orm/Metadata/ModelBuilder.ts +299 -0
  429. package/library/orm/Metadata/OrmModel.ts +80 -0
  430. package/library/orm/Metadata/ValueConverter.ts +57 -0
  431. package/library/orm/Metadata/conventions.ts +54 -0
  432. package/library/orm/Metadata/decorators.ts +396 -0
  433. package/library/orm/Metadata/types.ts +140 -0
  434. package/library/orm/Providers/OwnedStoreCatalog.reader.ts +1802 -0
  435. package/library/orm/Providers/PostgresDialect.ts +234 -0
  436. package/library/orm/Providers/PostgresProvider.ts +1494 -0
  437. package/library/orm/Providers/PostgresSchema.decoder.ts +107 -0
  438. package/library/orm/Providers/limits.ts +29 -0
  439. package/library/orm/Providers/operationDeadline.ts +43 -0
  440. package/library/orm/Providers/ormOwnedStoreRuntime.ts +19 -0
  441. package/library/orm/Providers/ormTransactionRuntime.ts +117 -0
  442. package/library/orm/Providers/propertyConversion.ts +14 -0
  443. package/library/orm/Providers/resolvedForeignKey.ts +16 -0
  444. package/library/orm/Providers/transactionCallbacks.ts +45 -0
  445. package/library/orm/Providers/transactionOutcome.ts +82 -0
  446. package/library/orm/Providers/transactionScopes.ts +78 -0
  447. package/library/orm/Providers/types.ts +207 -0
  448. package/library/orm/Query/DbSet.ts +78 -0
  449. package/library/orm/Query/EntityQuery.ts +247 -0
  450. package/library/orm/Query/ImmediateMutations.ts +226 -0
  451. package/library/orm/Query/IncludeLoader.ts +200 -0
  452. package/library/orm/Query/QueryPlan.ts +55 -0
  453. package/library/orm/Query/SqlTranslator.ts +195 -0
  454. package/library/orm/Query/conditions.ts +127 -0
  455. package/library/orm/Query/materialize.ts +39 -0
  456. package/library/orm/README.md +256 -0
  457. package/library/orm/Repository/README.md +684 -0
  458. package/library/orm/Repository/Repository.ts +68 -0
  459. package/library/orm/Saving/CommandBuilder.ts +139 -0
  460. package/library/orm/Saving/ExecutionStrategy.ts +128 -0
  461. package/library/orm/Saving/SaveExecutor.ts +413 -0
  462. package/library/orm/Saving/applyConventions.ts +64 -0
  463. package/library/orm/Schema/CheckExpression.ts +327 -0
  464. package/library/orm/Schema/ExactSchemaVerifier.ts +168 -0
  465. package/library/orm/Schema/ExpectedSchema.ts +43 -0
  466. package/library/orm/Schema/MigrationRunner.ts +146 -0
  467. package/library/orm/Schema/Migrator.ts +73 -0
  468. package/library/orm/Schema/OrmOwnedStore.ts +123 -0
  469. package/library/orm/Schema/OwnedStoreAdmission.ts +752 -0
  470. package/library/orm/Schema/OwnedStoreCanonical.ts +273 -0
  471. package/library/orm/Schema/OwnedStoreCatalog.ts +1325 -0
  472. package/library/orm/Schema/SafeAdditiveSchema.ts +100 -0
  473. package/library/orm/Schema/SchemaAdmission.ts +62 -0
  474. package/library/orm/Schema/SchemaDiffer.ts +78 -0
  475. package/library/orm/Schema/formatSchemaDifferences.ts +62 -0
  476. package/library/orm/Schema/introspection.ts +52 -0
  477. package/library/orm/Schema/physicalColumnTypes.ts +37 -0
  478. package/library/orm/Schema/tableKey.ts +26 -0
  479. package/library/orm/Tracking/ChangeTracker.ts +448 -0
  480. package/library/orm/Tracking/EntityState.ts +13 -0
  481. package/library/orm/Transactions/OrmTransaction.ts +30 -0
  482. package/library/orm/Transactions/TransactionScopeCoordinator.ts +377 -0
  483. package/library/orm/errors.ts +190 -0
  484. package/library/orm/index.ts +162 -0
  485. package/library/orm/runtime.ts +14 -0
  486. package/library/redaction/index.ts +166 -0
  487. package/library/ui/UiProfile.ts +77 -0
  488. package/library/ui/compiled-v1.ts +131 -0
  489. package/library/ui/compiler/compileUiSurfaceV1.ts +717 -0
  490. package/library/ui/compiler/contracts-v1.ts +25 -0
  491. package/library/ui/compiler/index.ts +12 -0
  492. package/library/ui/compiler/openApiIndex.ts +246 -0
  493. package/library/ui/defineUiProfile.ts +340 -0
  494. package/library/ui/diagnostics-v1.ts +33 -0
  495. package/library/ui/index.ts +129 -0
  496. package/library/ui/profile-v1.ts +191 -0
  497. package/library/ui/serialization.ts +130 -0
  498. package/library/ui/uiProfileAuthoring.ts +289 -0
  499. package/library/ui/uiProfileAuthoringMetadata.ts +78 -0
  500. package/library/validation/MessageRegistry.ts +144 -0
  501. package/library/validation/README.md +62 -0
  502. package/library/validation/RuleCompiler.ts +183 -0
  503. package/library/validation/RuleEngine.ts +401 -0
  504. package/library/validation/SPEC.md +579 -0
  505. package/library/validation/ValidationError.ts +37 -0
  506. package/library/validation/ValidationResult.ts +63 -0
  507. package/library/validation/Validator.ts +101 -0
  508. package/library/validation/index.ts +16 -0
  509. package/library/validation/metadata.ts +69 -0
  510. package/library/validation/modelValidatorAdapter.ts +119 -0
  511. package/library/validation/types/ValidationCode.ts +69 -0
  512. package/library/validation/types/ValidatorOptions.ts +153 -0
  513. package/package.json +80 -0
@@ -0,0 +1,1802 @@
1
+ import { types } from "node:util";
2
+ import type { Row, SqlParam } from "./types";
3
+ import { failure } from "./ormOwnedStoreRuntime";
4
+ import { canonicalPostgresType, canonicalPostgresDefault, canonicalPostgresCheck, exactPostgresType } from "./PostgresSchema.decoder";
5
+ import type { OrmCatalogScopeV1 } from "../Schema/OrmOwnedStore";
6
+ import type { OwnedCatalogArrayTypeV1, OwnedCatalogClassV1, OwnedCatalogColumnV1, OwnedCatalogConstraintV1, OwnedCatalogDependencyV1, OwnedCatalogIndexV1, OwnedCatalogInheritanceV1, OwnedCatalogPolicyV1, OwnedCatalogRelationV1, OwnedCatalogRowTypeV1, OwnedCatalogRuleV1, OwnedCatalogSequenceV1, OwnedCatalogTriggerV1, OwnedStoreCatalogSnapshotV1, OwnedStoreRegistryRowV1, OwnedStoreRegistryShapeV1, OwnedStoreRegistrySnapshotV1 } from "../Schema/OwnedStoreCatalog";
7
+ interface OwnedStoreConstraintParentV1 {
8
+ readonly value: OwnedCatalogConstraintV1;
9
+ readonly widths: readonly [
10
+ number,
11
+ number,
12
+ number,
13
+ number,
14
+ number,
15
+ number
16
+ ];
17
+ }
18
+ /** Read-only capability: the provider retains the reservation and admission state. */
19
+ export interface OwnedStoreCatalogSource {
20
+ query(sql: string, params: readonly SqlParam[], operation: "registry-read" | "catalog-read"): Promise<unknown>;
21
+ assertActive(): void;
22
+ unavailable(): never;
23
+ drift(): never;
24
+ }
25
+ /** Builds bounded catalog snapshots; it never owns a connection or a transaction. */
26
+ export class OwnedStoreCatalogReader {
27
+ public constructor(private readonly source: OwnedStoreCatalogSource) {
28
+ }
29
+ public async readRegistry(): Promise<OwnedStoreRegistrySnapshotV1> {
30
+ const publicResult = await this.source.query("SELECT EXISTS (SELECT 1 FROM pg_catalog.pg_namespace AS n WHERE n.nspname = 'public') AS public_schema_exists", [], "registry-read");
31
+ this.source.assertActive();
32
+ const publicRows = selectOwnedStoreRows(publicResult, ["public_schema_exists"], 1);
33
+ const publicSchemaExists = publicRows?.[0]?.public_schema_exists;
34
+ if (!publicRows || typeof publicSchemaExists !== "boolean" || publicRows.length !== 1) {
35
+ this.source.unavailable();
36
+ }
37
+ const rootResult = await this.source.query("SELECT c.oid::pg_catalog.text AS relation_oid FROM pg_catalog.pg_class AS c JOIN pg_catalog.pg_namespace AS n ON n.oid = c.relnamespace WHERE n.nspname = 'public' AND c.relname = '__bazis_orm_owned_stores_v1'", [], "registry-read");
38
+ this.source.assertActive();
39
+ const roots = selectOwnedStoreRows(rootResult, ["relation_oid"], 1);
40
+ if (!roots || (roots.length === 1 && typeof roots[0]!.relation_oid !== "string")) {
41
+ this.source.unavailable();
42
+ }
43
+ if (roots.length === 0)
44
+ return Object.freeze({
45
+ contract: "bazis.orm-owned-store-registry-snapshot/v1", publicSchemaExists, state: Object.freeze({ kind: "absent" as const })
46
+ });
47
+ const rootOid = roots[0]!.relation_oid;
48
+ if (!this.oid(rootOid) || !publicSchemaExists) {
49
+ this.source.drift();
50
+ }
51
+ const budget = { remaining: 65536 };
52
+ const rootsGraph = await this.readRelations([rootOid], "registry-read", budget);
53
+ const root = rootsGraph[0];
54
+ if (!root || root.schema !== "public" || root.name !== "__bazis_orm_owned_stores_v1" || root.kind !== "ordinaryTable" || root.rawKind !== "r" || root.rowTypeOid === null) {
55
+ this.source.drift();
56
+ }
57
+ const graph = await this.readRelationGraph(rootsGraph, "registry-read", budget);
58
+ const knownClasses = await this.readCatalogClasses("registry-read");
59
+ const ledger = await this.readDependencyLedger(graph, knownClasses, "registry-read", budget);
60
+ const shape = this.registryShape(root, graph, ledger);
61
+ const rows = await this.readRegistryRows();
62
+ return Object.freeze({
63
+ contract: "bazis.orm-owned-store-registry-snapshot/v1", publicSchemaExists, state: Object.freeze({ kind: "present" as const, shape, rows })
64
+ });
65
+ }
66
+ private async readRegistryRows(): Promise<readonly OwnedStoreRegistryRowV1[]> {
67
+ const aliases = [
68
+ "store_key", "contract", "format_version", "owned_schema", "table_prefix", "owned_scope_hash", "model_hash", "created_at_epoch_microseconds"
69
+ ] as const;
70
+ const result = await this.source.query("SELECT store_key,contract,format_version::pg_catalog.text AS format_version,owned_schema,table_prefix,owned_scope_hash,model_hash,pg_catalog.floor(EXTRACT(epoch FROM created_at)*1000000)::pg_catalog.numeric(19,0)::pg_catalog.text AS created_at_epoch_microseconds FROM \"public\".\"__bazis_orm_owned_stores_v1\" ORDER BY pg_catalog.convert_to(store_key,'UTF8') LIMIT 4097", [], "registry-read");
71
+ const rows = selectOwnedStoreRows(result, aliases, 4097);
72
+ if (!rows) {
73
+ this.source.unavailable();
74
+ }
75
+ this.wireRows(rows as readonly Row[], aliases);
76
+ if (rows.length === 4097) {
77
+ this.source.drift();
78
+ }
79
+ const output: OwnedStoreRegistryRowV1[] = [];
80
+ for (const row of rows) {
81
+ if (!aliases.every(alias => typeof row[alias] === "string")) {
82
+ this.source.unavailable();
83
+ }
84
+ const formatVersion = row.format_version as string, epoch = row.created_at_epoch_microseconds as string;
85
+ if (!/^[1-9][0-9]*$/u.test(formatVersion) || BigInt(formatVersion) > BigInt(Number.MAX_SAFE_INTEGER) || !/^(?:0|[1-9][0-9]*)$/u.test(epoch) || BigInt(epoch) > 8640000000000000000n) {
86
+ this.source.drift();
87
+ }
88
+ const contract = row.contract as string;
89
+ if (contract !== "bazis.orm-owned-store/v1") {
90
+ this.source.drift();
91
+ }
92
+ output.push(Object.freeze({
93
+ storeKey: row.store_key as string, contract, formatVersion, ownedSchema: row.owned_schema as string, tablePrefix: row.table_prefix as string, ownedScopeHash: row.owned_scope_hash as OwnedStoreRegistryRowV1["ownedScopeHash"], modelHash: row.model_hash as OwnedStoreRegistryRowV1["modelHash"], createdAtEpochMicroseconds: epoch
94
+ }));
95
+ }
96
+ output.sort((left, right) => Buffer.compare(Buffer.from(left.storeKey, "utf8"), Buffer.from(right.storeKey, "utf8")));
97
+ return Object.freeze(output);
98
+ }
99
+ private registryShape(root: OwnedCatalogRelationV1, graph: Readonly<Omit<OwnedStoreCatalogSnapshotV1, "contract" | "requestedScopes" | "existingSchemas" | "catalogClasses" | "dependencies">>, ledger: Readonly<Pick<OwnedStoreCatalogSnapshotV1, "catalogClasses" | "dependencies">>): OwnedStoreRegistryShapeV1 {
100
+ const drift = (): never => {
101
+ this.source.drift();
102
+ };
103
+ if (root.kind !== "ordinaryTable" || graph.rowTypes.length !== 1 || graph.arrayTypes.length !== 1)
104
+ drift();
105
+ const rowType = graph.rowTypes[0]!, arrayType = graph.arrayTypes[0]!;
106
+ if (root.rowTypeOid !== rowType.oid || rowType.relationOid !== root.oid || rowType.arrayTypeOid !== arrayType.oid || arrayType.elementTypeOid !== rowType.oid)
107
+ drift();
108
+ const byOid = new Map(graph.relations.map(value => [value.oid, value]));
109
+ const relationFor = (oid: string): OwnedCatalogRelationV1 => byOid.get(oid) ?? drift();
110
+ const sort = (values: readonly OwnedCatalogRelationV1[]) => Object.freeze([...values].sort((left, right) => BigInt(left.oid) < BigInt(right.oid) ? -1 : BigInt(left.oid) > BigInt(right.oid) ? 1 : 0));
111
+ const toast = root.toastRelationOid === null ? null : relationFor(root.toastRelationOid);
112
+ if (toast !== null && toast.kind !== "toastTable")
113
+ drift();
114
+ const rootIndexes = graph.indexes.filter(value => value.tableRelationOid === root.oid);
115
+ const toastIndexes = toast === null ? [] : graph.indexes.filter(value => value.tableRelationOid === toast.oid);
116
+ if (graph.indexes.length !== rootIndexes.length + toastIndexes.length || graph.columns.some(value => value.relationOid !== root.oid && value.relationOid !== toast?.oid))
117
+ drift();
118
+ const rootIndexRelations = sort(rootIndexes.map(value => relationFor(value.indexRelationOid)));
119
+ const toastIndexRelations = sort(toastIndexes.map(value => relationFor(value.indexRelationOid)));
120
+ const represented = new Set<string>([
121
+ root.oid, ...rootIndexRelations.map(value => value.oid), ...(toast === null ? [] : [toast.oid, ...toastIndexRelations.map(value => value.oid)])
122
+ ]);
123
+ if (graph.relations.length !== represented.size || graph.relations.some(value => !represented.has(value.oid)))
124
+ drift();
125
+ const pgClass = ledger.catalogClasses.find(value => value.kind === "pg_class")?.oid ?? drift();
126
+ const toastIds = new Set(toast === null ? [] : [toast.oid, ...toastIndexRelations.map(value => value.oid)]);
127
+ const nested: OwnedCatalogDependencyV1[] = [], outer: OwnedCatalogDependencyV1[] = [];
128
+ for (const value of ledger.dependencies)
129
+ (value.dependentClassOid === pgClass && toastIds.has(value.dependentOid) ? nested : outer).push(value);
130
+ const columns = Object.freeze(graph.columns.filter(value => value.relationOid === root.oid));
131
+ const shape: OwnedStoreRegistryShapeV1 = Object.freeze({
132
+ catalogClasses: ledger.catalogClasses, relation: root, rowType, arrayType, columns, indexes: Object.freeze(rootIndexes), indexRelations: rootIndexRelations, constraints: graph.constraints, triggers: graph.triggers, rules: graph.rules, policies: graph.policies, inheritance: graph.inheritance, dependencies: Object.freeze(outer), sequences: graph.sequences, toast: toast === null ? null : Object.freeze({
133
+ ownerTableOid: root.oid, relation: toast, columns: Object.freeze(graph.columns.filter(value => value.relationOid === toast.oid)), indexes: Object.freeze(toastIndexes), indexRelations: toastIndexRelations, dependencies: Object.freeze(nested)
134
+ })
135
+ });
136
+ return shape;
137
+ }
138
+ public async readCatalog(scopes: readonly OrmCatalogScopeV1[]): Promise<OwnedStoreCatalogSnapshotV1> {
139
+ const requestedScopes = this.catalogScopes(scopes);
140
+ const existingSchemas: string[] = [];
141
+ for (let offset = 0; offset < requestedScopes.length; offset += 512) {
142
+ const batch = requestedScopes.slice(offset, offset + 512), values: string[] = [];
143
+ const rows = batch.map((scope, index) => {
144
+ values.push(scope.schema, scope.tablePrefix);
145
+ const first = index * 2 + 1;
146
+ return `($${first}::pg_catalog.text,$${first + 1}::pg_catalog.text)`;
147
+ }).join(",");
148
+ const result = await this.source.query(`WITH requested(schema_name, table_prefix) AS (VALUES ${rows}) SELECT n.nspname AS schema_name FROM pg_catalog.pg_namespace AS n WHERE EXISTS (SELECT 1 FROM requested AS r WHERE r.schema_name = n.nspname) ORDER BY pg_catalog.convert_to(n.nspname, 'UTF8') LIMIT 513`, values, "catalog-read");
149
+ const selected = selectOwnedStoreRows(result, ["schema_name"], 513);
150
+ if (!selected) {
151
+ this.source.unavailable();
152
+ }
153
+ this.wireRows(selected as readonly Row[], ["schema_name"]);
154
+ if (selected.length === 513) {
155
+ this.source.drift();
156
+ }
157
+ const batchSchemas = new Set<string>();
158
+ for (const row of selected) {
159
+ if (typeof row.schema_name !== "string") {
160
+ this.source.unavailable();
161
+ }
162
+ if (!batch.some(scope => scope.schema === row.schema_name) || batchSchemas.has(row.schema_name)) {
163
+ this.source.drift();
164
+ }
165
+ batchSchemas.add(row.schema_name);
166
+ if (!existingSchemas.includes(row.schema_name))
167
+ existingSchemas.push(row.schema_name);
168
+ }
169
+ }
170
+ existingSchemas.sort((left, right) => Buffer.compare(Buffer.from(left, "utf8"), Buffer.from(right, "utf8")));
171
+ const budget = { remaining: 65536 };
172
+ const roots = await this.readCatalogueRoots(requestedScopes, budget);
173
+ const graph = await this.readRelationGraph(roots, "catalog-read", budget);
174
+ const knownClasses = await this.readCatalogClasses("catalog-read");
175
+ const ledger = await this.readDependencyLedger(graph, knownClasses, "catalog-read", budget);
176
+ return Object.freeze({
177
+ contract: "bazis.orm-owned-store-catalog-snapshot/v1", requestedScopes, existingSchemas: Object.freeze(existingSchemas), ...graph, ...ledger
178
+ });
179
+ }
180
+ private chargeRecords(budget: {
181
+ remaining: number;
182
+ }, count: number): void {
183
+ if (!Number.isSafeInteger(count) || count < 0 || count > budget.remaining) {
184
+ this.source.drift();
185
+ }
186
+ budget.remaining -= count;
187
+ }
188
+ private async readRelationGraph(roots: readonly OwnedCatalogRelationV1[], operation: "registry-read" | "catalog-read", budget: {
189
+ remaining: number;
190
+ }): Promise<Readonly<Omit<OwnedStoreCatalogSnapshotV1, "contract" | "requestedScopes" | "existingSchemas" | "catalogClasses" | "dependencies">>> {
191
+ const drift = (): never => {
192
+ this.source.drift();
193
+ };
194
+ const compareOid = (left: string, right: string): number => BigInt(left) < BigInt(right) ? -1 : BigInt(left) > BigInt(right) ? 1 : 0;
195
+ const compareText = (left: string, right: string): number => Buffer.compare(Buffer.from(left, "utf8"), Buffer.from(right, "utf8"));
196
+ const relationsByOid = new Map(roots.map(relation => [relation.oid, relation]));
197
+ const toastOwners = new Map<string, string>();
198
+ for (const relation of roots)
199
+ if (relation.toastRelationOid !== null) {
200
+ if (toastOwners.has(relation.toastRelationOid))
201
+ drift();
202
+ toastOwners.set(relation.toastRelationOid, relation.oid);
203
+ }
204
+ const declaredToasts = await this.readRelations([...toastOwners.keys()].filter(oid => !relationsByOid.has(oid)), operation, budget);
205
+ for (const relation of declaredToasts)
206
+ relationsByOid.set(relation.oid, relation);
207
+ for (const oid of toastOwners.keys())
208
+ if (relationsByOid.get(oid)?.kind !== "toastTable")
209
+ drift();
210
+ const attachmentRelations = Object.freeze([...roots, ...declaredToasts]);
211
+ const eligibleToastOids = new Set(roots.filter(relation => relation.kind === "ordinaryTable").flatMap(relation => relation.toastRelationOid === null ? [] : [relation.toastRelationOid]));
212
+ const columns = await this.readColumns(attachmentRelations.filter(relation => relation.kind === "ordinaryTable" || eligibleToastOids.has(relation.oid)), operation, budget);
213
+ const indexes = await this.readIndexes(attachmentRelations, operation, budget);
214
+ const discoveredIndexes = await this.readRelations(indexes.map(index => index.indexRelationOid).filter(oid => !relationsByOid.has(oid)), operation, budget);
215
+ for (const relation of discoveredIndexes)
216
+ relationsByOid.set(relation.oid, relation);
217
+ for (const index of indexes) {
218
+ const relation = relationsByOid.get(index.indexRelationOid);
219
+ if ((relation?.kind !== "index" && relation?.kind !== "partitionedIndex") || relation.name !== index.name)
220
+ drift();
221
+ }
222
+ let relations = Object.freeze([...attachmentRelations, ...discoveredIndexes]);
223
+ if (columns.some(column => column.identityCode !== "")) {
224
+ const pgClassOid = await this.readPgClassOid(operation);
225
+ const identitySequenceOids = await this.readIdentitySequenceOids(columns, pgClassOid, operation);
226
+ const discoveredSequences = await this.readRelations(identitySequenceOids.filter(oid => !relationsByOid.has(oid)), operation, budget);
227
+ for (const relation of discoveredSequences)
228
+ relationsByOid.set(relation.oid, relation);
229
+ for (const oid of identitySequenceOids)
230
+ if (relationsByOid.get(oid)?.kind !== "sequence")
231
+ drift();
232
+ relations = Object.freeze([...relations, ...discoveredSequences]);
233
+ }
234
+ const [rowTypes, arrayTypes] = await this.readRelationTypes(relations, operation, budget);
235
+ const constraintParents = await this.readConstraintParents(relations, operation, budget);
236
+ const constraintVectors = await this.readConstraintVectors(constraintParents, operation);
237
+ const constraints = await this.readForeignKeyDefaultEquality(constraintVectors, operation);
238
+ const triggers = await this.readTriggers(relations, constraints, operation, budget);
239
+ const rules = await this.readRules(relations, operation, budget);
240
+ const policies = await this.readPolicies(relations, operation, budget);
241
+ const inheritance = await this.readInheritance(relations, operation, budget);
242
+ const sequences = await this.readSequences(relations, operation, budget);
243
+ return Object.freeze({
244
+ relations: Object.freeze([...relations].sort((left, right) => compareText(left.schema, right.schema) || compareText(left.name, right.name) || compareOid(left.oid, right.oid))),
245
+ rowTypes: Object.freeze([...rowTypes].sort((left, right) => compareOid(left.oid, right.oid))),
246
+ arrayTypes: Object.freeze([...arrayTypes].sort((left, right) => compareOid(left.oid, right.oid))),
247
+ columns: Object.freeze([...columns].sort((left, right) => compareOid(left.relationOid, right.relationOid) || compareOid(left.attnum, right.attnum))),
248
+ indexes: Object.freeze([...indexes].sort((left, right) => compareOid(left.tableRelationOid, right.tableRelationOid) || compareOid(left.indexRelationOid, right.indexRelationOid))),
249
+ constraints: Object.freeze([...constraints].sort((left, right) => compareOid(left.relationOid, right.relationOid) || compareText(left.name, right.name) || compareOid(left.oid, right.oid))),
250
+ triggers: Object.freeze([...triggers].sort((left, right) => compareOid(left.relationOid, right.relationOid) || compareText(left.name, right.name) || compareOid(left.oid, right.oid))),
251
+ rules: Object.freeze([...rules].sort((left, right) => compareOid(left.relationOid, right.relationOid) || compareText(left.name, right.name) || compareOid(left.oid, right.oid))),
252
+ policies: Object.freeze([...policies].sort((left, right) => compareOid(left.relationOid, right.relationOid) || compareText(left.name, right.name) || compareOid(left.oid, right.oid))),
253
+ inheritance: Object.freeze([...inheritance].sort((left, right) => compareOid(left.childRelationOid, right.childRelationOid) || compareOid(left.parentRelationOid, right.parentRelationOid) || compareOid(left.sequence, right.sequence))),
254
+ sequences: Object.freeze([...sequences].sort((left, right) => compareOid(left.relationOid, right.relationOid))),
255
+ });
256
+ }
257
+ private async readCatalogClasses(operation: "registry-read" | "catalog-read", optionalOids?: readonly string[]): Promise<readonly OwnedCatalogClassV1[]> {
258
+ const aliases = ["class_oid", "class_schema", "class_name"] as const;
259
+ const drift = (): never => {
260
+ this.source.drift();
261
+ };
262
+ const map = (rows: readonly Row[], issued?: ReadonlySet<string>): readonly OwnedCatalogClassV1[] => {
263
+ this.wireRows(rows, aliases);
264
+ const output: OwnedCatalogClassV1[] = [];
265
+ const seen = new Set<string>();
266
+ for (const row of rows) {
267
+ const oid = row.class_oid as string;
268
+ const schema = row.class_schema as string;
269
+ const name = row.class_name as string;
270
+ if (!this.oid(oid) || seen.has(oid) || (issued !== undefined && !issued.has(oid)))
271
+ drift();
272
+ seen.add(oid);
273
+ const kind = schema === "pg_catalog"
274
+ ? new Map<string, OwnedCatalogClassV1["kind"]>([
275
+ ["pg_class", "pg_class"], ["pg_type", "pg_type"], ["pg_constraint", "pg_constraint"], ["pg_proc", "pg_proc"], ["pg_rewrite", "pg_rewrite"], ["pg_namespace", "pg_namespace"], ["pg_attrdef", "pg_attrdef"], ["pg_trigger", "pg_trigger"]
276
+ ]).get(name) ?? "other"
277
+ : "other";
278
+ output.push(Object.freeze({ oid, schema: schema === "pg_catalog" ? "pg_catalog" : "other", name, kind }));
279
+ }
280
+ if (issued !== undefined && seen.size !== issued.size)
281
+ drift();
282
+ return Object.freeze(output.sort((left, right) => BigInt(left.oid) < BigInt(right.oid) ? -1 : BigInt(left.oid) > BigInt(right.oid) ? 1 : 0));
283
+ };
284
+ if (optionalOids !== undefined) {
285
+ if (!optionalOids.length)
286
+ return Object.freeze([]);
287
+ const output: OwnedCatalogClassV1[] = [];
288
+ for (let offset = 0; offset < optionalOids.length; offset += 1024) {
289
+ const batch = optionalOids.slice(offset, offset + 1024);
290
+ const result = await this.source.query("SELECT c.oid::pg_catalog.text AS class_oid,n.nspname AS class_schema,c.relname AS class_name FROM pg_catalog.pg_class AS c JOIN pg_catalog.pg_namespace AS n ON n.oid=c.relnamespace WHERE c.oid=ANY($1::pg_catalog.oid[]) ORDER BY c.oid LIMIT " + (batch.length + 1), [this.encodePgOidArrayParameter(batch)], operation);
291
+ const rows = selectOwnedStoreRows(result, aliases, batch.length + 1);
292
+ if (!rows) {
293
+ this.source.unavailable();
294
+ }
295
+ const captured = map(rows as readonly Row[], new Set(batch));
296
+ if (rows.length === batch.length + 1)
297
+ drift();
298
+ output.push(...captured);
299
+ }
300
+ if (output.length !== optionalOids.length || new Set(output.map(value => value.oid)).size !== output.length)
301
+ drift();
302
+ return Object.freeze(output.sort((left, right) => BigInt(left.oid) < BigInt(right.oid) ? -1 : BigInt(left.oid) > BigInt(right.oid) ? 1 : 0));
303
+ }
304
+ const names = [
305
+ "pg_class", "pg_type", "pg_constraint", "pg_proc", "pg_rewrite", "pg_namespace", "pg_attrdef", "pg_trigger", "pg_policy"
306
+ ] as const;
307
+ const result = await this.source.query("WITH requested(class_name) AS (VALUES ('pg_class'::pg_catalog.text),('pg_type'::pg_catalog.text),('pg_constraint'::pg_catalog.text),('pg_proc'::pg_catalog.text),('pg_rewrite'::pg_catalog.text),('pg_namespace'::pg_catalog.text),('pg_attrdef'::pg_catalog.text),('pg_trigger'::pg_catalog.text),('pg_policy'::pg_catalog.text)) SELECT c.oid::pg_catalog.text AS class_oid,n.nspname AS class_schema,c.relname AS class_name FROM requested AS r JOIN pg_catalog.pg_class AS c ON c.relname=r.class_name JOIN pg_catalog.pg_namespace AS n ON n.oid=c.relnamespace WHERE n.nspname='pg_catalog'::pg_catalog.name ORDER BY c.relname,c.oid LIMIT 10", [], operation);
308
+ const rows = selectOwnedStoreRows(result, aliases, 10);
309
+ if (!rows) {
310
+ this.source.unavailable();
311
+ }
312
+ const captured = map(rows as readonly Row[]);
313
+ if (rows.length !== names.length)
314
+ drift();
315
+ if (new Set(captured.map(value => value.name)).size !== names.length || names.some(name => !captured.some(value => value.schema === "pg_catalog" && value.name === name)))
316
+ drift();
317
+ return captured;
318
+ }
319
+ private async readDependencyLedger(graph: Readonly<Omit<OwnedStoreCatalogSnapshotV1, "contract" | "requestedScopes" | "existingSchemas" | "catalogClasses" | "dependencies">>, knownClasses: readonly OwnedCatalogClassV1[], operation: "registry-read" | "catalog-read", budget: {
320
+ remaining: number;
321
+ }): Promise<Readonly<Pick<OwnedStoreCatalogSnapshotV1, "dependencies" | "catalogClasses">>> {
322
+ const drift = (): never => {
323
+ this.source.drift();
324
+ };
325
+ const lock = (): never => {
326
+ this.source.unavailable();
327
+ };
328
+ if (!Number.isSafeInteger(budget.remaining) || budget.remaining < 0 || budget.remaining > 65536)
329
+ drift();
330
+ const knownByName = new Map<string, OwnedCatalogClassV1>();
331
+ const knownByOid = new Map<string, OwnedCatalogClassV1>();
332
+ for (const entry of knownClasses) {
333
+ if (knownByName.has(entry.name) || knownByOid.has(entry.oid))
334
+ drift();
335
+ knownByName.set(entry.name, entry);
336
+ knownByOid.set(entry.oid, entry);
337
+ }
338
+ const classOid = (name: string): string => {
339
+ const entry = knownByName.get(name) ?? drift();
340
+ if (entry.schema !== "pg_catalog")
341
+ drift();
342
+ return entry.oid;
343
+ };
344
+ const pgClass = classOid("pg_class"), pgType = classOid("pg_type"), pgConstraint = classOid("pg_constraint"), pgAttrdef = classOid("pg_attrdef"), pgTrigger = classOid("pg_trigger"), pgRewrite = classOid("pg_rewrite"), pgPolicy = classOid("pg_policy");
345
+ const seeds = new Map<string, readonly [
346
+ string,
347
+ string
348
+ ]>();
349
+ const seed = (classOid: string, objectOid: string): void => {
350
+ if (!this.oid(classOid) || !this.oid(objectOid))
351
+ drift();
352
+ seeds.set(`${classOid}:${objectOid}`, Object.freeze([classOid, objectOid]));
353
+ };
354
+ for (const relation of graph.relations)
355
+ seed(pgClass, relation.oid);
356
+ for (const type of graph.rowTypes)
357
+ seed(pgType, type.oid);
358
+ for (const type of graph.arrayTypes)
359
+ seed(pgType, type.oid);
360
+ for (const column of graph.columns)
361
+ if (column.defaultObjectOid !== null)
362
+ seed(pgAttrdef, column.defaultObjectOid);
363
+ for (const constraint of graph.constraints)
364
+ seed(pgConstraint, constraint.oid);
365
+ for (const trigger of graph.triggers)
366
+ seed(pgTrigger, trigger.oid);
367
+ for (const rule of graph.rules)
368
+ seed(pgRewrite, rule.oid);
369
+ for (const policy of graph.policies)
370
+ seed(pgPolicy, policy.oid);
371
+ const seedPairs = [...seeds.values()].sort((left, right) => BigInt(left[0]) < BigInt(right[0]) ? -1 : BigInt(left[0]) > BigInt(right[0]) ? 1 : BigInt(left[1]) < BigInt(right[1]) ? -1 : BigInt(left[1]) > BigInt(right[1]) ? 1 : 0);
372
+ if (seedPairs.length > 65536)
373
+ drift();
374
+ const baseClassOids = new Set<string>();
375
+ for (const name of operation === "catalog-read" ? ["pg_class", "pg_type", "pg_constraint", "pg_namespace", "pg_attrdef"] : ["pg_class", "pg_type", "pg_constraint", "pg_namespace"])
376
+ baseClassOids.add(classOid(name));
377
+ if (graph.constraints.some(constraint => constraint.kind === "foreignKey") || graph.triggers.length) {
378
+ baseClassOids.add(classOid("pg_proc"));
379
+ baseClassOids.add(classOid("pg_trigger"));
380
+ }
381
+ for (const pair of seedPairs)
382
+ baseClassOids.add(pair[0]);
383
+ this.chargeRecords(budget, baseClassOids.size);
384
+ const aliases = [
385
+ "dependent_class_oid", "dependent_oid", "dependent_sub_id", "referenced_class_oid", "referenced_oid", "referenced_sub_id", "dependency_type"
386
+ ] as const;
387
+ const rows: Row[] = [];
388
+ if (seedPairs.length) {
389
+ const parameters: string[] = [], branches: string[] = [];
390
+ for (let offset = 0; offset < seedPairs.length; offset += 1024) {
391
+ const batch = seedPairs.slice(offset, offset + 1024);
392
+ const classIds = batch.map(pair => pair[0]), objectIds = batch.map(pair => pair[1]);
393
+ parameters.push(this.encodePgOidArrayParameter(classIds), this.encodePgOidArrayParameter(objectIds));
394
+ const position = parameters.length - 1;
395
+ branches.push(`SELECT pair.classid,pair.objid FROM ROWS FROM (pg_catalog.unnest($${position}::pg_catalog.oid[]),pg_catalog.unnest($${position + 1}::pg_catalog.oid[])) WITH ORDINALITY AS pair(classid,objid,ordinality)`);
396
+ }
397
+ if (branches.length > 64)
398
+ drift();
399
+ const issuedLimit = budget.remaining + 1;
400
+ const result = await this.source.query(`WITH seeds(classid,objid) AS (${branches.join(" UNION ALL ")}) SELECT d.classid::pg_catalog.text AS dependent_class_oid,d.objid::pg_catalog.text AS dependent_oid,d.objsubid::pg_catalog.text AS dependent_sub_id,d.refclassid::pg_catalog.text AS referenced_class_oid,d.refobjid::pg_catalog.text AS referenced_oid,d.refobjsubid::pg_catalog.text AS referenced_sub_id,d.deptype::pg_catalog.text AS dependency_type FROM pg_catalog.pg_depend AS d WHERE EXISTS (SELECT 1 FROM seeds AS s WHERE s.classid=d.classid AND s.objid=d.objid) OR EXISTS (SELECT 1 FROM seeds AS s WHERE s.classid=d.refclassid AND s.objid=d.refobjid) ORDER BY d.classid,d.objid,d.objsubid,d.refclassid,d.refobjid,d.refobjsubid,d.deptype LIMIT ${issuedLimit}`, parameters, operation);
401
+ const selected = selectOwnedStoreRows(result, aliases, issuedLimit);
402
+ const selectedRows = selected ?? lock();
403
+ this.wireRows(selectedRows as readonly Row[], aliases);
404
+ this.chargeRecords(budget, selectedRows.length);
405
+ rows.push(...selectedRows as Row[]);
406
+ }
407
+ const decimalSubId = (value: string): boolean => /^(?:0|[1-9][0-9]*)$/u.test(value) && BigInt(value) <= 2147483647n;
408
+ const endpoints = new Set<string>();
409
+ const dependencies: OwnedCatalogDependencyV1[] = [];
410
+ for (const row of rows) {
411
+ const dependentClassOid = row.dependent_class_oid as string, dependentOid = row.dependent_oid as string, dependentSubId = row.dependent_sub_id as string, referencedClassOid = row.referenced_class_oid as string, referencedOid = row.referenced_oid as string, referencedSubId = row.referenced_sub_id as string, dependencyType = row.dependency_type as string;
412
+ if (![dependentClassOid, dependentOid, referencedClassOid, referencedOid].every(value => this.oid(value)) || !decimalSubId(dependentSubId) || !decimalSubId(referencedSubId))
413
+ drift();
414
+ endpoints.add(dependentClassOid);
415
+ endpoints.add(referencedClassOid);
416
+ const kind = new Map<string, OwnedCatalogDependencyV1["kind"]>([
417
+ ["n", "normal"], ["a", "automatic"], ["i", "internal"], ["e", "extension"], ["P", "partitionPrimary"], ["S", "partitionSecondary"]
418
+ ]).get(dependencyType) ?? "other";
419
+ dependencies.push(Object.freeze({
420
+ dependentClassOid, dependentOid, dependentSubId, referencedClassOid, referencedOid, referencedSubId, kind
421
+ }));
422
+ }
423
+ const seededClassOids = new Set(seedPairs.map(pair => pair[0]));
424
+ const unresolved = [...endpoints].filter(oid => !knownByOid.has(oid)).sort((left, right) => BigInt(left) < BigInt(right) ? -1 : BigInt(left) > BigInt(right) ? 1 : 0);
425
+ const resolved = await this.readCatalogClasses(operation, unresolved);
426
+ const emitted = new Map<string, OwnedCatalogClassV1>();
427
+ for (const oid of baseClassOids)
428
+ emitted.set(oid, knownByOid.get(oid) ?? drift());
429
+ if (graph.constraints.some(constraint => constraint.kind === "foreignKey") || graph.triggers.length)
430
+ for (const name of ["pg_proc", "pg_trigger"]) {
431
+ const entry = knownByName.get(name) ?? drift();
432
+ emitted.set(entry.oid, entry);
433
+ }
434
+ for (const oid of seededClassOids) {
435
+ const entry = knownByOid.get(oid) ?? drift();
436
+ emitted.set(oid, entry);
437
+ }
438
+ for (const oid of endpoints) {
439
+ const entry = knownByOid.get(oid) ?? resolved.find(candidate => candidate.oid === oid) ?? drift();
440
+ emitted.set(oid, entry);
441
+ }
442
+ for (const entry of resolved)
443
+ emitted.set(entry.oid, entry);
444
+ this.chargeRecords(budget, [...emitted.keys()].filter(oid => !baseClassOids.has(oid)).length);
445
+ const compareOid = (left: string, right: string): number => BigInt(left) < BigInt(right) ? -1 : BigInt(left) > BigInt(right) ? 1 : 0;
446
+ return Object.freeze({
447
+ dependencies: Object.freeze([...dependencies].sort((left, right) => compareOid(left.dependentClassOid, right.dependentClassOid) || compareOid(left.dependentOid, right.dependentOid) || compareOid(left.dependentSubId, right.dependentSubId) || compareOid(left.referencedClassOid, right.referencedClassOid) || compareOid(left.referencedOid, right.referencedOid) || compareOid(left.referencedSubId, right.referencedSubId) || left.kind.localeCompare(right.kind))),
448
+ catalogClasses: Object.freeze([...emitted.values()].sort((left, right) => compareOid(left.oid, right.oid))),
449
+ });
450
+ }
451
+ private encodePgOidArrayParameter(values: readonly string[]): string {
452
+ try {
453
+ if (!Array.isArray(values) || types.isProxy(values) || values.length < 1 || values.length > 1024)
454
+ throw new Error();
455
+ const output: string[] = [];
456
+ for (let index = 0; index < values.length; index++) {
457
+ const descriptor = Object.getOwnPropertyDescriptor(values, String(index));
458
+ if (!descriptor || !("value" in descriptor) || typeof descriptor.value !== "string" || !/^[1-9][0-9]*$/u.test(descriptor.value) || BigInt(descriptor.value) > 4294967295n)
459
+ throw new Error();
460
+ output.push(descriptor.value);
461
+ }
462
+ return `{${output.join(",")}}`;
463
+ }
464
+ catch {
465
+ throw failure("ORM_OWNED_STORE_DRIFT");
466
+ }
467
+ }
468
+ private async readCatalogueRoots(scopes: readonly OrmCatalogScopeV1[], budget: {
469
+ remaining: number;
470
+ }): Promise<readonly OwnedCatalogRelationV1[]> {
471
+ const identities = new Set<string>();
472
+ for (let offset = 0; offset < scopes.length; offset += 512) {
473
+ const batch = scopes.slice(offset, offset + 512), params: string[] = [];
474
+ const values = batch.map((scope, index) => {
475
+ params.push(scope.schema, scope.tablePrefix);
476
+ const first = index * 2 + 1;
477
+ return `($${first}::pg_catalog.text,$${first + 1}::pg_catalog.text)`;
478
+ }).join(",");
479
+ const issuedLimit = budget.remaining + 1;
480
+ const result = await this.source.query(`WITH requested(schema_name, table_prefix) AS (VALUES ${values}) SELECT c.oid::pg_catalog.text AS relation_oid FROM pg_catalog.pg_class AS c JOIN pg_catalog.pg_namespace AS n ON n.oid=c.relnamespace WHERE EXISTS (SELECT 1 FROM requested AS r WHERE r.schema_name=n.nspname AND pg_catalog.left(c.relname,pg_catalog.char_length(r.table_prefix))=r.table_prefix) ORDER BY c.oid LIMIT ${issuedLimit}`, params, "catalog-read");
481
+ const rows = selectOwnedStoreRows(result, ["relation_oid"], issuedLimit);
482
+ if (!rows) {
483
+ this.source.unavailable();
484
+ }
485
+ for (const row of rows)
486
+ if (typeof row.relation_oid !== "string") {
487
+ this.source.unavailable();
488
+ }
489
+ if (rows.length === issuedLimit) {
490
+ this.source.drift();
491
+ }
492
+ for (const row of rows) {
493
+ const oid = row.relation_oid as string;
494
+ if (!this.oid(oid)) {
495
+ this.source.drift();
496
+ }
497
+ identities.add(oid);
498
+ }
499
+ }
500
+ if (identities.size > budget.remaining) {
501
+ this.source.drift();
502
+ }
503
+ return this.readRelations([...identities], "catalog-read", budget);
504
+ }
505
+ private oid(value: unknown): value is string {
506
+ return typeof value === "string" && /^[1-9][0-9]*$/u.test(value) && BigInt(value) <= 4294967295n;
507
+ }
508
+ private async readRelations(oids: readonly string[], operation: "registry-read" | "catalog-read" = "catalog-read", budget?: {
509
+ remaining: number;
510
+ }): Promise<readonly OwnedCatalogRelationV1[]> {
511
+ if (!oids.length)
512
+ return Object.freeze([]);
513
+ const out: OwnedCatalogRelationV1[] = [];
514
+ for (let offset = 0; offset < oids.length; offset += 1024) {
515
+ const batch = oids.slice(offset, offset + 1024), parameter = this.encodePgOidArrayParameter(batch), issuedLimit = budget ? Math.min(batch.length + 1, budget.remaining + 1) : 1025;
516
+ const result = await this.source.query(`SELECT c.oid::pg_catalog.text AS oid,n.oid::pg_catalog.text AS namespace_oid,n.nspname AS schema_name,c.relname AS relation_name,c.relkind AS relkind,c.relpersistence AS relpersistence,c.relispartition AS relispartition,c.relrowsecurity AS relrowsecurity,c.relforcerowsecurity AS relforcerowsecurity,c.relreplident AS relreplident,c.reltablespace::pg_catalog.text AS tablespace_oid,am.amname AS access_method,c.reltype::pg_catalog.text AS row_type_oid,c.reltoastrelid::pg_catalog.text AS toast_relation_oid FROM pg_catalog.pg_class AS c JOIN pg_catalog.pg_namespace AS n ON n.oid=c.relnamespace LEFT JOIN pg_catalog.pg_am AS am ON am.oid=c.relam WHERE c.oid=ANY($1::pg_catalog.oid[]) ORDER BY c.oid LIMIT ${issuedLimit}`, [parameter], operation);
517
+ const rows = selectOwnedStoreRows(result, [
518
+ "oid", "namespace_oid", "schema_name", "relation_name", "relkind", "relpersistence", "relispartition", "relrowsecurity", "relforcerowsecurity", "relreplident", "tablespace_oid", "access_method", "row_type_oid", "toast_relation_oid"
519
+ ], issuedLimit);
520
+ if (!rows) {
521
+ this.source.unavailable();
522
+ }
523
+ this.wireRows(rows as readonly Row[], [
524
+ "oid", "namespace_oid", "schema_name", "relation_name", "relkind", "relpersistence", "relispartition", "relrowsecurity", "relforcerowsecurity", "relreplident", "tablespace_oid", "access_method", "row_type_oid", "toast_relation_oid"
525
+ ], ["relispartition", "relrowsecurity", "relforcerowsecurity"], ["access_method"]);
526
+ if (budget)
527
+ this.chargeRecords(budget, rows.length);
528
+ if (rows.length > oids.slice(offset, offset + 1024).length) {
529
+ this.source.drift();
530
+ }
531
+ const issued = new Set(oids.slice(offset, offset + 1024));
532
+ for (const row of rows) {
533
+ const relation = this.relationRow(row);
534
+ if (!issued.has(relation.oid)) {
535
+ this.source.drift();
536
+ }
537
+ out.push(relation);
538
+ }
539
+ }
540
+ if (out.length !== oids.length || new Set(out.map(value => value.oid)).size !== out.length) {
541
+ this.source.drift();
542
+ }
543
+ return this.readRelationOptions(Object.freeze(out), operation);
544
+ }
545
+ private async readRelationOptions(relations: readonly OwnedCatalogRelationV1[], operation: "registry-read" | "catalog-read"): Promise<readonly OwnedCatalogRelationV1[]> {
546
+ if (!relations.length)
547
+ return relations;
548
+ const lengths = new Map<string, number>();
549
+ for (let offset = 0; offset < relations.length; offset += 1024) {
550
+ const batch = relations.slice(offset, offset + 1024), parameter = this.encodePgOidArrayParameter(batch.map(relation => relation.oid));
551
+ const result = await this.source.query(`SELECT c.oid::pg_catalog.text AS relation_oid,COALESCE(pg_catalog.cardinality(c.reloptions),0)::pg_catalog.text AS option_count FROM pg_catalog.pg_class AS c WHERE c.oid=ANY($1::pg_catalog.oid[]) ORDER BY c.oid LIMIT 1025`, [parameter], operation);
552
+ const rows = selectOwnedStoreRows(result, ["relation_oid", "option_count"], 1025);
553
+ if (!rows) {
554
+ this.source.unavailable();
555
+ }
556
+ this.wireRows(rows as readonly Row[], ["relation_oid", "option_count"]);
557
+ if (rows.length !== batch.length) {
558
+ this.source.drift();
559
+ }
560
+ const issued = new Set(batch.map(relation => relation.oid));
561
+ for (const row of rows) {
562
+ if (typeof row.relation_oid !== "string" || typeof row.option_count !== "string") {
563
+ this.source.unavailable();
564
+ }
565
+ if (!issued.has(row.relation_oid) || !/^(0|[1-9][0-9]*)$/u.test(row.option_count) || BigInt(row.option_count) > 65536n || lengths.has(row.relation_oid)) {
566
+ this.source.drift();
567
+ }
568
+ lengths.set(row.relation_oid, Number(row.option_count));
569
+ }
570
+ }
571
+ const values = new Map<string, string[]>();
572
+ const pending = relations.filter(relation => (lengths.get(relation.oid) ?? 0) !== 0);
573
+ for (let offset = 0; offset < pending.length;) {
574
+ const batch: OwnedCatalogRelationV1[] = [];
575
+ let expected = 0;
576
+ while (offset < pending.length && batch.length < 1024 && expected + (lengths.get(pending[offset]!.oid) ?? 0) <= 65536) {
577
+ const relation = pending[offset++]!;
578
+ batch.push(relation);
579
+ expected += lengths.get(relation.oid)!;
580
+ }
581
+ if (!batch.length) {
582
+ this.source.drift();
583
+ }
584
+ const parameter = this.encodePgOidArrayParameter(batch.map(relation => relation.oid));
585
+ const result = await this.source.query(`SELECT c.oid::pg_catalog.text AS relation_oid,u.ordinality::pg_catalog.text AS ordinality,u.option_value AS option_value FROM pg_catalog.pg_class AS c CROSS JOIN LATERAL pg_catalog.unnest(c.reloptions) WITH ORDINALITY AS u(option_value,ordinality) WHERE c.oid=ANY($1::pg_catalog.oid[]) ORDER BY c.oid,u.ordinality LIMIT ${expected + 1}`, [parameter], operation);
586
+ const rows = selectOwnedStoreRows(result, ["relation_oid", "ordinality", "option_value"], expected + 1);
587
+ if (!rows) {
588
+ this.source.unavailable();
589
+ }
590
+ this.wireRows(rows as readonly Row[], ["relation_oid", "ordinality", "option_value"]);
591
+ if (rows.length === expected + 1) {
592
+ this.source.drift();
593
+ }
594
+ for (const row of rows) {
595
+ if (typeof row.relation_oid !== "string" || typeof row.ordinality !== "string" || typeof row.option_value !== "string") {
596
+ this.source.unavailable();
597
+ }
598
+ const count = lengths.get(row.relation_oid), ordinal = /^(0|[1-9][0-9]*)$/u.test(row.ordinality) ? Number(row.ordinality) : NaN;
599
+ if (count === undefined || !Number.isSafeInteger(ordinal) || ordinal < 1 || ordinal > count) {
600
+ this.source.drift();
601
+ }
602
+ const list = values.get(row.relation_oid) ?? [];
603
+ if (list.length !== ordinal - 1) {
604
+ this.source.drift();
605
+ }
606
+ list.push(row.option_value);
607
+ values.set(row.relation_oid, list);
608
+ }
609
+ }
610
+ const result = relations.map(relation => {
611
+ const options = values.get(relation.oid) ?? [];
612
+ if (options.length !== lengths.get(relation.oid)) {
613
+ this.source.drift();
614
+ }
615
+ return Object.freeze({ ...relation, options: Object.freeze([...options]) });
616
+ });
617
+ return Object.freeze(result);
618
+ }
619
+ private relationRow(row: Row): OwnedCatalogRelationV1 {
620
+ const text = (value: unknown): string => {
621
+ if (typeof value !== "string") {
622
+ this.source.unavailable();
623
+ }
624
+ return value;
625
+ };
626
+ const oid = (value: unknown): string => {
627
+ const result = text(value);
628
+ if (!this.oid(result) && result !== "0") {
629
+ this.source.drift();
630
+ }
631
+ return result;
632
+ };
633
+ const rawKind = text(row.relkind), rawPersistence = text(row.relpersistence), rawIdentity = text(row.relreplident);
634
+ if (typeof row.relispartition !== "boolean" || typeof row.relrowsecurity !== "boolean" || typeof row.relforcerowsecurity !== "boolean" || (row.access_method !== null && typeof row.access_method !== "string")) {
635
+ this.source.unavailable();
636
+ }
637
+ if (rawKind.length !== 1 || rawPersistence.length !== 1 || rawIdentity.length !== 1) {
638
+ this.source.drift();
639
+ }
640
+ const kind: OwnedCatalogRelationV1["kind"] = ({
641
+ r: "ordinaryTable", p: "partitionedTable", f: "foreignTable", v: "view", m: "materializedView", S: "sequence", i: "index", I: "partitionedIndex", t: "toastTable"
642
+ } as Record<string, OwnedCatalogRelationV1["kind"]>)[rawKind] ?? "other";
643
+ const persistence: OwnedCatalogRelationV1["persistence"] = ({ p: "permanent", u: "unlogged", t: "temporary" } as Record<string, OwnedCatalogRelationV1["persistence"]>)[rawPersistence] ?? "other";
644
+ const replicaIdentity: OwnedCatalogRelationV1["replicaIdentity"] = ({ d: "default", n: "nothing", f: "full", i: "index" } as Record<string, OwnedCatalogRelationV1["replicaIdentity"]>)[rawIdentity] ?? "other";
645
+ return Object.freeze({
646
+ oid: oid(row.oid), namespaceOid: oid(row.namespace_oid), schema: text(row.schema_name), name: text(row.relation_name), kind, rawKind, persistence, isPartition: row.relispartition, rowSecurity: row.relrowsecurity, forceRowSecurity: row.relforcerowsecurity, replicaIdentity, tablespaceOid: oid(row.tablespace_oid), accessMethod: row.access_method, options: Object.freeze([]), rowTypeOid: oid(row.row_type_oid) === "0" ? null : oid(row.row_type_oid), toastRelationOid: oid(row.toast_relation_oid) === "0" ? null : oid(row.toast_relation_oid)
647
+ });
648
+ }
649
+ private async readRelationTypes(relations: readonly OwnedCatalogRelationV1[], operation: "registry-read" | "catalog-read", budget: {
650
+ remaining: number;
651
+ }): Promise<readonly [
652
+ readonly OwnedCatalogRowTypeV1[],
653
+ readonly OwnedCatalogArrayTypeV1[]
654
+ ]> {
655
+ const relationOids = relations.filter(relation => relation.rowTypeOid !== null).map(relation => relation.oid);
656
+ if (!relationOids.length)
657
+ return Object.freeze([Object.freeze([]), Object.freeze([])]);
658
+ const rowTypes: OwnedCatalogRowTypeV1[] = [], arrayTypes: OwnedCatalogArrayTypeV1[] = [];
659
+ for (let offset = 0; offset < relationOids.length; offset += 1024) {
660
+ const batch = relationOids.slice(offset, offset + 1024), parameter = this.encodePgOidArrayParameter(batch), issuedLimit = Math.min(batch.length + 1, budget.remaining + 1);
661
+ const result = await this.source.query(`SELECT t.oid::pg_catalog.text AS row_type_oid,t.typrelid::pg_catalog.text AS relation_oid,n.nspname AS schema_name,t.typname AS type_name,t.typtype AS typtype,a.oid::pg_catalog.text AS array_type_oid,a.typrelid::pg_catalog.text AS array_relation_oid,an.nspname AS array_schema_name,a.typname AS array_type_name,a.typtype AS array_typtype,a.typcategory AS array_typcategory,a.typelem::pg_catalog.text AS array_element_oid,a.typarray::pg_catalog.text AS array_array_oid FROM pg_catalog.pg_type AS t JOIN pg_catalog.pg_namespace AS n ON n.oid=t.typnamespace JOIN pg_catalog.pg_type AS a ON a.oid=t.typarray JOIN pg_catalog.pg_namespace AS an ON an.oid=a.typnamespace WHERE t.typrelid=ANY($1::pg_catalog.oid[]) ORDER BY t.typrelid LIMIT ${issuedLimit}`, [parameter], operation);
662
+ const rows = selectOwnedStoreRows(result, [
663
+ "row_type_oid", "relation_oid", "schema_name", "type_name", "typtype", "array_type_oid", "array_relation_oid", "array_schema_name", "array_type_name", "array_typtype", "array_typcategory", "array_element_oid", "array_array_oid"
664
+ ], issuedLimit);
665
+ if (!rows) {
666
+ this.source.unavailable();
667
+ }
668
+ this.wireRows(rows as readonly Row[], [
669
+ "row_type_oid", "relation_oid", "schema_name", "type_name", "typtype", "array_type_oid", "array_relation_oid", "array_schema_name", "array_type_name", "array_typtype", "array_typcategory", "array_element_oid", "array_array_oid"
670
+ ]);
671
+ this.chargeRecords(budget, rows.length * 2);
672
+ if (rows.length !== batch.length) {
673
+ this.source.drift();
674
+ }
675
+ const expected = new Map(batch.map(oid => [oid, relations.find(relation => relation.oid === oid)!]));
676
+ for (const row of rows) {
677
+ if (typeof row.row_type_oid !== "string" || typeof row.relation_oid !== "string" || typeof row.array_type_oid !== "string" || typeof row.array_relation_oid !== "string" || typeof row.array_array_oid !== "string" || typeof row.array_element_oid !== "string" || typeof row.schema_name !== "string" || typeof row.type_name !== "string" || typeof row.array_schema_name !== "string" || typeof row.array_type_name !== "string" || typeof row.typtype !== "string" || typeof row.array_typtype !== "string" || typeof row.array_typcategory !== "string") {
678
+ this.source.unavailable();
679
+ }
680
+ const relation = expected.get(row.relation_oid);
681
+ if (!relation || relation.rowTypeOid !== row.row_type_oid || !this.oid(row.row_type_oid) || !this.oid(row.relation_oid) || !this.oid(row.array_type_oid) || row.array_relation_oid !== "0" || row.array_array_oid !== "0" || row.array_element_oid !== row.row_type_oid) {
682
+ this.source.drift();
683
+ }
684
+ expected.delete(row.relation_oid);
685
+ rowTypes.push(Object.freeze({
686
+ oid: row.row_type_oid, relationOid: row.relation_oid, schema: row.schema_name, name: row.type_name, kind: row.typtype === "c" ? "composite" : "other", arrayTypeOid: row.array_type_oid
687
+ }));
688
+ arrayTypes.push(Object.freeze({
689
+ oid: row.array_type_oid, elementTypeOid: row.row_type_oid, relationOid: "0", arrayTypeOid: "0", schema: row.array_schema_name, name: row.array_type_name, kind: row.array_typtype === "b" ? "base" : "other", category: row.array_typcategory === "A" ? "array" : "other"
690
+ }));
691
+ }
692
+ if (expected.size) {
693
+ this.source.drift();
694
+ }
695
+ }
696
+ return Object.freeze([Object.freeze(rowTypes), Object.freeze(arrayTypes)]);
697
+ }
698
+ private async readColumns(relations: readonly OwnedCatalogRelationV1[], operation: "registry-read" | "catalog-read", budget: {
699
+ remaining: number;
700
+ }): Promise<readonly OwnedCatalogColumnV1[]> {
701
+ const relationOids = relations.filter(relation => relation.kind === "ordinaryTable" || relation.kind === "toastTable").map(relation => relation.oid);
702
+ if (!relationOids.length)
703
+ return Object.freeze([]);
704
+ const output: OwnedCatalogColumnV1[] = [], relationKinds = new Map(relations.map(relation => [relation.oid, relation.kind]));
705
+ for (let offset = 0; offset < relationOids.length; offset += 1024) {
706
+ const batch = relationOids.slice(offset, offset + 1024), parameter = this.encodePgOidArrayParameter(batch), issuedLimit = budget.remaining + 1;
707
+ const result = await this.source.query(`SELECT a.attrelid::pg_catalog.text AS relation_oid,a.attnum::pg_catalog.text AS attnum,a.attname AS column_name,a.attisdropped AS dropped,a.attislocal AS local,a.attinhcount::pg_catalog.text AS inheritance_count,pg_catalog.format_type(a.atttypid,a.atttypmod) AS physical_type,a.atttypid::pg_catalog.text AS type_oid,a.attnotnull AS not_null,d.oid::pg_catalog.text AS default_object_oid,pg_catalog.pg_get_expr(d.adbin,d.adrelid) AS default_expression,a.attidentity AS identity_code,a.attgenerated AS generated_code,a.attcollation::pg_catalog.text AS collation_oid,t.typcollation::pg_catalog.text AS type_default_collation_oid,a.attstorage AS storage_code,t.typstorage AS type_default_storage_code,a.attcompression AS compression_code,a.atthasdef AS has_default FROM pg_catalog.pg_attribute AS a LEFT JOIN pg_catalog.pg_type AS t ON t.oid=a.atttypid LEFT JOIN pg_catalog.pg_attrdef AS d ON d.adrelid=a.attrelid AND d.adnum=a.attnum WHERE a.attrelid=ANY($1::pg_catalog.oid[]) AND a.attnum>0 ORDER BY a.attrelid,a.attnum LIMIT ${issuedLimit}`, [parameter], operation);
708
+ const rows = selectOwnedStoreRows(result, [
709
+ "relation_oid", "attnum", "column_name", "dropped", "local", "inheritance_count", "physical_type", "type_oid", "not_null", "default_object_oid", "default_expression", "identity_code", "generated_code", "collation_oid", "type_default_collation_oid", "storage_code", "type_default_storage_code", "compression_code", "has_default"
710
+ ], issuedLimit);
711
+ if (!rows) {
712
+ this.source.unavailable();
713
+ }
714
+ this.wireRows(rows as readonly Row[], [
715
+ "relation_oid", "attnum", "column_name", "dropped", "local", "inheritance_count", "physical_type", "type_oid", "not_null", "default_object_oid", "default_expression", "identity_code", "generated_code", "collation_oid", "type_default_collation_oid", "storage_code", "type_default_storage_code", "compression_code", "has_default"
716
+ ], ["dropped", "local", "not_null", "has_default"], ["type_default_collation_oid", "type_default_storage_code", "default_object_oid", "default_expression"]);
717
+ this.chargeRecords(budget, rows.length);
718
+ const issued = new Set(batch);
719
+ for (const row of rows)
720
+ output.push(this.columnRow(row, issued, relationKinds));
721
+ }
722
+ return Object.freeze(output);
723
+ }
724
+ private async readIndexVectors(indexes: readonly OwnedCatalogIndexV1[], operation: "registry-read" | "catalog-read", parentMethods: ReadonlyMap<string, string>): Promise<readonly OwnedCatalogIndexV1[]> {
725
+ if (!indexes.length)
726
+ return indexes;
727
+ const values = new Map<string, {
728
+ attnums: string[];
729
+ names: (string | null)[];
730
+ collations: string[];
731
+ opclasses: string[];
732
+ options: string[];
733
+ }>();
734
+ for (let offset = 0; offset < indexes.length;) {
735
+ const batch: OwnedCatalogIndexV1[] = [];
736
+ let total = 0;
737
+ while (offset < indexes.length && batch.length < 1024) {
738
+ const index = indexes[offset]!;
739
+ const width = Number(index.totalAttributeCount);
740
+ if (total + width > 65536)
741
+ break;
742
+ batch.push(index);
743
+ total += width;
744
+ offset++;
745
+ }
746
+ if (!batch.length) {
747
+ this.source.drift();
748
+ }
749
+ const parameter = this.encodePgOidArrayParameter(batch.map(index => index.indexRelationOid));
750
+ const read = async (kind: "key" | "collation" | "opclass" | "option") => {
751
+ const expected = batch.reduce((sum, index) => sum + Number(kind === "key" ? index.totalAttributeCount : index.keyAttributeCount), 0);
752
+ if (expected > 65536) {
753
+ this.source.drift();
754
+ }
755
+ const select = kind === "key"
756
+ ? `element.attnum::pg_catalog.text AS value,a.attnum::pg_catalog.text AS resolved_attnum,a.attname AS column_name`
757
+ : `element.value::pg_catalog.text AS value`;
758
+ const source = kind === "key" ? "i.indkey" : kind === "collation" ? "i.indcollation" : kind === "opclass" ? "i.indclass" : "i.indoption";
759
+ const join = kind === "key" ? "LEFT JOIN pg_catalog.pg_attribute AS a ON a.attrelid=i.indrelid AND a.attnum=element.attnum" : "";
760
+ const result = await this.source.query(`SELECT i.indexrelid::pg_catalog.text AS index_relation_oid,element.element_ordinality::pg_catalog.text AS element_ordinality,${select} FROM pg_catalog.pg_index AS i CROSS JOIN LATERAL pg_catalog.unnest(${source}) WITH ORDINALITY AS element(${kind === "key" ? "attnum" : "value"},element_ordinality) ${join} WHERE i.indexrelid=ANY($1::pg_catalog.oid[]) ORDER BY i.indexrelid,element.element_ordinality LIMIT ${expected + 1}`, [parameter], operation);
761
+ const aliases = kind === "key" ? ["index_relation_oid", "element_ordinality", "value", "resolved_attnum", "column_name"] : ["index_relation_oid", "element_ordinality", "value"];
762
+ const rows = selectOwnedStoreRows(result, aliases, expected + 1);
763
+ if (!rows) {
764
+ this.source.unavailable();
765
+ }
766
+ this.wireRows(rows as readonly Row[], aliases, [], kind === "key" ? ["resolved_attnum", "column_name"] : []);
767
+ if (rows.length === expected + 1) {
768
+ this.source.drift();
769
+ }
770
+ for (const row of rows) {
771
+ if (typeof row.index_relation_oid !== "string" || typeof row.element_ordinality !== "string" || typeof row.value !== "string" || (kind === "key" && row.column_name !== null && typeof row.column_name !== "string") || (kind === "key" && row.resolved_attnum !== null && typeof row.resolved_attnum !== "string")) {
772
+ this.source.unavailable();
773
+ }
774
+ const index = batch.find(item => item.indexRelationOid === row.index_relation_oid), ordinal = Number(row.element_ordinality);
775
+ if (!index || !/^[1-9][0-9]*$/u.test(row.element_ordinality) || !Number.isSafeInteger(ordinal) || ordinal > Number(kind === "key" ? index.totalAttributeCount : index.keyAttributeCount)) {
776
+ this.source.drift();
777
+ }
778
+ const target = values.get(index.indexRelationOid) ?? { attnums: [], names: [], collations: [], opclasses: [], options: [] };
779
+ const list = kind === "key" ? target.attnums : kind === "collation" ? target.collations : kind === "opclass" ? target.opclasses : target.options;
780
+ if (list.length !== ordinal - 1) {
781
+ this.source.drift();
782
+ }
783
+ if (kind === "key") {
784
+ const signed = this.signedInt2(row.value);
785
+ if (!signed || (row.value === "0" ? row.resolved_attnum !== null || row.column_name !== null : row.resolved_attnum !== row.value || row.column_name === null)) {
786
+ this.source.drift();
787
+ }
788
+ target.attnums.push(row.value);
789
+ target.names.push(row.value === "0" ? null : row.column_name as string);
790
+ }
791
+ else {
792
+ if (kind === "option" ? !this.signedInt2(row.value) : !this.oid(row.value) && !(kind !== "opclass" && row.value === "0")) {
793
+ this.source.drift();
794
+ }
795
+ list.push(row.value);
796
+ }
797
+ values.set(index.indexRelationOid, target);
798
+ }
799
+ };
800
+ await read("key");
801
+ await read("collation");
802
+ await read("opclass");
803
+ await read("option");
804
+ }
805
+ return this.readIndexOpclasses(Object.freeze(indexes.map(index => {
806
+ const value = values.get(index.indexRelationOid);
807
+ if (!value || value.attnums.length !== Number(index.totalAttributeCount) || value.collations.length !== Number(index.keyAttributeCount) || value.opclasses.length !== Number(index.keyAttributeCount) || value.options.length !== Number(index.keyAttributeCount)) {
808
+ this.source.drift();
809
+ }
810
+ return Object.freeze({
811
+ ...index, attributeNumbers: Object.freeze(value.attnums), columnNames: Object.freeze(value.names), collationOids: Object.freeze(value.collations), opclassOids: Object.freeze(value.opclasses), options: Object.freeze(value.options)
812
+ });
813
+ })), operation, parentMethods);
814
+ }
815
+ private async readIndexOpclasses(indexes: readonly OwnedCatalogIndexV1[], operation: "registry-read" | "catalog-read", parentMethods: ReadonlyMap<string, string>): Promise<readonly OwnedCatalogIndexV1[]> {
816
+ const actual = [...new Set(indexes.flatMap(index => index.opclassOids))];
817
+ const defaults = new Map<string, string>();
818
+ const methods = new Map<string, string>();
819
+ for (let offset = 0; offset < actual.length; offset += 1024) {
820
+ const batch = actual.slice(offset, offset + 1024), parameter = this.encodePgOidArrayParameter(batch);
821
+ const result = await this.source.query(`SELECT actual.oid::pg_catalog.text AS actual_opclass_oid,actual.opcmethod::pg_catalog.text AS actual_method_oid,actual.opcintype::pg_catalog.text AS actual_input_type_oid,actual.opcfamily::pg_catalog.text AS actual_opfamily_oid,family.opfmethod::pg_catalog.text AS actual_family_method_oid,candidate.default_opclass_oid::pg_catalog.text AS default_opclass_oid,candidate.default_method_oid::pg_catalog.text AS default_method_oid,candidate.default_input_type_oid::pg_catalog.text AS default_input_type_oid,candidate.default_is_default AS default_is_default FROM pg_catalog.pg_opclass AS actual JOIN pg_catalog.pg_opfamily AS family ON family.oid=actual.opcfamily LEFT JOIN LATERAL (SELECT d.oid AS default_opclass_oid,d.opcmethod AS default_method_oid,d.opcintype AS default_input_type_oid,d.opcdefault AS default_is_default FROM pg_catalog.pg_opclass AS d WHERE d.opcmethod=actual.opcmethod AND d.opcintype=actual.opcintype AND d.opcdefault=true ORDER BY d.oid LIMIT 2) AS candidate ON true WHERE actual.oid=ANY($1::pg_catalog.oid[]) ORDER BY actual.oid,candidate.default_opclass_oid NULLS FIRST LIMIT 2049`, [parameter], operation);
822
+ const rows = selectOwnedStoreRows(result, [
823
+ "actual_opclass_oid", "actual_method_oid", "actual_input_type_oid", "actual_opfamily_oid", "actual_family_method_oid", "default_opclass_oid", "default_method_oid", "default_input_type_oid", "default_is_default"
824
+ ], 2049);
825
+ if (!rows) {
826
+ this.source.unavailable();
827
+ }
828
+ this.wireRows(rows as readonly Row[], [
829
+ "actual_opclass_oid", "actual_method_oid", "actual_input_type_oid", "actual_opfamily_oid", "actual_family_method_oid", "default_opclass_oid", "default_method_oid", "default_input_type_oid", "default_is_default"
830
+ ], ["default_is_default"], ["default_opclass_oid", "default_method_oid", "default_input_type_oid", "default_is_default"]);
831
+ if (rows.length === 2049) {
832
+ this.source.drift();
833
+ }
834
+ const grouped = new Map<string, Row[]>();
835
+ for (const row of rows) {
836
+ if (typeof row.actual_opclass_oid !== "string") {
837
+ this.source.unavailable();
838
+ }
839
+ const group = grouped.get(row.actual_opclass_oid) ?? [];
840
+ group.push(row);
841
+ grouped.set(row.actual_opclass_oid, group);
842
+ }
843
+ if (grouped.size !== batch.length || [...grouped.keys()].some(oid => !batch.includes(oid))) {
844
+ this.source.drift();
845
+ }
846
+ for (const oid of batch) {
847
+ const group = grouped.get(oid);
848
+ if (!group || group.length !== 1) {
849
+ this.source.drift();
850
+ }
851
+ const row = group[0]!;
852
+ if (![
853
+ row.actual_method_oid, row.actual_input_type_oid, row.actual_opfamily_oid, row.actual_family_method_oid
854
+ ].every(value => typeof value === "string") || (row.default_opclass_oid !== null && typeof row.default_opclass_oid !== "string") || (row.default_method_oid !== null && typeof row.default_method_oid !== "string") || (row.default_input_type_oid !== null && typeof row.default_input_type_oid !== "string") || (row.default_is_default !== null && typeof row.default_is_default !== "boolean")) {
855
+ this.source.unavailable();
856
+ }
857
+ if (row.default_opclass_oid === null || row.default_method_oid === null || row.default_input_type_oid === null || row.default_is_default !== true || row.actual_method_oid !== row.actual_family_method_oid || row.actual_method_oid !== row.default_method_oid || row.actual_input_type_oid !== row.default_input_type_oid || ![
858
+ row.actual_method_oid, row.actual_input_type_oid, row.actual_opfamily_oid, row.actual_family_method_oid, row.default_opclass_oid, row.default_method_oid, row.default_input_type_oid
859
+ ].every(value => this.oid(value))) {
860
+ this.source.drift();
861
+ }
862
+ methods.set(oid, row.actual_method_oid);
863
+ defaults.set(oid, row.default_opclass_oid);
864
+ }
865
+ }
866
+ for (const index of indexes)
867
+ for (const opclass of index.opclassOids)
868
+ if (parentMethods.get(index.indexRelationOid) !== methods.get(opclass)) {
869
+ this.source.drift();
870
+ }
871
+ return Object.freeze(indexes.map(index => {
872
+ const defaultOpclassOids = index.opclassOids.map(oid => defaults.get(oid));
873
+ if (defaultOpclassOids.some(oid => oid === undefined)) {
874
+ this.source.drift();
875
+ }
876
+ return Object.freeze({ ...index, defaultOpclassOids: Object.freeze(defaultOpclassOids as string[]) });
877
+ }));
878
+ }
879
+ private async readConstraintParents(relations: readonly OwnedCatalogRelationV1[], operation: "registry-read" | "catalog-read", budget: {
880
+ remaining: number;
881
+ }): Promise<readonly OwnedStoreConstraintParentV1[]> {
882
+ const owned = relations.filter(relation => relation.kind === "ordinaryTable" || relation.kind === "toastTable").map(relation => relation.oid);
883
+ if (!owned.length)
884
+ return Object.freeze([]);
885
+ const parameters: string[] = [], branches: string[] = [];
886
+ for (let offset = 0; offset < owned.length; offset += 1024) {
887
+ parameters.push(this.encodePgOidArrayParameter(owned.slice(offset, offset + 1024)));
888
+ branches.push(`SELECT x.oid FROM pg_catalog.unnest($${parameters.length}::pg_catalog.oid[]) AS x(oid)`);
889
+ }
890
+ const issuedLimit = budget.remaining + 1;
891
+ const result = await this.source.query(`WITH owned(oid) AS (${branches.join(" UNION ALL ")}) SELECT c.oid::pg_catalog.text AS constraint_oid,c.conrelid::pg_catalog.text AS relation_oid,c.confrelid::pg_catalog.text AS referenced_relation_oid,c.conname AS constraint_name,c.contype::pg_catalog.text AS constraint_type_code,c.conindid::pg_catalog.text AS backing_index_oid,c.confdeltype::pg_catalog.text AS delete_action_code,c.confupdtype::pg_catalog.text AS update_action_code,c.confmatchtype::pg_catalog.text AS match_type_code,c.condeferrable AS is_deferrable,c.condeferred AS is_initially_deferred,c.convalidated AS is_validated,c.conparentid::pg_catalog.text AS parent_constraint_oid,c.coninhcount::pg_catalog.text AS inheritance_count,c.connoinherit AS is_no_inherit,COALESCE(pg_catalog.cardinality(c.conkey),0)::pg_catalog.text AS conkey_count,COALESCE(pg_catalog.cardinality(c.confkey),0)::pg_catalog.text AS confkey_count,COALESCE(pg_catalog.cardinality(c.confdelsetcols),0)::pg_catalog.text AS confdelsetcols_count,COALESCE(pg_catalog.cardinality(c.conpfeqop),0)::pg_catalog.text AS conpfeqop_count,COALESCE(pg_catalog.cardinality(c.conppeqop),0)::pg_catalog.text AS conppeqop_count,COALESCE(pg_catalog.cardinality(c.conffeqop),0)::pg_catalog.text AS conffeqop_count,CASE WHEN c.contype='c'::pg_catalog."char" THEN pg_catalog.pg_get_constraintdef(c.oid,false) ELSE NULL::pg_catalog.text END AS check_definition FROM pg_catalog.pg_constraint AS c WHERE c.conrelid IN (SELECT oid FROM owned) OR (c.contype='f'::pg_catalog."char" AND c.confrelid IN (SELECT oid FROM owned)) ORDER BY c.conrelid,pg_catalog.convert_to(c.conname,'UTF8'),c.oid LIMIT ${issuedLimit}`, parameters, operation);
892
+ const rows = selectOwnedStoreRows(result, [
893
+ "constraint_oid", "relation_oid", "referenced_relation_oid", "constraint_name", "constraint_type_code", "backing_index_oid", "delete_action_code", "update_action_code", "match_type_code", "is_deferrable", "is_initially_deferred", "is_validated", "parent_constraint_oid", "inheritance_count", "is_no_inherit", "conkey_count", "confkey_count", "confdelsetcols_count", "conpfeqop_count", "conppeqop_count", "conffeqop_count", "check_definition"
894
+ ], issuedLimit);
895
+ if (!rows) {
896
+ this.source.unavailable();
897
+ }
898
+ this.wireRows(rows as readonly Row[], [
899
+ "constraint_oid", "relation_oid", "referenced_relation_oid", "constraint_name", "constraint_type_code", "backing_index_oid", "delete_action_code", "update_action_code", "match_type_code", "is_deferrable", "is_initially_deferred", "is_validated", "parent_constraint_oid", "inheritance_count", "is_no_inherit", "conkey_count", "confkey_count", "confdelsetcols_count", "conpfeqop_count", "conppeqop_count", "conffeqop_count", "check_definition"
900
+ ], ["is_deferrable", "is_initially_deferred", "is_validated", "is_no_inherit"], ["check_definition"]);
901
+ this.chargeRecords(budget, rows.length);
902
+ const out: OwnedStoreConstraintParentV1[] = [];
903
+ for (const row of rows) {
904
+ const str = (v: unknown) => {
905
+ if (typeof v !== "string") {
906
+ this.source.unavailable();
907
+ }
908
+ return v;
909
+ };
910
+ const oid = (v: unknown, nullable = false) => {
911
+ const x = str(v);
912
+ if ((nullable && x !== "0" || !nullable) && !this.oid(x)) {
913
+ this.source.drift();
914
+ }
915
+ return nullable && x === "0" ? null : x;
916
+ };
917
+ const count = (v: unknown) => {
918
+ const x = str(v);
919
+ if (!/^(0|[1-9][0-9]*)$/u.test(x) || BigInt(x) > 65536n) {
920
+ this.source.drift();
921
+ }
922
+ return Number(x);
923
+ };
924
+ if (typeof row.is_deferrable !== "boolean" || typeof row.is_initially_deferred !== "boolean" || typeof row.is_validated !== "boolean" || typeof row.is_no_inherit !== "boolean" || (row.check_definition !== null && typeof row.check_definition !== "string")) {
925
+ this.source.unavailable();
926
+ }
927
+ const code = str(row.constraint_type_code), kind = ({ p: "primaryKey", u: "unique", f: "foreignKey", c: "check", x: "exclusion" } as Record<string, OwnedCatalogConstraintV1["kind"]>)[code] ?? "other";
928
+ const widths = [
929
+ count(row.conkey_count), count(row.confkey_count), count(row.confdelsetcols_count), count(row.conpfeqop_count), count(row.conppeqop_count), count(row.conffeqop_count)
930
+ ] as const;
931
+ const inheritance = str(row.inheritance_count);
932
+ if (!/^(0|[1-9][0-9]*)$/u.test(inheritance) || BigInt(inheritance) > 32767n || (kind === "check" && row.check_definition === null) || (kind !== "foreignKey" && widths.slice(1).some(x => x !== 0)) || (kind === "foreignKey" && (widths[0] === 0 || widths[0] !== widths[1] || widths[0] !== widths[3] || widths[0] !== widths[4] || widths[0] !== widths[5] || widths[2] > widths[0]))) {
933
+ this.source.drift();
934
+ }
935
+ const checked = kind === "check" ? canonicalPostgresCheck(str(row.constraint_name), row.check_definition as string) : undefined;
936
+ if (checked?.unsupported) {
937
+ this.source.drift();
938
+ }
939
+ const expression = this.freezeCheck(checked?.expression ?? null) as NonNullable<OwnedCatalogConstraintV1["checkExpression"]> | null;
940
+ const action = (v: unknown) => ({ a: "noAction", r: "restrict", c: "cascade", n: "setNull", d: "setDefault" } as Record<string, string>)[str(v)] ?? `other:${str(v)}`;
941
+ const match = (v: unknown) => ({ s: "simple", f: "full", p: "partial" } as Record<string, string>)[str(v)] ?? `other:${str(v)}`;
942
+ out.push(Object.freeze({
943
+ value: Object.freeze({
944
+ oid: oid(row.constraint_oid)!, relationOid: oid(row.relation_oid)!, referencedRelationOid: oid(row.referenced_relation_oid, true), name: str(row.constraint_name), kind, columns: Object.freeze([]), referencedColumns: Object.freeze([]), backingIndexOid: oid(row.backing_index_oid, true), onDelete: kind === "foreignKey" ? action(row.delete_action_code) : null, onUpdate: kind === "foreignKey" ? action(row.update_action_code) : null, match: kind === "foreignKey" ? match(row.match_type_code) : null, deferrable: row.is_deferrable, initiallyDeferred: row.is_initially_deferred, validated: row.is_validated, parentConstraintOid: oid(row.parent_constraint_oid, true), inheritanceCount: inheritance, noInherit: row.is_no_inherit, deleteSetColumns: Object.freeze([]), primaryForeignEqualityOperatorOids: Object.freeze([]), primaryPrimaryEqualityOperatorOids: Object.freeze([]), foreignForeignEqualityOperatorOids: Object.freeze([]), defaultEqualityOperatorOids: Object.freeze([]), checkExpression: expression
945
+ }), widths
946
+ }));
947
+ }
948
+ return Object.freeze(out);
949
+ }
950
+ /** Captures every pg_constraint vector independently; FK default equality is resolved separately. */
951
+ private async readConstraintVectors(parents: readonly OwnedStoreConstraintParentV1[], operation: "registry-read" | "catalog-read"): Promise<readonly OwnedCatalogConstraintV1[]> {
952
+ if (!parents.length)
953
+ return Object.freeze([]);
954
+ const ids = new Set<string>();
955
+ for (const parent of parents)
956
+ if (ids.has(parent.value.oid)) {
957
+ this.source.drift();
958
+ }
959
+ else
960
+ ids.add(parent.value.oid);
961
+ type VectorKind = "columns" | "referencedColumns" | "deleteSetColumns" | "primaryForeignEqualityOperatorOids" | "primaryPrimaryEqualityOperatorOids" | "foreignForeignEqualityOperatorOids";
962
+ const vectors = new Map<string, Record<VectorKind, string[]>>();
963
+ for (const parent of parents)
964
+ vectors.set(parent.value.oid, {
965
+ columns: [], referencedColumns: [], deleteSetColumns: [], primaryForeignEqualityOperatorOids: [], primaryPrimaryEqualityOperatorOids: [], foreignForeignEqualityOperatorOids: []
966
+ });
967
+ const width = (parent: OwnedStoreConstraintParentV1, kind: VectorKind): number => kind === "columns" ? parent.widths[0] : kind === "referencedColumns" ? parent.widths[1] : kind === "deleteSetColumns" ? parent.widths[2] : kind === "primaryForeignEqualityOperatorOids" ? parent.widths[3] : kind === "primaryPrimaryEqualityOperatorOids" ? parent.widths[4] : parent.widths[5];
968
+ const kinds: readonly VectorKind[] = [
969
+ "columns", "referencedColumns", "deleteSetColumns", "primaryForeignEqualityOperatorOids", "primaryPrimaryEqualityOperatorOids", "foreignForeignEqualityOperatorOids"
970
+ ];
971
+ for (const kind of kinds) {
972
+ for (let offset = 0; offset < parents.length;) {
973
+ const batch: OwnedStoreConstraintParentV1[] = [];
974
+ let expected = 0;
975
+ while (offset < parents.length && batch.length < 1024) {
976
+ const parent = parents[offset]!, next = width(parent, kind);
977
+ if (expected + next > 65536)
978
+ break;
979
+ batch.push(parent);
980
+ expected += next;
981
+ offset++;
982
+ }
983
+ if (!batch.length) {
984
+ this.source.drift();
985
+ }
986
+ const parameter = this.encodePgOidArrayParameter(batch.map(parent => parent.value.oid));
987
+ const names = kind === "columns" || kind === "referencedColumns" || kind === "deleteSetColumns";
988
+ const native = kind === "columns" ? "c.conkey" : kind === "referencedColumns" ? "c.confkey" : kind === "deleteSetColumns" ? "c.confdelsetcols" : kind === "primaryForeignEqualityOperatorOids" ? "c.conpfeqop" : kind === "primaryPrimaryEqualityOperatorOids" ? "c.conppeqop" : "c.conffeqop";
989
+ const select = names
990
+ ? "element.attnum::pg_catalog.text AS attribute_number,a.attnum::pg_catalog.text AS resolved_attribute_number,a.attname AS column_name"
991
+ : "element.operator_oid::pg_catalog.text AS operator_oid";
992
+ const join = names ? ` LEFT JOIN pg_catalog.pg_attribute AS a ON a.attrelid=requested.${kind === "referencedColumns" ? "referenced_relation_oid" : "relation_oid"} AND a.attnum=element.attnum` : "";
993
+ const result = await this.source.query(`WITH requested(constraint_oid,request_ordinality,relation_oid,referenced_relation_oid) AS (SELECT input.constraint_oid,input.request_ordinality,c.conrelid,c.confrelid FROM pg_catalog.unnest($1::pg_catalog.oid[]) WITH ORDINALITY AS input(constraint_oid,request_ordinality) JOIN pg_catalog.pg_constraint AS c ON c.oid=input.constraint_oid) SELECT requested.request_ordinality::pg_catalog.text AS request_ordinality,c.oid::pg_catalog.text AS constraint_oid,element.element_ordinality::pg_catalog.text AS element_ordinality,${select} FROM requested JOIN pg_catalog.pg_constraint AS c ON c.oid=requested.constraint_oid CROSS JOIN LATERAL pg_catalog.unnest(${native}) WITH ORDINALITY AS element(${names ? "attnum" : "operator_oid"},element_ordinality)${join} ORDER BY requested.request_ordinality,element.element_ordinality LIMIT ${expected + 1}`, [parameter], operation);
994
+ const aliases = names ? [
995
+ "request_ordinality", "constraint_oid", "element_ordinality", "attribute_number", "resolved_attribute_number", "column_name"
996
+ ] : ["request_ordinality", "constraint_oid", "element_ordinality", "operator_oid"];
997
+ const rows = selectOwnedStoreRows(result, aliases, expected + 1);
998
+ if (!rows) {
999
+ this.source.unavailable();
1000
+ }
1001
+ this.wireRows(rows as readonly Row[], aliases, [], names ? ["resolved_attribute_number", "column_name"] : []);
1002
+ if (rows.length === expected + 1) {
1003
+ this.source.drift();
1004
+ }
1005
+ for (const row of rows) {
1006
+ const required = (value: unknown): string => {
1007
+ if (typeof value !== "string") {
1008
+ this.source.unavailable();
1009
+ }
1010
+ return value;
1011
+ };
1012
+ const nullable = (value: unknown): string | null => {
1013
+ if (value === null)
1014
+ return null;
1015
+ return required(value);
1016
+ };
1017
+ const ordinal = required(row.request_ordinality), constraintOid = required(row.constraint_oid), element = required(row.element_ordinality);
1018
+ if (!/^[1-9][0-9]*$/u.test(ordinal) || !/^[1-9][0-9]*$/u.test(element)) {
1019
+ this.source.drift();
1020
+ }
1021
+ const request = Number(ordinal), position = Number(element), parent = Number.isSafeInteger(request) ? batch[request - 1] : undefined;
1022
+ if (!parent || parent.value.oid !== constraintOid || position > width(parent, kind)) {
1023
+ this.source.drift();
1024
+ }
1025
+ const vector = vectors.get(constraintOid) ?? {
1026
+ columns: [], referencedColumns: [], deleteSetColumns: [], primaryForeignEqualityOperatorOids: [], primaryPrimaryEqualityOperatorOids: [], foreignForeignEqualityOperatorOids: []
1027
+ };
1028
+ const target = vector[kind];
1029
+ if (target.length !== position - 1) {
1030
+ this.source.drift();
1031
+ }
1032
+ if (names) {
1033
+ const attnum = required(row.attribute_number), resolved = nullable(row.resolved_attribute_number), name = nullable(row.column_name);
1034
+ if (resolved === null || name === null || !/^[1-9][0-9]*$/u.test(attnum) || BigInt(attnum) > 32767n || attnum !== resolved) {
1035
+ this.source.drift();
1036
+ }
1037
+ target.push(name);
1038
+ }
1039
+ else {
1040
+ const operator = required(row.operator_oid);
1041
+ if (!this.oid(operator)) {
1042
+ this.source.drift();
1043
+ }
1044
+ target.push(operator);
1045
+ }
1046
+ vectors.set(constraintOid, vector);
1047
+ }
1048
+ for (const parent of batch) {
1049
+ const vector = vectors.get(parent.value.oid);
1050
+ if ((vector?.[kind].length ?? 0) !== width(parent, kind)) {
1051
+ this.source.drift();
1052
+ }
1053
+ }
1054
+ }
1055
+ }
1056
+ return Object.freeze(parents.map(parent => {
1057
+ const vector = vectors.get(parent.value.oid);
1058
+ if (!vector) {
1059
+ this.source.drift();
1060
+ }
1061
+ return Object.freeze({
1062
+ ...parent.value, columns: Object.freeze([...vector.columns]), referencedColumns: Object.freeze([...vector.referencedColumns]), deleteSetColumns: Object.freeze([...vector.deleteSetColumns]), primaryForeignEqualityOperatorOids: Object.freeze([...vector.primaryForeignEqualityOperatorOids]), primaryPrimaryEqualityOperatorOids: Object.freeze([...vector.primaryPrimaryEqualityOperatorOids]), foreignForeignEqualityOperatorOids: Object.freeze([...vector.foreignForeignEqualityOperatorOids]), defaultEqualityOperatorOids: Object.freeze([])
1063
+ });
1064
+ }));
1065
+ }
1066
+ /** Resolves FK default equality from the exact referenced PK/index/opfamily path. */
1067
+ private async readForeignKeyDefaultEquality(constraints: readonly OwnedCatalogConstraintV1[], operation: "registry-read" | "catalog-read"): Promise<readonly OwnedCatalogConstraintV1[]> {
1068
+ const foreignKeys = constraints.filter(constraint => constraint.kind === "foreignKey");
1069
+ if (!foreignKeys.length)
1070
+ return constraints;
1071
+ const targetPks = new Map<string, string>();
1072
+ for (let offset = 0; offset < foreignKeys.length; offset += 1024) {
1073
+ const batch = foreignKeys.slice(offset, offset + 1024), parameter = this.encodePgOidArrayParameter(batch.map(value => value.oid));
1074
+ const result = await this.source.query(`WITH requested AS (SELECT input.fk_oid,input.request_ordinality FROM pg_catalog.unnest($1::pg_catalog.oid[]) WITH ORDINALITY AS input(fk_oid,request_ordinality)) SELECT requested.request_ordinality::pg_catalog.text AS request_ordinality,fk.oid::pg_catalog.text AS fk_oid,fk.confrelid::pg_catalog.text AS referenced_relation_oid,fk.conindid::pg_catalog.text AS referenced_supporting_index_oid,target.pk_constraint_oid::pg_catalog.text AS target_pk_constraint_oid,target.pk_backing_index_oid::pg_catalog.text AS target_pk_backing_index_oid FROM requested JOIN pg_catalog.pg_constraint AS fk ON fk.oid OPERATOR(pg_catalog.=) requested.fk_oid AND fk.contype OPERATOR(pg_catalog.=) 'f'::pg_catalog."char" LEFT JOIN LATERAL (SELECT pk.oid AS pk_constraint_oid,pk.conindid AS pk_backing_index_oid FROM pg_catalog.pg_constraint AS pk WHERE pk.contype OPERATOR(pg_catalog.=) 'p'::pg_catalog."char" AND pk.conrelid OPERATOR(pg_catalog.=) fk.confrelid AND pk.conindid OPERATOR(pg_catalog.=) fk.conindid ORDER BY pk.oid LIMIT 2) AS target ON true ORDER BY requested.request_ordinality,target.pk_constraint_oid NULLS FIRST LIMIT 2049`, [parameter], operation);
1075
+ const rows = selectOwnedStoreRows(result, [
1076
+ "request_ordinality", "fk_oid", "referenced_relation_oid", "referenced_supporting_index_oid", "target_pk_constraint_oid", "target_pk_backing_index_oid"
1077
+ ], 2049);
1078
+ if (!rows) {
1079
+ this.source.unavailable();
1080
+ }
1081
+ this.wireRows(rows as readonly Row[], [
1082
+ "request_ordinality", "fk_oid", "referenced_relation_oid", "referenced_supporting_index_oid", "target_pk_constraint_oid", "target_pk_backing_index_oid"
1083
+ ], [], ["target_pk_constraint_oid", "target_pk_backing_index_oid"]);
1084
+ if (rows.length === 2049) {
1085
+ this.source.drift();
1086
+ }
1087
+ const grouped = new Map<string, Row[]>();
1088
+ for (const row of rows) {
1089
+ if (typeof row.request_ordinality !== "string" || typeof row.fk_oid !== "string" || typeof row.referenced_relation_oid !== "string" || typeof row.referenced_supporting_index_oid !== "string" || (row.target_pk_constraint_oid !== null && typeof row.target_pk_constraint_oid !== "string") || (row.target_pk_backing_index_oid !== null && typeof row.target_pk_backing_index_oid !== "string")) {
1090
+ this.source.unavailable();
1091
+ }
1092
+ const group = grouped.get(row.fk_oid) ?? [];
1093
+ group.push(row);
1094
+ grouped.set(row.fk_oid, group);
1095
+ }
1096
+ if ([...grouped.keys()].some(oid => !batch.some(fk => fk.oid === oid))) {
1097
+ this.source.drift();
1098
+ }
1099
+ for (let index = 0; index < batch.length; index++) {
1100
+ const fk = batch[index]!, group = grouped.get(fk.oid);
1101
+ if (!group || group.length !== 1) {
1102
+ this.source.drift();
1103
+ }
1104
+ const row = group[0]!;
1105
+ if (row.target_pk_constraint_oid === null || row.target_pk_backing_index_oid === null || row.request_ordinality !== String(index + 1) || row.fk_oid !== fk.oid || row.referenced_relation_oid !== fk.referencedRelationOid || row.referenced_supporting_index_oid !== fk.backingIndexOid || row.target_pk_backing_index_oid !== fk.backingIndexOid || !this.oid(row.referenced_relation_oid) || !this.oid(row.referenced_supporting_index_oid) || !this.oid(row.target_pk_constraint_oid) || !this.oid(row.target_pk_backing_index_oid)) {
1106
+ this.source.drift();
1107
+ }
1108
+ targetPks.set(fk.oid, row.target_pk_constraint_oid);
1109
+ }
1110
+ }
1111
+ const positions = new Map<string, {
1112
+ readonly family: string;
1113
+ readonly method: string;
1114
+ readonly type: string;
1115
+ }>();
1116
+ for (let offset = 0; offset < foreignKeys.length;) {
1117
+ const batch: OwnedCatalogConstraintV1[] = [];
1118
+ let expected = 0;
1119
+ while (offset < foreignKeys.length && batch.length < 1024 && expected + foreignKeys[offset]!.columns.length <= 65536) {
1120
+ const fk = foreignKeys[offset++]!;
1121
+ batch.push(fk);
1122
+ expected += fk.columns.length;
1123
+ }
1124
+ if (!batch.length) {
1125
+ this.source.drift();
1126
+ }
1127
+ const fks = this.encodePgOidArrayParameter(batch.map(value => value.oid)), pks = this.encodePgOidArrayParameter(batch.map(value => targetPks.get(value.oid) ?? "0"));
1128
+ const result = await this.source.query(`WITH fk_input AS (SELECT x.fk_oid,x.request_ordinality FROM pg_catalog.unnest($1::pg_catalog.oid[]) WITH ORDINALITY AS x(fk_oid,request_ordinality)),pk_input AS (SELECT x.pk_oid,x.request_ordinality FROM pg_catalog.unnest($2::pg_catalog.oid[]) WITH ORDINALITY AS x(pk_oid,request_ordinality)),requested AS (SELECT f.request_ordinality,f.fk_oid,p.pk_oid FROM fk_input AS f JOIN pk_input AS p ON p.request_ordinality OPERATOR(pg_catalog.=) f.request_ordinality) SELECT requested.request_ordinality::pg_catalog.text AS request_ordinality,fk.oid::pg_catalog.text AS fk_oid,src.fk_position::pg_catalog.text AS fk_position,src.source_attnum::pg_catalog.text AS source_attnum,ref.referenced_attnum::pg_catalog.text AS referenced_attnum,pk.oid::pg_catalog.text AS target_pk_constraint_oid,pg_catalog.cardinality(pk.conkey)::pg_catalog.text AS target_pk_key_count,pk_key.pk_position::pg_catalog.text AS target_pk_position,ix.indexrelid::pg_catalog.text AS target_index_oid,ix.indnkeyatts::pg_catalog.text AS target_index_key_count,ix_key.index_position::pg_catalog.text AS target_index_position,ix_op.opclass_oid::pg_catalog.text AS actual_opclass_oid,opc.opcfamily::pg_catalog.text AS opfamily_oid,opc.opcmethod::pg_catalog.text AS opclass_method_oid,family.opfmethod::pg_catalog.text AS opfamily_method_oid,ix_rel.relam::pg_catalog.text AS index_method_oid,attr.atttypid::pg_catalog.text AS referenced_type_oid FROM requested JOIN pg_catalog.pg_constraint AS fk ON fk.oid OPERATOR(pg_catalog.=) requested.fk_oid AND fk.contype OPERATOR(pg_catalog.=) 'f'::pg_catalog."char" JOIN pg_catalog.pg_constraint AS pk ON pk.oid OPERATOR(pg_catalog.=) requested.pk_oid AND pk.conrelid OPERATOR(pg_catalog.=) fk.confrelid AND pk.conindid OPERATOR(pg_catalog.=) fk.conindid JOIN pg_catalog.pg_index AS ix ON ix.indexrelid OPERATOR(pg_catalog.=) pk.conindid AND ix.indrelid OPERATOR(pg_catalog.=) pk.conrelid JOIN pg_catalog.pg_class AS ix_rel ON ix_rel.oid OPERATOR(pg_catalog.=) ix.indexrelid CROSS JOIN LATERAL pg_catalog.unnest(fk.conkey) WITH ORDINALITY AS src(source_attnum,fk_position) JOIN LATERAL pg_catalog.unnest(fk.confkey) WITH ORDINALITY AS ref(referenced_attnum,fk_position) ON ref.fk_position OPERATOR(pg_catalog.=) src.fk_position JOIN LATERAL pg_catalog.unnest(pk.conkey) WITH ORDINALITY AS pk_key(pk_attnum,pk_position) ON pk_key.pk_attnum OPERATOR(pg_catalog.=) ref.referenced_attnum JOIN LATERAL pg_catalog.unnest(ix.indkey) WITH ORDINALITY AS ix_key(index_attnum,index_position) ON ix_key.index_position OPERATOR(pg_catalog.=) pk_key.pk_position AND ix_key.index_attnum OPERATOR(pg_catalog.=) pk_key.pk_attnum AND ix_key.index_position OPERATOR(pg_catalog.<=) ix.indnkeyatts JOIN LATERAL pg_catalog.unnest(ix.indclass) WITH ORDINALITY AS ix_op(opclass_oid,index_position) ON ix_op.index_position OPERATOR(pg_catalog.=) ix_key.index_position JOIN pg_catalog.pg_attribute AS attr ON attr.attrelid OPERATOR(pg_catalog.=) fk.confrelid AND attr.attnum OPERATOR(pg_catalog.=) ref.referenced_attnum JOIN pg_catalog.pg_opclass AS opc ON opc.oid OPERATOR(pg_catalog.=) ix_op.opclass_oid JOIN pg_catalog.pg_opfamily AS family ON family.oid OPERATOR(pg_catalog.=) opc.opcfamily ORDER BY requested.request_ordinality,src.fk_position LIMIT $3::pg_catalog.int8`, [fks, pks, String(expected + 1)], operation);
1129
+ const aliases = [
1130
+ "request_ordinality", "fk_oid", "fk_position", "source_attnum", "referenced_attnum", "target_pk_constraint_oid", "target_pk_key_count", "target_pk_position", "target_index_oid", "target_index_key_count", "target_index_position", "actual_opclass_oid", "opfamily_oid", "opclass_method_oid", "opfamily_method_oid", "index_method_oid", "referenced_type_oid"
1131
+ ];
1132
+ const rows = selectOwnedStoreRows(result, aliases, expected + 1);
1133
+ if (!rows) {
1134
+ this.source.unavailable();
1135
+ }
1136
+ this.wireRows(rows as readonly Row[], aliases);
1137
+ if (rows.length === expected + 1) {
1138
+ this.source.drift();
1139
+ }
1140
+ for (const row of rows) {
1141
+ if (!aliases.every(alias => typeof row[alias] === "string")) {
1142
+ this.source.unavailable();
1143
+ }
1144
+ const requestOrdinality = row.request_ordinality as string, fkPosition = row.fk_position as string, sourceAttnum = row.source_attnum as string, referencedAttnum = row.referenced_attnum as string, targetPkPosition = row.target_pk_position as string, targetIndexPosition = row.target_index_position as string, targetPkWidth = row.target_pk_key_count as string, targetIndexWidth = row.target_index_key_count as string;
1145
+ const request = Number(requestOrdinality), position = Number(fkPosition), fk = Number.isSafeInteger(request) ? batch[request - 1] : undefined;
1146
+ const pkPosition = Number(targetPkPosition), indexPosition = Number(targetIndexPosition), pkWidth = Number(targetPkWidth), indexWidth = Number(targetIndexWidth);
1147
+ if (!/^[1-9][0-9]*$/u.test(requestOrdinality) || !/^[1-9][0-9]*$/u.test(fkPosition) || !/^[1-9][0-9]*$/u.test(sourceAttnum) || !/^[1-9][0-9]*$/u.test(referencedAttnum) || !/^[1-9][0-9]*$/u.test(targetPkPosition) || !/^[1-9][0-9]*$/u.test(targetIndexPosition) || !/^[1-9][0-9]*$/u.test(targetPkWidth) || !/^[1-9][0-9]*$/u.test(targetIndexWidth) || !fk || !Number.isSafeInteger(position) || position < 1 || position > fk.columns.length || !Number.isSafeInteger(pkPosition) || !Number.isSafeInteger(indexPosition) || !Number.isSafeInteger(pkWidth) || !Number.isSafeInteger(indexWidth) || pkWidth !== fk.columns.length || indexWidth !== fk.columns.length || pkPosition < 1 || pkPosition > pkWidth || indexPosition !== pkPosition || row.fk_oid !== fk.oid || row.target_pk_constraint_oid !== targetPks.get(fk.oid) || row.target_index_oid !== fk.backingIndexOid || row.opclass_method_oid !== row.opfamily_method_oid || row.opclass_method_oid !== row.index_method_oid || ![
1148
+ sourceAttnum, referencedAttnum, row.target_index_oid, row.actual_opclass_oid, row.opfamily_oid, row.opclass_method_oid, row.referenced_type_oid
1149
+ ].every(value => this.oid(value)) || BigInt(sourceAttnum) > 32767n || BigInt(referencedAttnum) > 32767n || positions.has(`${fk.oid}:${position}`)) {
1150
+ this.source.drift();
1151
+ }
1152
+ positions.set(`${fk.oid}:${position}`, Object.freeze({
1153
+ family: row.opfamily_oid as string, method: row.opclass_method_oid as string, type: row.referenced_type_oid as string
1154
+ }));
1155
+ }
1156
+ if (batch.some(fk => fk.columns.some((_, index) => !positions.has(`${fk.oid}:${index + 1}`)))) {
1157
+ this.source.drift();
1158
+ }
1159
+ }
1160
+ const tuples = [
1161
+ ...new Map([...positions.values()].map(value => [`${value.family}:${value.method}:${value.type}`, value])).values()
1162
+ ];
1163
+ const operators = new Map<string, string>();
1164
+ for (let offset = 0; offset < tuples.length; offset += 1024) {
1165
+ const batch = tuples.slice(offset, offset + 1024), families = this.encodePgOidArrayParameter(batch.map(value => value.family)), methods = this.encodePgOidArrayParameter(batch.map(value => value.method)), types = this.encodePgOidArrayParameter(batch.map(value => value.type));
1166
+ const result = await this.source.query(`WITH family_input AS (SELECT x.family_oid,x.request_ordinality FROM pg_catalog.unnest($1::pg_catalog.oid[]) WITH ORDINALITY AS x(family_oid,request_ordinality)),method_input AS (SELECT x.method_oid,x.request_ordinality FROM pg_catalog.unnest($2::pg_catalog.oid[]) WITH ORDINALITY AS x(method_oid,request_ordinality)),type_input AS (SELECT x.type_oid,x.request_ordinality FROM pg_catalog.unnest($3::pg_catalog.oid[]) WITH ORDINALITY AS x(type_oid,request_ordinality)),requested AS (SELECT f.request_ordinality,f.family_oid,m.method_oid,t.type_oid FROM family_input AS f JOIN method_input AS m ON m.request_ordinality OPERATOR(pg_catalog.=) f.request_ordinality JOIN type_input AS t ON t.request_ordinality OPERATOR(pg_catalog.=) f.request_ordinality) SELECT requested.request_ordinality::pg_catalog.text AS request_ordinality,requested.family_oid::pg_catalog.text AS requested_family_oid,requested.method_oid::pg_catalog.text AS requested_method_oid,requested.type_oid::pg_catalog.text AS requested_type_oid,candidate.amop_oid::pg_catalog.text AS amop_oid,candidate.amop_family_oid::pg_catalog.text AS amop_family_oid,candidate.amop_method_oid::pg_catalog.text AS amop_method_oid,candidate.amop_left_type_oid::pg_catalog.text AS amop_left_type_oid,candidate.amop_right_type_oid::pg_catalog.text AS amop_right_type_oid,candidate.amop_purpose::pg_catalog.text AS amop_purpose,candidate.amop_strategy::pg_catalog.text AS amop_strategy,candidate.operator_oid::pg_catalog.text AS operator_oid,candidate.operator_left_type_oid::pg_catalog.text AS operator_left_type_oid,candidate.operator_right_type_oid::pg_catalog.text AS operator_right_type_oid FROM requested LEFT JOIN LATERAL (SELECT amop.oid AS amop_oid,amop.amopfamily AS amop_family_oid,amop.amopmethod AS amop_method_oid,amop.amoplefttype AS amop_left_type_oid,amop.amoprighttype AS amop_right_type_oid,amop.amoppurpose AS amop_purpose,amop.amopstrategy AS amop_strategy,amop.amopopr AS operator_oid,op.oprleft AS operator_left_type_oid,op.oprright AS operator_right_type_oid FROM pg_catalog.pg_amop AS amop LEFT JOIN pg_catalog.pg_operator AS op ON op.oid OPERATOR(pg_catalog.=) amop.amopopr WHERE amop.amopfamily OPERATOR(pg_catalog.=) requested.family_oid AND amop.amopmethod OPERATOR(pg_catalog.=) requested.method_oid AND amop.amoppurpose OPERATOR(pg_catalog.=) 's'::pg_catalog."char" AND amop.amopstrategy OPERATOR(pg_catalog.=) 3::pg_catalog.int2 AND amop.amoplefttype OPERATOR(pg_catalog.=) requested.type_oid AND amop.amoprighttype OPERATOR(pg_catalog.=) requested.type_oid ORDER BY amop.oid,amop.amopopr LIMIT 2) AS candidate ON true ORDER BY requested.request_ordinality,candidate.amop_oid NULLS FIRST LIMIT 2049`, [families, methods, types], operation);
1167
+ const aliases = [
1168
+ "request_ordinality", "requested_family_oid", "requested_method_oid", "requested_type_oid", "amop_oid", "amop_family_oid", "amop_method_oid", "amop_left_type_oid", "amop_right_type_oid", "amop_purpose", "amop_strategy", "operator_oid", "operator_left_type_oid", "operator_right_type_oid"
1169
+ ];
1170
+ const rows = selectOwnedStoreRows(result, aliases, 2049);
1171
+ if (!rows) {
1172
+ this.source.unavailable();
1173
+ }
1174
+ this.wireRows(rows as readonly Row[], aliases, [], aliases.slice(4));
1175
+ if (rows.length === 2049) {
1176
+ this.source.drift();
1177
+ }
1178
+ const requestedAliases = aliases.slice(0, 4), candidateAliases = aliases.slice(4), grouped = new Map<string, Row[]>();
1179
+ for (const row of rows) {
1180
+ if (!requestedAliases.every(alias => typeof row[alias] === "string") || !candidateAliases.every(alias => row[alias] === null || typeof row[alias] === "string")) {
1181
+ this.source.unavailable();
1182
+ }
1183
+ const group = grouped.get(row.request_ordinality as string) ?? [];
1184
+ group.push(row);
1185
+ grouped.set(row.request_ordinality as string, group);
1186
+ }
1187
+ if ([...grouped.keys()].some(ordinal => !/^[1-9][0-9]*$/u.test(ordinal) || Number(ordinal) > batch.length)) {
1188
+ this.source.drift();
1189
+ }
1190
+ for (let index = 0; index < batch.length; index++) {
1191
+ const tuple = batch[index]!, group = grouped.get(String(index + 1));
1192
+ if (!group || group.length !== 1) {
1193
+ this.source.drift();
1194
+ }
1195
+ const row = group[0]!;
1196
+ if (!candidateAliases.every(alias => typeof row[alias] === "string") || row.requested_family_oid !== tuple.family || row.requested_method_oid !== tuple.method || row.requested_type_oid !== tuple.type || row.amop_family_oid !== tuple.family || row.amop_method_oid !== tuple.method || row.amop_left_type_oid !== tuple.type || row.amop_right_type_oid !== tuple.type || row.amop_purpose !== "s" || row.amop_strategy !== "3" || row.operator_left_type_oid !== tuple.type || row.operator_right_type_oid !== tuple.type || ![row.amop_oid, row.operator_oid].every(value => this.oid(value))) {
1197
+ this.source.drift();
1198
+ }
1199
+ operators.set(`${tuple.family}:${tuple.method}:${tuple.type}`, row.operator_oid as string);
1200
+ }
1201
+ }
1202
+ return Object.freeze(constraints.map(constraint => constraint.kind !== "foreignKey" ? constraint : Object.freeze({
1203
+ ...constraint, defaultEqualityOperatorOids: Object.freeze(constraint.columns.map((_, index) => {
1204
+ const tuple = positions.get(`${constraint.oid}:${index + 1}`), operator = tuple ? operators.get(`${tuple.family}:${tuple.method}:${tuple.type}`) : undefined;
1205
+ if (!operator) {
1206
+ this.source.drift();
1207
+ }
1208
+ return operator;
1209
+ }))
1210
+ })));
1211
+ }
1212
+ private async readTriggers(relations: readonly OwnedCatalogRelationV1[], constraints: readonly OwnedCatalogConstraintV1[], operation: "registry-read" | "catalog-read", budget: {
1213
+ remaining: number;
1214
+ }): Promise<readonly OwnedCatalogTriggerV1[]> {
1215
+ const relationOids = relations.map(value => value.oid), constraintOids = constraints.map(value => value.oid);
1216
+ if (!relationOids.length)
1217
+ return Object.freeze([]);
1218
+ const parameters: string[] = [], branches = (oids: readonly string[], name: string): string => {
1219
+ const out: string[] = [];
1220
+ for (let offset = 0; offset < oids.length; offset += 1024) {
1221
+ parameters.push(this.encodePgOidArrayParameter(oids.slice(offset, offset + 1024)));
1222
+ out.push(`SELECT input.oid FROM pg_catalog.unnest($${parameters.length}::pg_catalog.oid[]) AS input(oid)`);
1223
+ }
1224
+ return `WITH ${name}(oid) AS (${out.join(" UNION ALL ")})`;
1225
+ };
1226
+ const relationCte = branches(relationOids, "requested_relation"), constraintCte = constraintOids.length ? `,requested_constraint(oid) AS (${(() => {
1227
+ const out: string[] = [];
1228
+ for (let offset = 0; offset < constraintOids.length; offset += 1024) {
1229
+ parameters.push(this.encodePgOidArrayParameter(constraintOids.slice(offset, offset + 1024)));
1230
+ out.push(`SELECT input.oid FROM pg_catalog.unnest($${parameters.length}::pg_catalog.oid[]) AS input(oid)`);
1231
+ }
1232
+ return out.join(" UNION ALL ");
1233
+ })()})` : "";
1234
+ const issuedLimit = budget.remaining + 1;
1235
+ const result = await this.source.query(`${relationCte}${constraintCte} SELECT t.oid::pg_catalog.text AS trigger_oid,t.tgrelid::pg_catalog.text AS relation_oid,t.tgname AS trigger_name,t.tgisinternal AS is_internal,t.tgconstraint::pg_catalog.text AS constraint_oid,t.tgparentid::pg_catalog.text AS parent_trigger_oid,t.tgenabled::pg_catalog.text AS enabled_code,t.tgfoid::pg_catalog.text AS function_oid,n.nspname AS function_schema,p.proname AS function_name,t.tgtype::pg_catalog.text AS type_bits FROM pg_catalog.pg_trigger AS t LEFT JOIN pg_catalog.pg_proc AS p ON p.oid=t.tgfoid LEFT JOIN pg_catalog.pg_namespace AS n ON n.oid=p.pronamespace WHERE EXISTS (SELECT 1 FROM requested_relation AS r WHERE r.oid=t.tgrelid) OR ${constraintOids.length ? "EXISTS (SELECT 1 FROM requested_constraint AS c WHERE c.oid=t.tgconstraint)" : "false"} ORDER BY t.tgrelid,pg_catalog.convert_to(t.tgname,'UTF8'),t.oid LIMIT ${issuedLimit}`, parameters, operation);
1236
+ const aliases = [
1237
+ "trigger_oid", "relation_oid", "trigger_name", "is_internal", "constraint_oid", "parent_trigger_oid", "enabled_code", "function_oid", "function_schema", "function_name", "type_bits"
1238
+ ];
1239
+ const rows = selectOwnedStoreRows(result, aliases, issuedLimit);
1240
+ if (!rows) {
1241
+ this.source.unavailable();
1242
+ }
1243
+ this.wireRows(rows as readonly Row[], aliases, ["is_internal"], ["function_schema", "function_name"]);
1244
+ this.chargeRecords(budget, rows.length);
1245
+ const out: OwnedCatalogTriggerV1[] = [];
1246
+ for (const row of rows) {
1247
+ if (![
1248
+ row.trigger_oid, row.relation_oid, row.trigger_name, row.enabled_code, row.function_oid, row.type_bits
1249
+ ].every(value => typeof value === "string") || typeof row.is_internal !== "boolean" || (row.constraint_oid !== "0" && typeof row.constraint_oid !== "string") || (row.parent_trigger_oid !== "0" && typeof row.parent_trigger_oid !== "string") || (row.function_schema !== null && typeof row.function_schema !== "string") || (row.function_name !== null && typeof row.function_name !== "string")) {
1250
+ this.source.unavailable();
1251
+ }
1252
+ const constraint = row.constraint_oid === "0" ? null : row.constraint_oid as string, parent = row.parent_trigger_oid === "0" ? null : row.parent_trigger_oid as string, enabled: OwnedCatalogTriggerV1["enabled"] = row.enabled_code === "O" ? "origin" : row.enabled_code === "A" ? "always" : row.enabled_code === "R" ? "replica" : row.enabled_code === "D" ? "disabled" : "other";
1253
+ if (row.function_schema === null || row.function_name === null || ![row.trigger_oid, row.relation_oid, row.function_oid].every(value => typeof value === "string" && this.oid(value)) || (constraint !== null && !this.oid(constraint)) || (parent !== null && !this.oid(parent)) || (!relationOids.includes(row.relation_oid as string) && (constraint === null || !constraintOids.includes(constraint))) || !/^[1-9][0-9]*$/u.test(row.type_bits as string) || BigInt(row.type_bits as string) > 32767n) {
1254
+ this.source.drift();
1255
+ }
1256
+ out.push(Object.freeze({
1257
+ oid: row.trigger_oid as string, relationOid: row.relation_oid as string, name: row.trigger_name as string, internal: row.is_internal, constraintOid: constraint, parentTriggerOid: parent, enabled, functionOid: row.function_oid as string, functionSchema: row.function_schema as string, functionName: row.function_name as string, typeBits: row.type_bits as string
1258
+ }));
1259
+ }
1260
+ return Object.freeze(out);
1261
+ }
1262
+ private async readRules(relations: readonly OwnedCatalogRelationV1[], operation: "registry-read" | "catalog-read", budget: {
1263
+ remaining: number;
1264
+ }): Promise<readonly OwnedCatalogRuleV1[]> {
1265
+ const ids = relations.map(value => value.oid);
1266
+ if (!ids.length)
1267
+ return Object.freeze([]);
1268
+ const out: OwnedCatalogRuleV1[] = [];
1269
+ for (let offset = 0; offset < ids.length; offset += 1024) {
1270
+ const parameter = this.encodePgOidArrayParameter(ids.slice(offset, offset + 1024)), issuedLimit = budget.remaining + 1;
1271
+ const result = await this.source.query(`SELECT r.oid::pg_catalog.text AS rule_oid,r.ev_class::pg_catalog.text AS relation_oid,r.rulename AS rule_name,r.ev_type::pg_catalog.text AS event_code,r.ev_enabled::pg_catalog.text AS enabled_code,r.is_instead AS is_instead FROM pg_catalog.pg_rewrite AS r WHERE r.ev_class=ANY($1::pg_catalog.oid[]) ORDER BY r.ev_class,pg_catalog.convert_to(r.rulename,'UTF8'),r.oid LIMIT ${issuedLimit}`, [parameter], operation);
1272
+ const aliases = ["rule_oid", "relation_oid", "rule_name", "event_code", "enabled_code", "is_instead"];
1273
+ const rows = selectOwnedStoreRows(result, aliases, issuedLimit);
1274
+ if (!rows) {
1275
+ this.source.unavailable();
1276
+ }
1277
+ this.wireRows(rows as readonly Row[], aliases, ["is_instead"]);
1278
+ this.chargeRecords(budget, rows.length);
1279
+ for (const row of rows) {
1280
+ const oid = row.rule_oid as string, relation = row.relation_oid as string;
1281
+ if (!this.oid(oid) || !ids.includes(relation) || !this.oid(relation)) {
1282
+ this.source.drift();
1283
+ }
1284
+ out.push(Object.freeze({
1285
+ oid, relationOid: relation, name: row.rule_name as string, event: row.event_code as string, enabled: row.enabled_code as string, instead: row.is_instead as boolean
1286
+ }));
1287
+ }
1288
+ }
1289
+ return Object.freeze(out);
1290
+ }
1291
+ private async readPolicies(relations: readonly OwnedCatalogRelationV1[], operation: "registry-read" | "catalog-read", budget: {
1292
+ remaining: number;
1293
+ }): Promise<readonly OwnedCatalogPolicyV1[]> {
1294
+ const ids = relations.map(value => value.oid);
1295
+ if (!ids.length)
1296
+ return Object.freeze([]);
1297
+ const parents: {
1298
+ readonly oid: string;
1299
+ readonly relation: string;
1300
+ readonly width: number;
1301
+ readonly name: string;
1302
+ readonly permissive: boolean;
1303
+ readonly command: string;
1304
+ readonly using: string | null;
1305
+ readonly check: string | null;
1306
+ }[] = [];
1307
+ for (let offset = 0; offset < ids.length; offset += 1024) {
1308
+ const batchIds = ids.slice(offset, offset + 1024), parameter = this.encodePgOidArrayParameter(batchIds), issuedLimit = budget.remaining + 1;
1309
+ const result = await this.source.query(`SELECT p.oid::pg_catalog.text AS policy_oid,p.polrelid::pg_catalog.text AS relation_oid,p.polname AS policy_name,p.polpermissive AS permissive,p.polcmd::pg_catalog.text AS command_code,pg_catalog.pg_get_expr(p.polqual,p.polrelid,false) AS using_expression,pg_catalog.pg_get_expr(p.polwithcheck,p.polrelid,false) AS check_expression,COALESCE(pg_catalog.cardinality(p.polroles),0)::pg_catalog.text AS role_count FROM pg_catalog.pg_policy AS p WHERE p.polrelid=ANY($1::pg_catalog.oid[]) ORDER BY p.polrelid,pg_catalog.convert_to(p.polname,'UTF8'),p.oid LIMIT ${issuedLimit}`, [parameter], operation);
1310
+ const rows = selectOwnedStoreRows(result, [
1311
+ "policy_oid", "relation_oid", "policy_name", "permissive", "command_code", "using_expression", "check_expression", "role_count"
1312
+ ], issuedLimit);
1313
+ if (!rows) {
1314
+ this.source.unavailable();
1315
+ }
1316
+ this.wireRows(rows as readonly Row[], [
1317
+ "policy_oid", "relation_oid", "policy_name", "permissive", "command_code", "using_expression", "check_expression", "role_count"
1318
+ ], ["permissive"], ["using_expression", "check_expression"]);
1319
+ this.chargeRecords(budget, rows.length);
1320
+ for (const row of rows) {
1321
+ if (![row.policy_oid, row.relation_oid, row.policy_name, row.command_code, row.role_count].every(value => typeof value === "string") || typeof row.permissive !== "boolean" || (row.using_expression !== null && typeof row.using_expression !== "string") || (row.check_expression !== null && typeof row.check_expression !== "string")) {
1322
+ this.source.unavailable();
1323
+ }
1324
+ const oid = row.policy_oid as string, relation = row.relation_oid as string, count = row.role_count as string;
1325
+ if (!this.oid(oid) || !this.oid(relation) || !batchIds.includes(relation) || !/^(0|[1-9][0-9]*)$/u.test(count) || BigInt(count) > 65536n) {
1326
+ this.source.drift();
1327
+ }
1328
+ parents.push(Object.freeze({
1329
+ oid, relation, width: Number(count), name: row.policy_name as string, permissive: row.permissive, command: row.command_code as string, using: row.using_expression as string | null, check: row.check_expression as string | null
1330
+ }));
1331
+ }
1332
+ }
1333
+ const roles = new Map<string, string[]>();
1334
+ for (let offset = 0; offset < parents.length;) {
1335
+ const batch: typeof parents = [];
1336
+ let expected = 0;
1337
+ while (offset < parents.length && batch.length < 1024 && expected + parents[offset]!.width <= 65536) {
1338
+ const parent = parents[offset++]!;
1339
+ batch.push(parent);
1340
+ expected += parent.width;
1341
+ }
1342
+ if (!batch.length) {
1343
+ this.source.drift();
1344
+ }
1345
+ const parameter = this.encodePgOidArrayParameter(batch.map(value => value.oid));
1346
+ const result = await this.source.query(`WITH requested(policy_oid,request_ordinality) AS (SELECT input.policy_oid,input.request_ordinality FROM pg_catalog.unnest($1::pg_catalog.oid[]) WITH ORDINALITY AS input(policy_oid,request_ordinality)) SELECT requested.request_ordinality::pg_catalog.text AS request_ordinality,p.oid::pg_catalog.text AS policy_oid,element.element_ordinality::pg_catalog.text AS element_ordinality,element.role_oid::pg_catalog.text AS role_oid FROM requested JOIN pg_catalog.pg_policy AS p ON p.oid=requested.policy_oid CROSS JOIN LATERAL pg_catalog.unnest(p.polroles) WITH ORDINALITY AS element(role_oid,element_ordinality) ORDER BY requested.request_ordinality,element.element_ordinality LIMIT ${expected + 1}`, [parameter], operation);
1347
+ const rows = selectOwnedStoreRows(result, ["request_ordinality", "policy_oid", "element_ordinality", "role_oid"], expected + 1);
1348
+ if (!rows) {
1349
+ this.source.unavailable();
1350
+ }
1351
+ this.wireRows(rows as readonly Row[], ["request_ordinality", "policy_oid", "element_ordinality", "role_oid"]);
1352
+ if (rows.length === expected + 1) {
1353
+ this.source.drift();
1354
+ }
1355
+ for (const row of rows) {
1356
+ if (![row.request_ordinality, row.policy_oid, row.element_ordinality, row.role_oid].every(value => typeof value === "string")) {
1357
+ this.source.unavailable();
1358
+ }
1359
+ const ordinal = row.request_ordinality as string, policy = row.policy_oid as string, element = row.element_ordinality as string, role = row.role_oid as string, request = Number(ordinal), position = Number(element), parent = Number.isSafeInteger(request) ? batch[request - 1] : undefined;
1360
+ if (!/^[1-9][0-9]*$/u.test(ordinal) || !/^[1-9][0-9]*$/u.test(element) || !parent || parent.oid !== policy || !Number.isSafeInteger(position) || position < 1 || position > parent.width || !/^(0|[1-9][0-9]*)$/u.test(role) || (role !== "0" && !this.oid(role))) {
1361
+ this.source.drift();
1362
+ }
1363
+ const list = roles.get(parent.oid) ?? [];
1364
+ if (list.length !== position - 1) {
1365
+ this.source.drift();
1366
+ }
1367
+ list.push(role);
1368
+ roles.set(parent.oid, list);
1369
+ }
1370
+ for (const parent of batch)
1371
+ if ((roles.get(parent.oid)?.length ?? 0) !== parent.width) {
1372
+ this.source.drift();
1373
+ }
1374
+ }
1375
+ return Object.freeze(parents.map(parent => Object.freeze({
1376
+ oid: parent.oid, relationOid: parent.relation, name: parent.name, permissive: parent.permissive, command: parent.command, roles: Object.freeze([...(roles.get(parent.oid) ?? [])]), usingExpression: parent.using, checkExpression: parent.check
1377
+ })));
1378
+ }
1379
+ private async readInheritance(relations: readonly OwnedCatalogRelationV1[], operation: "registry-read" | "catalog-read", budget: {
1380
+ remaining: number;
1381
+ }): Promise<readonly OwnedCatalogInheritanceV1[]> {
1382
+ const ids = relations.map(value => value.oid);
1383
+ if (!ids.length)
1384
+ return Object.freeze([]);
1385
+ const parameters: string[] = [];
1386
+ const branches: string[] = [];
1387
+ for (let offset = 0; offset < ids.length; offset += 1024) {
1388
+ parameters.push(this.encodePgOidArrayParameter(ids.slice(offset, offset + 1024)));
1389
+ branches.push(`SELECT input.oid FROM pg_catalog.unnest($${parameters.length}::pg_catalog.oid[]) AS input(oid)`);
1390
+ }
1391
+ const issuedLimit = budget.remaining + 1, result = await this.source.query(`WITH requested(oid) AS (${branches.join(" UNION ALL ")}) SELECT i.inhrelid::pg_catalog.text AS child_relation_oid,i.inhparent::pg_catalog.text AS parent_relation_oid,i.inhseqno::pg_catalog.text AS sequence FROM pg_catalog.pg_inherits AS i WHERE EXISTS (SELECT 1 FROM requested AS r WHERE r.oid=i.inhrelid) OR EXISTS (SELECT 1 FROM requested AS r WHERE r.oid=i.inhparent) ORDER BY i.inhrelid,i.inhparent,i.inhseqno LIMIT ${issuedLimit}`, parameters, operation);
1392
+ const aliases = ["child_relation_oid", "parent_relation_oid", "sequence"], rows = selectOwnedStoreRows(result, aliases, issuedLimit);
1393
+ if (!rows) {
1394
+ this.source.unavailable();
1395
+ }
1396
+ this.wireRows(rows as readonly Row[], aliases);
1397
+ this.chargeRecords(budget, rows.length);
1398
+ const out: OwnedCatalogInheritanceV1[] = [];
1399
+ for (const row of rows) {
1400
+ const childRelationOid = row.child_relation_oid as string, parentRelationOid = row.parent_relation_oid as string, sequence = row.sequence as string;
1401
+ if (!this.oid(childRelationOid) || !this.oid(parentRelationOid) || (!ids.includes(childRelationOid) && !ids.includes(parentRelationOid)) || !/^[1-9][0-9]*$/u.test(sequence) || BigInt(sequence) > 2147483647n) {
1402
+ this.source.drift();
1403
+ }
1404
+ out.push(Object.freeze({ childRelationOid, parentRelationOid, sequence }));
1405
+ }
1406
+ return Object.freeze(out);
1407
+ }
1408
+ private async readPgClassOid(operation: "registry-read" | "catalog-read"): Promise<string> {
1409
+ const result = await this.source.query("SELECT c.oid::pg_catalog.text AS catalog_class_oid FROM pg_catalog.pg_class AS c JOIN pg_catalog.pg_namespace AS n ON n.oid=c.relnamespace WHERE n.nspname='pg_catalog' AND c.relname='pg_class' LIMIT 2", [], operation);
1410
+ const rows = selectOwnedStoreRows(result, ["catalog_class_oid"], 2);
1411
+ if (!rows) {
1412
+ this.source.unavailable();
1413
+ }
1414
+ for (const row of rows)
1415
+ if (typeof row.catalog_class_oid !== "string") {
1416
+ this.source.unavailable();
1417
+ }
1418
+ if (rows.length !== 1 || !this.oid(rows[0]!.catalog_class_oid)) {
1419
+ this.source.drift();
1420
+ }
1421
+ return rows[0]!.catalog_class_oid;
1422
+ }
1423
+ private async readIdentitySequenceOids(columns: readonly OwnedCatalogColumnV1[], pgClassOid: string, operation: "registry-read" | "catalog-read"): Promise<readonly string[]> {
1424
+ const drift = (): never => {
1425
+ this.source.drift();
1426
+ }, lock = (): never => {
1427
+ this.source.unavailable();
1428
+ }, owners = new Map<string, Set<string>>();
1429
+ for (const column of columns) {
1430
+ if (column.identityCode === "")
1431
+ continue;
1432
+ if (!this.oid(column.relationOid) || !/^[1-9][0-9]*$/u.test(column.attnum) || BigInt(column.attnum) > 32767n)
1433
+ drift();
1434
+ const attributes = owners.get(column.relationOid) ?? new Set<string>();
1435
+ if (attributes.has(column.attnum))
1436
+ drift();
1437
+ attributes.add(column.attnum);
1438
+ owners.set(column.relationOid, attributes);
1439
+ }
1440
+ if (!owners.size)
1441
+ return Object.freeze([]);
1442
+ if (!this.oid(pgClassOid))
1443
+ drift();
1444
+ const ids = [...owners.keys()].sort((a, b) => BigInt(a) < BigInt(b) ? -1 : BigInt(a) > BigInt(b) ? 1 : 0), seen = new Set<string>(), sequences = new Map<string, string>(), aliases = [
1445
+ "dependent_class_oid", "sequence_oid", "dependent_sub_id", "referenced_class_oid", "owner_relation_oid", "owner_attnum", "dependency_type"
1446
+ ];
1447
+ for (let offset = 0; offset < ids.length;) {
1448
+ const batch: string[] = [];
1449
+ let expected = 0;
1450
+ while (offset < ids.length && batch.length < 1024) {
1451
+ const id = ids[offset]!, width = owners.get(id)!.size;
1452
+ if (expected + width > 65536)
1453
+ break;
1454
+ batch.push(id);
1455
+ expected += width;
1456
+ offset++;
1457
+ }
1458
+ if (!batch.length)
1459
+ drift();
1460
+ const result = await this.source.query(`SELECT d.classid::pg_catalog.text AS dependent_class_oid,d.objid::pg_catalog.text AS sequence_oid,d.objsubid::pg_catalog.text AS dependent_sub_id,d.refclassid::pg_catalog.text AS referenced_class_oid,d.refobjid::pg_catalog.text AS owner_relation_oid,d.refobjsubid::pg_catalog.text AS owner_attnum,d.deptype::pg_catalog.text AS dependency_type FROM pg_catalog.pg_depend AS d JOIN pg_catalog.pg_attribute AS a ON a.attrelid=d.refobjid AND a.attnum=d.refobjsubid WHERE d.classid=$2::pg_catalog.oid AND d.refclassid=$2::pg_catalog.oid AND d.objsubid=0 AND d.deptype='i'::pg_catalog."char" AND d.refobjid=ANY($1::pg_catalog.oid[]) AND a.attidentity<>''::pg_catalog."char" ORDER BY d.refobjid,d.refobjsubid,d.objid LIMIT ${expected + 1}`, [this.encodePgOidArrayParameter(batch), pgClassOid], operation), maybeRows = selectOwnedStoreRows(result, aliases, expected + 1);
1461
+ if (!maybeRows)
1462
+ lock();
1463
+ const rows = maybeRows as readonly Row[];
1464
+ for (const row of rows)
1465
+ for (const alias of aliases)
1466
+ if (typeof row[alias] !== "string")
1467
+ lock();
1468
+ if (rows.length === expected + 1)
1469
+ drift();
1470
+ const issued = new Set(batch);
1471
+ for (const row of rows) {
1472
+ const owner = row.owner_relation_oid as string, attnum = row.owner_attnum as string, sequence = row.sequence_oid as string, key = `${owner}:${attnum}`;
1473
+ if (row.dependent_class_oid !== pgClassOid || row.referenced_class_oid !== pgClassOid || row.dependent_sub_id !== "0" || row.dependency_type !== "i" || !issued.has(owner) || !owners.get(owner)?.has(attnum) || !this.oid(sequence) || seen.has(key) || sequences.has(sequence))
1474
+ drift();
1475
+ seen.add(key);
1476
+ sequences.set(sequence, key);
1477
+ }
1478
+ for (const owner of batch)
1479
+ for (const attnum of owners.get(owner)!)
1480
+ if (!seen.has(`${owner}:${attnum}`))
1481
+ drift();
1482
+ }
1483
+ return Object.freeze([...sequences.keys()].sort((a, b) => BigInt(a) < BigInt(b) ? -1 : BigInt(a) > BigInt(b) ? 1 : 0));
1484
+ }
1485
+ private async readSequences(relations: readonly OwnedCatalogRelationV1[], operation: "registry-read" | "catalog-read", budget: {
1486
+ remaining: number;
1487
+ }): Promise<readonly OwnedCatalogSequenceV1[]> {
1488
+ const ids = relations.filter(relation => relation.kind === "sequence").map(relation => relation.oid);
1489
+ if (!ids.length)
1490
+ return Object.freeze([]);
1491
+ const out: OwnedCatalogSequenceV1[] = [];
1492
+ for (let offset = 0; offset < ids.length; offset += 1024) {
1493
+ const batch = ids.slice(offset, offset + 1024), parameter = this.encodePgOidArrayParameter(batch), issuedLimit = Math.min(batch.length + 1, budget.remaining + 1), result = await this.source.query(`SELECT s.seqrelid::pg_catalog.text AS relation_oid,s.seqtypid::pg_catalog.text AS sequence_type_oid,t.oid::pg_catalog.text AS resolved_type_oid,n.nspname AS type_schema,t.typname AS type_name,s.seqstart::pg_catalog.text AS start_value,s.seqincrement::pg_catalog.text AS increment_value,s.seqmin::pg_catalog.text AS minimum_value,s.seqmax::pg_catalog.text AS maximum_value,s.seqcache::pg_catalog.text AS cache_value,s.seqcycle AS cycle FROM pg_catalog.pg_sequence AS s LEFT JOIN pg_catalog.pg_type AS t ON t.oid=s.seqtypid LEFT JOIN pg_catalog.pg_namespace AS n ON n.oid=t.typnamespace WHERE s.seqrelid=ANY($1::pg_catalog.oid[]) ORDER BY s.seqrelid LIMIT ${issuedLimit}`, [parameter], operation), aliases = [
1494
+ "relation_oid", "sequence_type_oid", "resolved_type_oid", "type_schema", "type_name", "start_value", "increment_value", "minimum_value", "maximum_value", "cache_value", "cycle"
1495
+ ], rows = selectOwnedStoreRows(result, aliases, issuedLimit);
1496
+ if (!rows) {
1497
+ this.source.unavailable();
1498
+ }
1499
+ this.wireRows(rows as readonly Row[], aliases, ["cycle"], ["resolved_type_oid", "type_schema", "type_name"]);
1500
+ this.chargeRecords(budget, rows.length);
1501
+ if (rows.length === issuedLimit) {
1502
+ this.source.drift();
1503
+ }
1504
+ const seen = new Set<string>();
1505
+ for (const row of rows) {
1506
+ const relationOid = row.relation_oid as string, sequenceTypeOid = row.sequence_type_oid as string, resolvedTypeOid = row.resolved_type_oid as string | null, typeSchema = row.type_schema as string | null, typeName = row.type_name as string | null, start = row.start_value as string, increment = row.increment_value as string, minimum = row.minimum_value as string, maximum = row.maximum_value as string, cache = row.cache_value as string, cycle = row.cycle as boolean;
1507
+ if (!batch.includes(relationOid) || seen.has(relationOid) || !this.oid(relationOid) || !this.oid(sequenceTypeOid) || resolvedTypeOid === null || typeSchema === null || typeName === null || resolvedTypeOid !== sequenceTypeOid || !this.oid(resolvedTypeOid) || ![start, increment, minimum, maximum].every(value => /^(?:0|-[1-9][0-9]*|[1-9][0-9]*)$/u.test(value) && BigInt(value) >= -9223372036854775808n && BigInt(value) <= 9223372036854775807n) || !/^[1-9][0-9]*$/u.test(cache) || BigInt(cache) > 9223372036854775807n) {
1508
+ this.source.drift();
1509
+ }
1510
+ const type = typeSchema === "pg_catalog" && typeName === "int8" ? "bigint" : typeSchema === "pg_catalog" && typeName === "int4" ? "integer" : typeSchema === "pg_catalog" && typeName === "int2" ? "smallint" : "other";
1511
+ out.push(Object.freeze({ relationOid, type, start, increment, minimum, maximum, cache, cycle }));
1512
+ seen.add(relationOid);
1513
+ }
1514
+ if (seen.size !== batch.length) {
1515
+ this.source.drift();
1516
+ }
1517
+ }
1518
+ return Object.freeze(out);
1519
+ }
1520
+ private async readIndexes(relations: readonly OwnedCatalogRelationV1[], operation: "registry-read" | "catalog-read", budget: {
1521
+ remaining: number;
1522
+ }): Promise<readonly OwnedCatalogIndexV1[]> {
1523
+ const issued = relations.map(relation => relation.oid);
1524
+ if (!issued.length)
1525
+ return Object.freeze([]);
1526
+ const indexOids = new Set<string>();
1527
+ for (let offset = 0; offset < issued.length; offset += 1024) {
1528
+ const batch = issued.slice(offset, offset + 1024), issuedLimit = budget.remaining + 1, result = await this.source.query(`SELECT i.indexrelid::pg_catalog.text AS index_relation_oid FROM pg_catalog.pg_index AS i WHERE i.indrelid=ANY($1::pg_catalog.oid[]) OR i.indexrelid=ANY($1::pg_catalog.oid[]) ORDER BY i.indexrelid LIMIT ${issuedLimit}`, [this.encodePgOidArrayParameter(batch)], operation), rows = selectOwnedStoreRows(result, ["index_relation_oid"], issuedLimit);
1529
+ if (!rows) {
1530
+ this.source.unavailable();
1531
+ }
1532
+ for (const row of rows)
1533
+ if (typeof row.index_relation_oid !== "string") {
1534
+ this.source.unavailable();
1535
+ }
1536
+ this.wireRows(rows as readonly Row[], ["index_relation_oid"]);
1537
+ if (rows.length === issuedLimit) {
1538
+ this.source.drift();
1539
+ }
1540
+ for (const row of rows) {
1541
+ const oid = row.index_relation_oid as string;
1542
+ if (!this.oid(oid)) {
1543
+ this.source.drift();
1544
+ }
1545
+ indexOids.add(oid);
1546
+ }
1547
+ }
1548
+ if (indexOids.size > budget.remaining) {
1549
+ this.source.drift();
1550
+ }
1551
+ const output: OwnedCatalogIndexV1[] = [], parentMethods = new Map<string, string>(), issuedSet = new Set(issued), rootIndexOids = new Set(relations.filter(relation => relation.kind === "index" || relation.kind === "partitionedIndex").map(relation => relation.oid)), discovered = [...indexOids].sort((left, right) => BigInt(left) < BigInt(right) ? -1 : BigInt(left) > BigInt(right) ? 1 : 0);
1552
+ for (let offset = 0; offset < discovered.length; offset += 1024) {
1553
+ const batch = discovered.slice(offset, offset + 1024), bound = batch.length * 2 + 1, result = await this.source.query(`SELECT i.indexrelid::pg_catalog.text AS index_relation_oid,i.indrelid::pg_catalog.text AS table_relation_oid,c.relname AS index_name,c.relam::pg_catalog.text AS method_oid,am.amname AS method_name,i.indisunique AS is_unique,i.indisprimary AS is_primary,i.indisexclusion AS is_exclusion,i.indimmediate AS is_immediate,i.indisvalid AS is_valid,i.indisready AS is_ready,i.indislive AS is_live,i.indisreplident AS is_replica_identity,i.indnullsnotdistinct AS nulls_not_distinct,i.indnkeyatts::pg_catalog.text AS key_attribute_count,i.indnatts::pg_catalog.text AS total_attribute_count,pg_catalog.pg_get_expr(i.indexprs,i.indrelid,false) AS index_expression,pg_catalog.pg_get_expr(i.indpred,i.indrelid,false) AS index_predicate,owner_constraint.constraint_oid::pg_catalog.text AS backing_constraint_oid FROM pg_catalog.pg_index AS i JOIN pg_catalog.pg_class AS c ON c.oid=i.indexrelid JOIN pg_catalog.pg_am AS am ON am.oid=c.relam LEFT JOIN LATERAL (SELECT con.oid AS constraint_oid FROM pg_catalog.pg_constraint AS con WHERE con.conindid=i.indexrelid AND (con.contype='p'::pg_catalog."char" OR con.contype='u'::pg_catalog."char" OR con.contype='x'::pg_catalog."char") ORDER BY con.oid LIMIT 2) AS owner_constraint ON true WHERE i.indexrelid=ANY($1::pg_catalog.oid[]) ORDER BY i.indexrelid,owner_constraint.constraint_oid NULLS FIRST LIMIT ${bound}`, [this.encodePgOidArrayParameter(batch)], operation), aliases = [
1554
+ "index_relation_oid", "table_relation_oid", "index_name", "method_oid", "method_name", "is_unique", "is_primary", "is_exclusion", "is_immediate", "is_valid", "is_ready", "is_live", "is_replica_identity", "nulls_not_distinct", "key_attribute_count", "total_attribute_count", "index_expression", "index_predicate", "backing_constraint_oid"
1555
+ ], rows = selectOwnedStoreRows(result, aliases, bound);
1556
+ if (!rows) {
1557
+ this.source.unavailable();
1558
+ }
1559
+ for (const row of rows)
1560
+ if (typeof row.index_relation_oid !== "string" || typeof row.table_relation_oid !== "string" || typeof row.index_name !== "string" || typeof row.method_oid !== "string" || typeof row.method_name !== "string" || typeof row.key_attribute_count !== "string" || typeof row.total_attribute_count !== "string" || typeof row.is_unique !== "boolean" || typeof row.is_primary !== "boolean" || typeof row.is_exclusion !== "boolean" || typeof row.is_immediate !== "boolean" || typeof row.is_valid !== "boolean" || typeof row.is_ready !== "boolean" || typeof row.is_live !== "boolean" || typeof row.is_replica_identity !== "boolean" || typeof row.nulls_not_distinct !== "boolean" || (row.index_expression !== null && typeof row.index_expression !== "string") || (row.index_predicate !== null && typeof row.index_predicate !== "string") || (row.backing_constraint_oid !== null && typeof row.backing_constraint_oid !== "string")) {
1561
+ this.source.unavailable();
1562
+ }
1563
+ if (rows.length === bound) {
1564
+ this.source.drift();
1565
+ }
1566
+ const parents = new Map<string, Row[]>();
1567
+ for (const row of rows) {
1568
+ const oid = row.index_relation_oid as string;
1569
+ if (!batch.includes(oid)) {
1570
+ this.source.drift();
1571
+ }
1572
+ const entries = parents.get(oid) ?? [];
1573
+ entries.push(row);
1574
+ parents.set(oid, entries);
1575
+ }
1576
+ if (parents.size !== batch.length) {
1577
+ this.source.drift();
1578
+ }
1579
+ for (const oid of batch) {
1580
+ const entries = parents.get(oid);
1581
+ if (!entries) {
1582
+ this.source.drift();
1583
+ }
1584
+ const method = entries[0]?.method_oid as string;
1585
+ if (!this.oid(method) || parentMethods.has(oid)) {
1586
+ this.source.drift();
1587
+ }
1588
+ parentMethods.set(oid, method);
1589
+ output.push(this.indexParent(oid, entries, issuedSet, rootIndexOids));
1590
+ }
1591
+ }
1592
+ this.chargeRecords(budget, output.length);
1593
+ return this.readIndexVectors(Object.freeze(output), operation, parentMethods);
1594
+ }
1595
+ private indexParent(indexOid: string, rows: readonly Row[], relations: ReadonlySet<string>, rootIndexes: ReadonlySet<string>): OwnedCatalogIndexV1 {
1596
+ const first = rows[0];
1597
+ if (!first) {
1598
+ this.source.drift();
1599
+ }
1600
+ const text = (value: unknown): string => {
1601
+ if (typeof value !== "string") {
1602
+ this.source.unavailable();
1603
+ }
1604
+ return value;
1605
+ };
1606
+ const bool = (value: unknown): boolean => {
1607
+ if (typeof value !== "boolean") {
1608
+ this.source.unavailable();
1609
+ }
1610
+ return value;
1611
+ };
1612
+ const oid = (value: unknown): string => {
1613
+ const result = text(value);
1614
+ if (!this.oid(result)) {
1615
+ this.source.drift();
1616
+ }
1617
+ return result;
1618
+ };
1619
+ const table = oid(first.table_relation_oid), keyCount = text(first.key_attribute_count), totalCount = text(first.total_attribute_count);
1620
+ if ((!relations.has(table) && !rootIndexes.has(indexOid)) || !/^[1-9][0-9]*$/u.test(keyCount) || !/^[1-9][0-9]*$/u.test(totalCount) || BigInt(keyCount) > 32767n || BigInt(totalCount) > 32767n || BigInt(keyCount) > BigInt(totalCount)) {
1621
+ this.source.drift();
1622
+ }
1623
+ const constraint = rows.map(row => row.backing_constraint_oid).filter(value => value !== null);
1624
+ if (rows.length !== 1 || constraint.length > 1 || (constraint[0] !== undefined && !this.oid(constraint[0]))) {
1625
+ this.source.drift();
1626
+ }
1627
+ return Object.freeze({
1628
+ indexRelationOid: oid(indexOid), tableRelationOid: table, name: text(first.index_name), method: text(first.method_name), unique: bool(first.is_unique), primary: bool(first.is_primary), exclusion: bool(first.is_exclusion), immediate: bool(first.is_immediate), valid: bool(first.is_valid), ready: bool(first.is_ready), live: bool(first.is_live), replicaIdentity: bool(first.is_replica_identity), nullsNotDistinct: bool(first.nulls_not_distinct), keyAttributeCount: keyCount, totalAttributeCount: totalCount, attributeNumbers: Object.freeze([]), columnNames: Object.freeze([]), collationOids: Object.freeze([]), opclassOids: Object.freeze([]), defaultOpclassOids: Object.freeze([]), options: Object.freeze([]), expression: first.index_expression === null ? null : text(first.index_expression), predicate: first.index_predicate === null ? null : text(first.index_predicate), backingConstraintOid: constraint.length ? constraint[0]! : null
1629
+ });
1630
+ }
1631
+ private columnRow(row: Row, issued: ReadonlySet<string>, relationKinds: ReadonlyMap<string, OwnedCatalogRelationV1["kind"]>): OwnedCatalogColumnV1 {
1632
+ const string = (value: unknown): string => {
1633
+ if (typeof value !== "string") {
1634
+ this.source.unavailable();
1635
+ }
1636
+ return value;
1637
+ };
1638
+ const boolean = (value: unknown): boolean => {
1639
+ if (typeof value !== "boolean") {
1640
+ this.source.unavailable();
1641
+ }
1642
+ return value;
1643
+ };
1644
+ const oid = (value: unknown, zero = false): string => {
1645
+ const result = string(value);
1646
+ if ((!zero && !this.oid(result)) || (zero && result !== "0" && !this.oid(result))) {
1647
+ this.source.drift();
1648
+ }
1649
+ return result;
1650
+ };
1651
+ const relationOid = oid(row.relation_oid);
1652
+ const attnum = string(row.attnum), inheritanceCount = string(row.inheritance_count);
1653
+ if (!issued.has(relationOid) || !/^[1-9][0-9]*$/u.test(attnum) || !/^(0|[1-9][0-9]*)$/u.test(inheritanceCount)) {
1654
+ this.source.drift();
1655
+ }
1656
+ if ((row.type_default_collation_oid !== null && typeof row.type_default_collation_oid !== "string") || (row.type_default_storage_code !== null && typeof row.type_default_storage_code !== "string")) {
1657
+ this.source.unavailable();
1658
+ }
1659
+ if (row.type_default_collation_oid === null || row.type_default_storage_code === null) {
1660
+ this.source.drift();
1661
+ }
1662
+ const hasDefault = boolean(row.has_default), defaultOid = row.default_object_oid === null ? null : oid(row.default_object_oid), defaultExpression = row.default_expression === null ? null : string(row.default_expression);
1663
+ if ((defaultOid === null) !== (defaultExpression === null) || hasDefault !== (defaultOid !== null)) {
1664
+ this.source.drift();
1665
+ }
1666
+ const rawType = string(row.physical_type), relationKind = relationKinds.get(relationOid);
1667
+ if (!relationKind) {
1668
+ this.source.drift();
1669
+ }
1670
+ const canonical: string = relationKind === "toastTable" ? rawType : rawType === rawType.trim().toLowerCase() ? (exactPostgresType(rawType, canonicalPostgresType(rawType)) ?? "unknown") : rawType;
1671
+ const defaultValue = canonicalPostgresDefault(defaultExpression, canonical);
1672
+ if (defaultValue.unsupported || defaultValue.value === undefined) {
1673
+ this.source.drift();
1674
+ }
1675
+ const identityRaw = string(row.identity_code), generatedRaw = string(row.generated_code);
1676
+ if (identityRaw.length > 1 || generatedRaw.length > 1) {
1677
+ this.source.drift();
1678
+ }
1679
+ const identityCode: OwnedCatalogColumnV1["identityCode"] = identityRaw === "" || identityRaw === "a" || identityRaw === "d" ? identityRaw : "other";
1680
+ const generatedCode: OwnedCatalogColumnV1["generatedCode"] = generatedRaw === "" || generatedRaw === "s" || generatedRaw === "v" ? generatedRaw : "other";
1681
+ let generation: OwnedCatalogColumnV1["generation"] = "other";
1682
+ if (identityCode === "d" && generatedCode === "" && !hasDefault)
1683
+ generation = "identityByDefault";
1684
+ else if (identityCode === "" && generatedCode === "" && defaultValue.kind === "uuidV4")
1685
+ generation = "uuidDefault";
1686
+ else if (identityCode === "" && generatedCode === "" && !hasDefault)
1687
+ generation = "none";
1688
+ else if (identityCode === "" && generatedCode === "" && hasDefault)
1689
+ generation = "none";
1690
+ return Object.freeze({
1691
+ relationOid, attnum, name: string(row.column_name), dropped: boolean(row.dropped), local: boolean(row.local), inheritanceCount, physicalType: canonical, typeOid: oid(row.type_oid, true), notNull: boolean(row.not_null), default: Object.freeze(defaultValue.value), defaultObjectOid: defaultOid, generation, identityCode, generatedCode, collationOid: oid(row.collation_oid, true), typeDefaultCollationOid: oid(row.type_default_collation_oid, true), storageCode: string(row.storage_code), typeDefaultStorageCode: string(row.type_default_storage_code), compressionCode: row.compression_code === "" || row.compression_code === "p" || row.compression_code === "l" ? row.compression_code : typeof row.compression_code === "string" ? "other" : (() => {
1692
+ this.source.unavailable();
1693
+ })()
1694
+ });
1695
+ }
1696
+ private catalogScopes(value: readonly OrmCatalogScopeV1[]): readonly OrmCatalogScopeV1[] {
1697
+ try {
1698
+ if (!Array.isArray(value) || types.isProxy(value) || Object.getOwnPropertySymbols(value).length || value.length > 8320)
1699
+ throw new Error();
1700
+ const own = Object.getOwnPropertyDescriptors(value);
1701
+ if (Object.keys(own).length !== value.length + 1 || Object.keys(own).some(key => key !== "length" && (!/^(0|[1-9][0-9]*)$/u.test(key) || Number(key) >= value.length)))
1702
+ throw new Error();
1703
+ const output: OrmCatalogScopeV1[] = [];
1704
+ let previous: OrmCatalogScopeV1 | undefined;
1705
+ for (let index = 0; index < value.length; index++) {
1706
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
1707
+ if (!descriptor || !("value" in descriptor) || descriptor.value === null || typeof descriptor.value !== "object" || Array.isArray(descriptor.value) || types.isProxy(descriptor.value) || Object.getOwnPropertySymbols(descriptor.value).length)
1708
+ throw new Error();
1709
+ const candidate = descriptor.value;
1710
+ const candidateKeys = Object.keys(Object.getOwnPropertyDescriptors(candidate));
1711
+ if (candidateKeys.length !== 2 || !candidateKeys.includes("schema") || !candidateKeys.includes("tablePrefix"))
1712
+ throw new Error();
1713
+ const schema = Object.getOwnPropertyDescriptor(candidate, "schema"), tablePrefix = Object.getOwnPropertyDescriptor(candidate, "tablePrefix");
1714
+ if (!schema || !("value" in schema) || !tablePrefix || !("value" in tablePrefix) || typeof schema.value !== "string" || typeof tablePrefix.value !== "string")
1715
+ throw new Error();
1716
+ const scope = Object.freeze({ schema: schema.value, tablePrefix: tablePrefix.value });
1717
+ if (Buffer.byteLength(scope.schema, "utf8") < 1 || Buffer.byteLength(scope.schema, "utf8") > 63 || Buffer.byteLength(scope.tablePrefix, "utf8") < 1 || Buffer.byteLength(scope.tablePrefix, "utf8") > 63 || /[\x00-\x1f\x7f-\x9f]|[\ud800-\udfff]/u.test(scope.schema) || /[\x00-\x1f\x7f-\x9f]|[\ud800-\udfff]/u.test(scope.tablePrefix))
1718
+ throw new Error();
1719
+ if (previous && Buffer.compare(Buffer.from(previous.schema, "utf8"), Buffer.from(scope.schema, "utf8")) >= 0 && (previous.schema !== scope.schema || Buffer.compare(Buffer.from(previous.tablePrefix, "utf8"), Buffer.from(scope.tablePrefix, "utf8")) >= 0))
1720
+ throw new Error();
1721
+ output.push(scope);
1722
+ previous = scope;
1723
+ }
1724
+ return Object.freeze(output);
1725
+ }
1726
+ catch {
1727
+ throw failure("ORM_OWNED_STORE_DRIFT");
1728
+ }
1729
+ }
1730
+ private wireRows(rows: readonly Row[], aliases: readonly string[], booleanAliases: readonly string[] = [], nullableAliases: readonly string[] = []): void {
1731
+ const booleans = new Set(booleanAliases), nullable = new Set(nullableAliases);
1732
+ for (const row of rows)
1733
+ for (const alias of aliases) {
1734
+ const value = row[alias];
1735
+ if (value === null && nullable.has(alias))
1736
+ continue;
1737
+ if ((booleans.has(alias) ? typeof value !== "boolean" : typeof value !== "string")) {
1738
+ this.source.unavailable();
1739
+ }
1740
+ }
1741
+ }
1742
+ private signedInt2(value: string): boolean {
1743
+ return /^(?:0|-?[1-9][0-9]*)$/u.test(value) && BigInt(value) >= -32768n && BigInt(value) <= 32767n;
1744
+ }
1745
+ private freezeCheck(value: unknown): unknown {
1746
+ if (Array.isArray(value)) {
1747
+ for (const item of value)
1748
+ this.freezeCheck(item);
1749
+ return Object.freeze(value);
1750
+ }
1751
+ if (value !== null && typeof value === "object") {
1752
+ for (const item of Object.values(value as Record<string, unknown>))
1753
+ this.freezeCheck(item);
1754
+ return Object.freeze(value);
1755
+ }
1756
+ return value;
1757
+ }
1758
+ }
1759
+ /** Snapshot native SELECT rows without invoking getters or accepting driver shape drift. */
1760
+ export function selectOwnedStoreRows(value: unknown, aliases: readonly string[], maximum: number): readonly Readonly<Record<string, unknown>>[] | undefined {
1761
+ try {
1762
+ if (!Array.isArray(value) || types.isProxy(value))
1763
+ return undefined;
1764
+ const lengthDescriptor = Object.getOwnPropertyDescriptor(value, "length");
1765
+ if (!lengthDescriptor || !("value" in lengthDescriptor) || typeof lengthDescriptor.value !== "number")
1766
+ return undefined;
1767
+ const length = lengthDescriptor.value;
1768
+ if (!Number.isSafeInteger(length) || length < 0 || length > maximum)
1769
+ return undefined;
1770
+ const allowed = new Set(["length", "count", "affectedRows", "command", "lastInsertRowid"]);
1771
+ for (let index = 0; index < length; index++)
1772
+ allowed.add(String(index));
1773
+ for (const key of Reflect.ownKeys(value)) {
1774
+ if (typeof key !== "string" || !allowed.has(key))
1775
+ return undefined;
1776
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
1777
+ if (!descriptor || !("value" in descriptor))
1778
+ return undefined;
1779
+ }
1780
+ const rows: Readonly<Record<string, unknown>>[] = [];
1781
+ for (let index = 0; index < length; index++) {
1782
+ const row = Object.getOwnPropertyDescriptor(value, String(index))?.value;
1783
+ if (row === null || typeof row !== "object" || Array.isArray(row) || types.isProxy(row))
1784
+ return undefined;
1785
+ const keys = Reflect.ownKeys(row);
1786
+ if (keys.length !== aliases.length || keys.some(key => typeof key !== "string" || !aliases.includes(key)))
1787
+ return undefined;
1788
+ const copy: Record<string, unknown> = Object.create(null);
1789
+ for (const alias of aliases) {
1790
+ const descriptor = Object.getOwnPropertyDescriptor(row, alias);
1791
+ if (!descriptor || !("value" in descriptor))
1792
+ return undefined;
1793
+ copy[alias] = descriptor.value;
1794
+ }
1795
+ rows.push(Object.freeze(copy));
1796
+ }
1797
+ return Object.freeze(rows);
1798
+ }
1799
+ catch {
1800
+ return undefined;
1801
+ }
1802
+ }