ts-prorm-orm 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/CHANGELOG.md +1111 -0
  2. package/LICENSE +21 -0
  3. package/README.md +573 -0
  4. package/dist/audit/history-query.js +180 -0
  5. package/dist/audit/index.js +23 -0
  6. package/dist/audit/logger.js +236 -0
  7. package/dist/cache/cache-manager.js +84 -0
  8. package/dist/cache/index.js +16 -0
  9. package/dist/cache/redis-cluster-cache.js +557 -0
  10. package/dist/cli.js +2200 -0
  11. package/dist/compliance/audit-trail.js +68 -0
  12. package/dist/compliance/backup-verification.js +685 -0
  13. package/dist/compliance/breach-detector.js +505 -0
  14. package/dist/compliance/consent-record.js +227 -0
  15. package/dist/compliance/consent-versioning.js +331 -0
  16. package/dist/compliance/cross-border-log.js +530 -0
  17. package/dist/compliance/data-classifier.js +258 -0
  18. package/dist/compliance/data-lineage.js +565 -0
  19. package/dist/compliance/data-masker.js +303 -0
  20. package/dist/compliance/data-portability.js +265 -0
  21. package/dist/compliance/data-retention.js +195 -0
  22. package/dist/compliance/dsar-workflow.js +342 -0
  23. package/dist/compliance/field-encryption.js +223 -0
  24. package/dist/compliance/immutable-record.js +148 -0
  25. package/dist/compliance/index.js +260 -0
  26. package/dist/compliance/privacy-impact-assessment.js +364 -0
  27. package/dist/compliance/pseudonymization.js +269 -0
  28. package/dist/compliance/query-firewall.js +1182 -0
  29. package/dist/compliance/rate-limiter.js +580 -0
  30. package/dist/compliance/right-to-erasure.js +117 -0
  31. package/dist/compliance/row-level-security.js +246 -0
  32. package/dist/compliance/security-decorator.js +574 -0
  33. package/dist/compliance/security-monitor.js +525 -0
  34. package/dist/compliance/sensitive-data-discovery.js +476 -0
  35. package/dist/compliance/session-isolation.js +472 -0
  36. package/dist/compliance/tls-enforcer.js +108 -0
  37. package/dist/compliance/worm-storage.js +712 -0
  38. package/dist/connection-manager.js +198 -0
  39. package/dist/connection-pool.js +519 -0
  40. package/dist/decorators/audit.js +136 -0
  41. package/dist/decorators/belongs-to-many.js +115 -0
  42. package/dist/decorators/belongs-to.js +115 -0
  43. package/dist/decorators/check.js +435 -0
  44. package/dist/decorators/collate.js +329 -0
  45. package/dist/decorators/comment.js +205 -0
  46. package/dist/decorators/database-settings.js +236 -0
  47. package/dist/decorators/default.js +244 -0
  48. package/dist/decorators/encryption.js +235 -0
  49. package/dist/decorators/engine.js +97 -0
  50. package/dist/decorators/fk-constraints.js +594 -0
  51. package/dist/decorators/foreign-table.js +136 -0
  52. package/dist/decorators/generated.js +274 -0
  53. package/dist/decorators/has-many.js +127 -0
  54. package/dist/decorators/has-one.js +116 -0
  55. package/dist/decorators/hstore.js +129 -0
  56. package/dist/decorators/index.js +355 -0
  57. package/dist/decorators/json-column.js +83 -0
  58. package/dist/decorators/jsonb.js +101 -0
  59. package/dist/decorators/orm-decorators.js +425 -0
  60. package/dist/decorators/permissions.js +294 -0
  61. package/dist/decorators/procedure.js +210 -0
  62. package/dist/decorators/query-options.js +556 -0
  63. package/dist/decorators/range.js +167 -0
  64. package/dist/decorators/set-column.js +83 -0
  65. package/dist/decorators/spatial.js +114 -0
  66. package/dist/decorators/storage.js +580 -0
  67. package/dist/decorators/timezone.js +512 -0
  68. package/dist/decorators/trigger.js +90 -0
  69. package/dist/decorators/uuid.js +135 -0
  70. package/dist/decorators/view.js +258 -0
  71. package/dist/diagrams/chen-diagram.js +354 -0
  72. package/dist/diagrams/class-diagram.js +384 -0
  73. package/dist/diagrams/dependency-diagram.js +432 -0
  74. package/dist/diagrams/er-diagram.js +605 -0
  75. package/dist/diagrams/flow-diagram.js +394 -0
  76. package/dist/diagrams/gantt-diagram.js +411 -0
  77. package/dist/diagrams/index-diagram.js +353 -0
  78. package/dist/diagrams/index.js +184 -0
  79. package/dist/diagrams/migration-diagram.js +316 -0
  80. package/dist/diagrams/model-diagram.js +616 -0
  81. package/dist/diagrams/package-diagram.js +376 -0
  82. package/dist/diagrams/palette.js +85 -0
  83. package/dist/diagrams/relational-diagram.js +455 -0
  84. package/dist/diagrams/schemadoc-diagram.js +309 -0
  85. package/dist/diagrams/sequence-diagram.js +307 -0
  86. package/dist/diagrams/state-diagram.js +344 -0
  87. package/dist/diagrams/svg-dom.js +111 -0
  88. package/dist/diagrams/tree-diagram.js +250 -0
  89. package/dist/dialects/clickhouse/index.js +1742 -0
  90. package/dist/dialects/cockroachdb/index.js +4677 -0
  91. package/dist/dialects/cratedb/index.js +441 -0
  92. package/dist/dialects/databricks/index.js +517 -0
  93. package/dist/dialects/db2/index.js +2225 -0
  94. package/dist/dialects/dialect.js +720 -0
  95. package/dist/dialects/duckdb/index.js +2014 -0
  96. package/dist/dialects/exasol/index.js +357 -0
  97. package/dist/dialects/firebird/index.js +495 -0
  98. package/dist/dialects/greenplum/index.js +457 -0
  99. package/dist/dialects/hana/index.js +1741 -0
  100. package/dist/dialects/mariadb/index.js +3590 -0
  101. package/dist/dialects/mssql/index.js +2296 -0
  102. package/dist/dialects/mysql/index.js +4058 -0
  103. package/dist/dialects/oracle/index.js +2999 -0
  104. package/dist/dialects/postgres/index.js +5319 -0
  105. package/dist/dialects/query-stream-helper.js +152 -0
  106. package/dist/dialects/questdb/index.js +433 -0
  107. package/dist/dialects/redshift/index.js +2277 -0
  108. package/dist/dialects/singlestore/index.js +354 -0
  109. package/dist/dialects/snowflake/index.js +2082 -0
  110. package/dist/dialects/spanner/index.js +1768 -0
  111. package/dist/dialects/sqlite/index.js +3382 -0
  112. package/dist/dialects/tidb/index.js +377 -0
  113. package/dist/dialects/timescaledb/index.js +164 -0
  114. package/dist/dialects/trino/index.js +420 -0
  115. package/dist/dialects/turso/index.js +227 -0
  116. package/dist/dialects/vertica/index.js +317 -0
  117. package/dist/dialects/yugabytedb/index.js +424 -0
  118. package/dist/errors/index.js +472 -0
  119. package/dist/errors/utils.js +340 -0
  120. package/dist/errors.js +21 -0
  121. package/dist/extensions/catalog/cloud-warehouse-features.js +207 -0
  122. package/dist/extensions/catalog/mssql-features.js +147 -0
  123. package/dist/extensions/catalog/mysql-mariadb-plugins.js +229 -0
  124. package/dist/extensions/catalog/oracle-db2-features.js +196 -0
  125. package/dist/extensions/catalog/postgres-extensions.js +516 -0
  126. package/dist/extensions/index.js +71 -0
  127. package/dist/extensions/types.js +13 -0
  128. package/dist/foreign-data.js +173 -0
  129. package/dist/hooks/hooks-manager.js +350 -0
  130. package/dist/hooks/index.js +37 -0
  131. package/dist/index.js +463 -0
  132. package/dist/logging.js +335 -0
  133. package/dist/migrations/index.js +40 -0
  134. package/dist/migrations/migration.js +196 -0
  135. package/dist/migrations/migrator.js +411 -0
  136. package/dist/migrations/prormmigration.js +275 -0
  137. package/dist/migrations/query-interface.js +435 -0
  138. package/dist/migrations/seeder.js +353 -0
  139. package/dist/models/associations.js +852 -0
  140. package/dist/models/constraints.js +288 -0
  141. package/dist/models/data-types.js +2518 -0
  142. package/dist/models/decorators.js +445 -0
  143. package/dist/models/index.js +33 -0
  144. package/dist/models/indexes.js +531 -0
  145. package/dist/models/methods.js +382 -0
  146. package/dist/models/model-manager.js +103 -0
  147. package/dist/models/model.js +5349 -0
  148. package/dist/models/operators.js +67 -0
  149. package/dist/models/scopes.js +189 -0
  150. package/dist/models/typescript-types.js +26 -0
  151. package/dist/nosql/aerospike/index.js +205 -0
  152. package/dist/nosql/allegrograph/index.js +169 -0
  153. package/dist/nosql/arangodb/index.js +364 -0
  154. package/dist/nosql/azure-blob/index.js +206 -0
  155. package/dist/nosql/beanstalkd/index.js +231 -0
  156. package/dist/nosql/beequeue/index.js +210 -0
  157. package/dist/nosql/bigchaindb/index.js +195 -0
  158. package/dist/nosql/bigtable/index.js +224 -0
  159. package/dist/nosql/blazegraph/index.js +173 -0
  160. package/dist/nosql/bullmq/index.js +191 -0
  161. package/dist/nosql/cassandra/index.js +174 -0
  162. package/dist/nosql/chroma/index.js +190 -0
  163. package/dist/nosql/cloudflare-kv/index.js +220 -0
  164. package/dist/nosql/coherence/index.js +200 -0
  165. package/dist/nosql/cosmosdb/index.js +157 -0
  166. package/dist/nosql/couchbase/index.js +213 -0
  167. package/dist/nosql/dax/index.js +212 -0
  168. package/dist/nosql/deno-kv/index.js +206 -0
  169. package/dist/nosql/dgraph/index.js +171 -0
  170. package/dist/nosql/doris/index.js +169 -0
  171. package/dist/nosql/druid/index.js +162 -0
  172. package/dist/nosql/dynamodb/index.js +937 -0
  173. package/dist/nosql/elasticsearch/index.js +377 -0
  174. package/dist/nosql/etcd/index.js +502 -0
  175. package/dist/nosql/eventhubs/index.js +213 -0
  176. package/dist/nosql/eventstore/index.js +254 -0
  177. package/dist/nosql/faunadb/index.js +188 -0
  178. package/dist/nosql/firestore/index.js +177 -0
  179. package/dist/nosql/fluree/index.js +148 -0
  180. package/dist/nosql/fuseki/index.js +170 -0
  181. package/dist/nosql/gcs/index.js +172 -0
  182. package/dist/nosql/gearman/index.js +160 -0
  183. package/dist/nosql/geode/index.js +196 -0
  184. package/dist/nosql/graphdb/index.js +169 -0
  185. package/dist/nosql/graylog/index.js +188 -0
  186. package/dist/nosql/gridgain/index.js +171 -0
  187. package/dist/nosql/hazelcast/index.js +162 -0
  188. package/dist/nosql/hbase/index.js +230 -0
  189. package/dist/nosql/ignite/index.js +173 -0
  190. package/dist/nosql/immudb/index.js +184 -0
  191. package/dist/nosql/index.js +232 -0
  192. package/dist/nosql/infinispan/index.js +200 -0
  193. package/dist/nosql/influxdb/index.js +0 -0
  194. package/dist/nosql/kafka/index.js +234 -0
  195. package/dist/nosql/keyspaces/index.js +189 -0
  196. package/dist/nosql/kinesis/index.js +253 -0
  197. package/dist/nosql/leveldb/index.js +153 -0
  198. package/dist/nosql/lmdb/index.js +160 -0
  199. package/dist/nosql/loki/index.js +201 -0
  200. package/dist/nosql/marklogic/index.js +204 -0
  201. package/dist/nosql/materialize/index.js +145 -0
  202. package/dist/nosql/meilisearch/index.js +154 -0
  203. package/dist/nosql/memcached/index.js +223 -0
  204. package/dist/nosql/milvus/index.js +410 -0
  205. package/dist/nosql/minio/index.js +265 -0
  206. package/dist/nosql/momento/index.js +179 -0
  207. package/dist/nosql/mongodb/index.js +461 -0
  208. package/dist/nosql/nats/index.js +247 -0
  209. package/dist/nosql/nedb/index.js +164 -0
  210. package/dist/nosql/neo4j/index.js +450 -0
  211. package/dist/nosql/neptune/index.js +470 -0
  212. package/dist/nosql/nsq/index.js +200 -0
  213. package/dist/nosql/opensearch/index.js +186 -0
  214. package/dist/nosql/orientdb/index.js +175 -0
  215. package/dist/nosql/papertrail/index.js +200 -0
  216. package/dist/nosql/pinecone/index.js +0 -0
  217. package/dist/nosql/pinot/index.js +133 -0
  218. package/dist/nosql/pouchdb/index.js +172 -0
  219. package/dist/nosql/prometheus/index.js +174 -0
  220. package/dist/nosql/provendb/index.js +147 -0
  221. package/dist/nosql/pubsub/index.js +187 -0
  222. package/dist/nosql/pulsar/index.js +232 -0
  223. package/dist/nosql/qdrant/index.js +295 -0
  224. package/dist/nosql/qldb/index.js +192 -0
  225. package/dist/nosql/r2/index.js +281 -0
  226. package/dist/nosql/rabbitmq/index.js +237 -0
  227. package/dist/nosql/ravendb/index.js +175 -0
  228. package/dist/nosql/redis/index.js +607 -0
  229. package/dist/nosql/redpanda/index.js +237 -0
  230. package/dist/nosql/resque/index.js +203 -0
  231. package/dist/nosql/rethinkdb/index.js +232 -0
  232. package/dist/nosql/rocksdb/index.js +152 -0
  233. package/dist/nosql/rockset/index.js +126 -0
  234. package/dist/nosql/s3/index.js +298 -0
  235. package/dist/nosql/scylladb/index.js +178 -0
  236. package/dist/nosql/signoz/index.js +227 -0
  237. package/dist/nosql/sns/index.js +201 -0
  238. package/dist/nosql/solr/index.js +231 -0
  239. package/dist/nosql/splunk/index.js +227 -0
  240. package/dist/nosql/sqs/index.js +246 -0
  241. package/dist/nosql/stardog/index.js +169 -0
  242. package/dist/nosql/starrocks/index.js +170 -0
  243. package/dist/nosql/store.js +2 -0
  244. package/dist/nosql/sumologic/index.js +213 -0
  245. package/dist/nosql/surrealdb/index.js +179 -0
  246. package/dist/nosql/terminusdb/index.js +151 -0
  247. package/dist/nosql/tigergraph/index.js +469 -0
  248. package/dist/nosql/typesense/index.js +148 -0
  249. package/dist/nosql/unqlite/index.js +157 -0
  250. package/dist/nosql/upstash/index.js +167 -0
  251. package/dist/nosql/vercel-kv/index.js +166 -0
  252. package/dist/nosql/victoriametrics/index.js +213 -0
  253. package/dist/nosql/virtuoso/index.js +169 -0
  254. package/dist/nosql/weaviate/index.js +276 -0
  255. package/dist/operators/index.js +108 -0
  256. package/dist/operators.js +2690 -0
  257. package/dist/prisma-migrate/index.js +38 -0
  258. package/dist/prisma-migrate/migration-generator.js +125 -0
  259. package/dist/prisma-migrate/model-generator.js +172 -0
  260. package/dist/prisma-migrate/relations.js +100 -0
  261. package/dist/prisma-migrate/schema-parser.js +167 -0
  262. package/dist/prisma-migrate/type-mapper.js +40 -0
  263. package/dist/prorm.js +6832 -0
  264. package/dist/query-builders/cte-builder.js +80 -0
  265. package/dist/query-builders/functions/aggregate.js +390 -0
  266. package/dist/query-builders/functions/conditional.js +503 -0
  267. package/dist/query-builders/functions/datetime.js +695 -0
  268. package/dist/query-builders/functions/fulltext.js +439 -0
  269. package/dist/query-builders/functions/index.js +93 -0
  270. package/dist/query-builders/functions/json.js +427 -0
  271. package/dist/query-builders/functions/math.js +399 -0
  272. package/dist/query-builders/functions/string.js +518 -0
  273. package/dist/query-builders/functions/window.js +328 -0
  274. package/dist/query-builders/include-builder.js +323 -0
  275. package/dist/query-builders/index-expression-builder.js +242 -0
  276. package/dist/query-builders/index.js +161 -0
  277. package/dist/query-builders/insert-builder.js +164 -0
  278. package/dist/query-builders/model-helpers.js +38 -0
  279. package/dist/query-builders/order-limit-builder.js +239 -0
  280. package/dist/query-builders/sql-compiler.js +2040 -0
  281. package/dist/query-builders/subquery-builder.js +152 -0
  282. package/dist/query-builders/update-builder.js +182 -0
  283. package/dist/query-builders/view-builder.js +218 -0
  284. package/dist/query-builders/where-builder.js +1532 -0
  285. package/dist/query-interface.js +622 -0
  286. package/dist/query-optimizers/batch-optimizer.js +426 -0
  287. package/dist/query-optimizers/explain-plans.js +415 -0
  288. package/dist/query-optimizers/index.js +51 -0
  289. package/dist/query-optimizers/prepared-statement-cache.js +423 -0
  290. package/dist/query-optimizers/query-hints.js +438 -0
  291. package/dist/query-optimizers/query-optimizer.js +278 -0
  292. package/dist/query-optimizers/slow-query-logger.js +271 -0
  293. package/dist/replica-manager.js +507 -0
  294. package/dist/schema/index.js +15 -0
  295. package/dist/schema/migration-generator.js +374 -0
  296. package/dist/schema/schema-differ.js +549 -0
  297. package/dist/schema/types.js +6 -0
  298. package/dist/sql-constants.js +300 -0
  299. package/dist/sqlite-advanced.js +1047 -0
  300. package/dist/streams/index.js +12 -0
  301. package/dist/streams/transforms.js +178 -0
  302. package/dist/transaction.js +456 -0
  303. package/dist/types/index.js +180 -0
  304. package/dist/user-management.js +127 -0
  305. package/dist/utils/date.js +300 -0
  306. package/dist/utils/index.js +1079 -0
  307. package/dist/utils/string.js +161 -0
  308. package/dist/validators/index.js +19 -0
  309. package/dist/validators/validator.js +911 -0
  310. package/package.json +190 -0
@@ -0,0 +1,415 @@
1
+ "use strict";
2
+ /**
3
+ * Explain Query Plans
4
+ * Provides functionality to analyze and explain SQL query execution plans
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ExplainPlanGenerator = exports.ExplainFormat = void 0;
8
+ exports.createExplainPlanGenerator = createExplainPlanGenerator;
9
+ /**
10
+ * Explain output format options
11
+ */
12
+ var ExplainFormat;
13
+ (function (ExplainFormat) {
14
+ ExplainFormat["TEXT"] = "text";
15
+ ExplainFormat["JSON"] = "json";
16
+ ExplainFormat["XML"] = "xml";
17
+ ExplainFormat["YAML"] = "yaml";
18
+ ExplainFormat["TREE"] = "tree";
19
+ })(ExplainFormat || (exports.ExplainFormat = ExplainFormat = {}));
20
+ /**
21
+ * Explain plan generator for different database dialects
22
+ */
23
+ class ExplainPlanGenerator {
24
+ constructor(dialect, defaultOptions) {
25
+ this.dialect = dialect;
26
+ this.defaultOptions = {
27
+ format: ExplainFormat.TEXT,
28
+ analyze: false,
29
+ verbose: false,
30
+ ...defaultOptions,
31
+ };
32
+ }
33
+ /**
34
+ * Set default options for EXPLAIN queries
35
+ */
36
+ setDefaultOptions(options) {
37
+ this.defaultOptions = { ...this.defaultOptions, ...options };
38
+ }
39
+ /**
40
+ * Generate an explain plan for a SQL query
41
+ */
42
+ async explain(sql, options) {
43
+ const startTime = Date.now();
44
+ const mergedOptions = { ...this.defaultOptions, ...options };
45
+ // Build EXPLAIN statement based on dialect
46
+ const explainSql = this.buildExplainSql(sql, mergedOptions);
47
+ // Execute the explain query
48
+ const rawResults = await this.dialect.query(explainSql, { raw: true });
49
+ const duration = Date.now() - startTime;
50
+ // Parse the explain output
51
+ const parsedPlan = this.parseExplainOutput(rawResults, mergedOptions.format || ExplainFormat.TEXT);
52
+ return {
53
+ sql,
54
+ plan: rawResults,
55
+ rawResults,
56
+ duration,
57
+ dialect: this.dialect.name,
58
+ parsedPlan,
59
+ };
60
+ }
61
+ /**
62
+ * Build the appropriate EXPLAIN SQL statement for the dialect
63
+ */
64
+ buildExplainSql(sql, options) {
65
+ const dialectName = this.dialect.name.toLowerCase();
66
+ const format = options.format || ExplainFormat.TEXT;
67
+ switch (dialectName) {
68
+ case 'mysql':
69
+ case 'mariadb':
70
+ return this.buildMySQLExplain(sql, options);
71
+ case 'postgres':
72
+ case 'postgresql':
73
+ return this.buildPostgresExplain(sql, options);
74
+ case 'sqlite':
75
+ return this.buildSQLiteExplain(sql, options);
76
+ default:
77
+ return `EXPLAIN ${sql}`;
78
+ }
79
+ }
80
+ /**
81
+ * Build MySQL EXPLAIN statement
82
+ */
83
+ buildMySQLExplain(sql, options) {
84
+ let explain = 'EXPLAIN';
85
+ // Add options
86
+ if (options.analyze) {
87
+ explain += ' ANALYZE';
88
+ }
89
+ if (options.format === ExplainFormat.JSON) {
90
+ explain += ' FORMAT=JSON';
91
+ }
92
+ else if (options.format === ExplainFormat.TREE) {
93
+ explain += ' FORMAT=TREE';
94
+ }
95
+ // Add statement type if provided
96
+ if (options.type) {
97
+ explain += ` ${options.type}`;
98
+ }
99
+ return `${explain} ${sql}`;
100
+ }
101
+ /**
102
+ * Build PostgreSQL EXPLAIN statement
103
+ */
104
+ buildPostgresExplain(sql, options) {
105
+ let explain = 'EXPLAIN';
106
+ if (options.analyze) {
107
+ explain += ' ANALYZE';
108
+ }
109
+ if (options.buffers) {
110
+ explain += ' BUFFERS';
111
+ }
112
+ if (options.timing) {
113
+ explain += ' TIMING';
114
+ }
115
+ if (options.format === ExplainFormat.JSON) {
116
+ explain += ' (FORMAT JSON)';
117
+ }
118
+ else if (options.format === ExplainFormat.XML) {
119
+ explain += ' (FORMAT XML)';
120
+ }
121
+ else if (options.format === ExplainFormat.YAML) {
122
+ explain += ' (FORMAT YAML)';
123
+ }
124
+ return `${explain} ${sql}`;
125
+ }
126
+ /**
127
+ * Build SQLite EXPLAIN statement
128
+ */
129
+ buildSQLiteExplain(sql, _options) {
130
+ // SQLite has QUERY_PLAN and EXPLAIN
131
+ return `EXPLAIN QUERY PLAN ${sql}`;
132
+ }
133
+ /**
134
+ * Parse EXPLAIN output into structured format
135
+ */
136
+ parseExplainOutput(results, format) {
137
+ const rows = results.rows || [];
138
+ if (rows.length === 0) {
139
+ return [];
140
+ }
141
+ const dialectName = this.dialect.name.toLowerCase();
142
+ switch (dialectName) {
143
+ case 'mysql':
144
+ case 'mariadb':
145
+ return this.parseMySQLExplain(rows);
146
+ case 'postgres':
147
+ case 'postgresql':
148
+ return this.parsePostgresExplain(rows);
149
+ case 'sqlite':
150
+ return this.parseSQLiteExplain(rows);
151
+ default:
152
+ return this.parseGenericExplain(rows);
153
+ }
154
+ }
155
+ /**
156
+ * Parse MySQL EXPLAIN output
157
+ */
158
+ parseMySQLExplain(rows) {
159
+ return rows.map((row) => ({
160
+ operation: row.type || row.select_type || 'UNKNOWN',
161
+ table: row.table,
162
+ index: row.possible_keys,
163
+ rows: row.rows ? parseInt(String(row.rows), 10) : undefined,
164
+ cost: row.key_len ? parseInt(String(row.key_len), 10) : undefined,
165
+ details: {
166
+ selectId: row.id,
167
+ selectType: row.select_type,
168
+ key: row.key,
169
+ keyLength: row.key_len,
170
+ ref: row.ref,
171
+ extra: row.Extra,
172
+ },
173
+ }));
174
+ }
175
+ /**
176
+ * Parse PostgreSQL EXPLAIN output
177
+ */
178
+ parsePostgresExplain(rows) {
179
+ return rows.map((row) => {
180
+ // Check if it's a JSON format result
181
+ if (row.Plan) {
182
+ return this.parsePostgresPlanNode(row.Plan);
183
+ }
184
+ // Text format - parse the output
185
+ const planText = row['Query Plan'] || row.plan || row;
186
+ return {
187
+ operation: 'UNKNOWN',
188
+ details: { raw: planText },
189
+ };
190
+ });
191
+ }
192
+ /**
193
+ * Recursively parse PostgreSQL plan nodes
194
+ */
195
+ parsePostgresPlanNode(plan) {
196
+ const step = {
197
+ operation: plan.NodeType || 'OPERATION',
198
+ table: plan.RelationName,
199
+ index: plan.IndexName,
200
+ rows: plan.PlanRows ? parseInt(String(plan.PlanRows), 10) : undefined,
201
+ cost: plan.TotalCost ? parseFloat(String(plan.TotalCost)) : undefined,
202
+ details: {
203
+ startupCost: plan.StartupCost,
204
+ totalCost: plan.TotalCost,
205
+ planWidth: plan.PlanWidth,
206
+ actualStartupTime: plan.ActualStartupTime,
207
+ actualTotalTime: plan.ActualTotalTime,
208
+ actualRows: plan.ActualRows,
209
+ sharedHitBlocks: plan.SharedHitBlocks,
210
+ sharedReadBlocks: plan.SharedReadBlocks,
211
+ },
212
+ };
213
+ if (plan.Plans && plan.Plans.length > 0) {
214
+ step.children = plan.Plans.map((p) => this.parsePostgresPlanNode(p));
215
+ }
216
+ return step;
217
+ }
218
+ /**
219
+ * Parse SQLite EXPLAIN QUERY PLAN output
220
+ */
221
+ parseSQLiteExplain(rows) {
222
+ return rows.map((row) => {
223
+ // SQLite returns: id, order, from, detail
224
+ const detail = row.detail || row.DETAIL || '';
225
+ const operation = this.extractSQLiteOperation(detail);
226
+ const table = this.extractSQLiteTable(detail);
227
+ const index = this.extractSQLiteIndex(detail);
228
+ return {
229
+ operation,
230
+ table,
231
+ index,
232
+ details: { detail },
233
+ };
234
+ });
235
+ }
236
+ /**
237
+ * Extract operation type from SQLite detail
238
+ */
239
+ extractSQLiteOperation(detail) {
240
+ if (detail.includes('SCAN'))
241
+ return 'SCAN';
242
+ if (detail.includes('SEARCH'))
243
+ return 'SEARCH';
244
+ if (detail.includes('USING INDEX'))
245
+ return 'INDEX';
246
+ if (detail.includes('USING COVERING INDEX'))
247
+ return 'COVERING INDEX';
248
+ if (detail.includes('USING TEMP'))
249
+ return 'TEMP';
250
+ if (detail.includes('USING FILESORT'))
251
+ return 'FILESORT';
252
+ if (detail.includes('COMPOUND'))
253
+ return 'COMPOUND';
254
+ return 'OPERATION';
255
+ }
256
+ /**
257
+ * Extract table name from SQLite detail
258
+ */
259
+ extractSQLiteTable(detail) {
260
+ const match = detail.match(/(?:SCAN|SEARCH)\s+(\w+)/i);
261
+ return match ? match[1] : undefined;
262
+ }
263
+ /**
264
+ * Extract index name from SQLite detail
265
+ */
266
+ extractSQLiteIndex(detail) {
267
+ const match = detail.match(/USING\s+INDEX\s+(\w+)/i);
268
+ return match ? match[1] : undefined;
269
+ }
270
+ /**
271
+ * Generic explain output parser
272
+ */
273
+ parseGenericExplain(rows) {
274
+ return rows.map((row) => ({
275
+ operation: 'ROW',
276
+ details: { ...row },
277
+ }));
278
+ }
279
+ /**
280
+ * Analyze a query and provide optimization recommendations
281
+ */
282
+ async analyzeQuery(sql, options) {
283
+ const plan = await this.explain(sql, options);
284
+ const recommendations = this.generateRecommendations(plan);
285
+ return { plan, recommendations };
286
+ }
287
+ /**
288
+ * Generate optimization recommendations based on explain plan
289
+ */
290
+ generateRecommendations(plan) {
291
+ const recommendations = [];
292
+ const dialectName = plan.dialect.toLowerCase();
293
+ if (!plan.parsedPlan || plan.parsedPlan.length === 0) {
294
+ return recommendations;
295
+ }
296
+ switch (dialectName) {
297
+ case 'mysql':
298
+ case 'mariadb':
299
+ return this.generateMySQLRecommendations(plan.parsedPlan);
300
+ case 'postgres':
301
+ case 'postgresql':
302
+ return this.generatePostgresRecommendations(plan.parsedPlan);
303
+ case 'sqlite':
304
+ return this.generateSQLiteRecommendations(plan.parsedPlan);
305
+ default:
306
+ return recommendations;
307
+ }
308
+ }
309
+ /**
310
+ * Generate MySQL-specific recommendations
311
+ */
312
+ generateMySQLRecommendations(plan) {
313
+ const recommendations = [];
314
+ for (const step of plan) {
315
+ // Check for full table scans
316
+ if (step.operation === 'ALL' || step.details?.extra?.includes('Using where')) {
317
+ recommendations.push({
318
+ type: 'INDEX',
319
+ severity: 'HIGH',
320
+ message: 'Full table scan detected. Consider adding an index.',
321
+ table: step.table,
322
+ });
323
+ }
324
+ // Check for missing indexes on WHERE
325
+ if (step.details?.possible_keys === null && step.details?.key === null) {
326
+ recommendations.push({
327
+ type: 'INDEX',
328
+ severity: 'MEDIUM',
329
+ message: 'No suitable index found for query conditions.',
330
+ table: step.table,
331
+ });
332
+ }
333
+ // Check for filesort
334
+ if (step.details?.extra?.includes('Using filesort')) {
335
+ recommendations.push({
336
+ type: 'OPTIMIZATION',
337
+ severity: 'MEDIUM',
338
+ message: 'Filesort detected. Consider adding an index on the ORDER BY column.',
339
+ table: step.table,
340
+ });
341
+ }
342
+ // Check for temporary tables
343
+ if (step.details?.extra?.includes('Using temporary')) {
344
+ recommendations.push({
345
+ type: 'OPTIMIZATION',
346
+ severity: 'LOW',
347
+ message: 'Temporary table used. Query may benefit from optimization.',
348
+ table: step.table,
349
+ });
350
+ }
351
+ }
352
+ return recommendations;
353
+ }
354
+ /**
355
+ * Generate PostgreSQL-specific recommendations
356
+ */
357
+ generatePostgresRecommendations(plan) {
358
+ const recommendations = [];
359
+ const checkNode = (node) => {
360
+ // Check for sequential scans
361
+ if (node.operation === 'Seq Scan') {
362
+ recommendations.push({
363
+ type: 'INDEX',
364
+ severity: 'HIGH',
365
+ message: 'Sequential scan detected on table.',
366
+ table: node.table,
367
+ });
368
+ }
369
+ // Check for high row estimates
370
+ if (node.rows && node.rows > 10000) {
371
+ recommendations.push({
372
+ type: 'OPTIMIZATION',
373
+ severity: 'MEDIUM',
374
+ message: `High row estimate (${node.rows}). Consider using an index.`,
375
+ table: node.table,
376
+ });
377
+ }
378
+ // Check children
379
+ if (node.children) {
380
+ node.children.forEach(checkNode);
381
+ }
382
+ };
383
+ plan.forEach(checkNode);
384
+ return recommendations;
385
+ }
386
+ /**
387
+ * Generate SQLite-specific recommendations
388
+ */
389
+ generateSQLiteRecommendations(plan) {
390
+ const recommendations = [];
391
+ for (const step of plan) {
392
+ if (step.operation === 'SCAN') {
393
+ recommendations.push({
394
+ type: 'INDEX',
395
+ severity: 'HIGH',
396
+ message: 'Full table scan detected.',
397
+ table: step.table,
398
+ });
399
+ }
400
+ }
401
+ return recommendations;
402
+ }
403
+ }
404
+ exports.ExplainPlanGenerator = ExplainPlanGenerator;
405
+ /**
406
+ * Create an ExplainPlanGenerator instance
407
+ */
408
+ function createExplainPlanGenerator(dialect, options) {
409
+ return new ExplainPlanGenerator(dialect, options);
410
+ }
411
+ exports.default = {
412
+ ExplainPlanGenerator,
413
+ ExplainFormat,
414
+ createExplainPlanGenerator,
415
+ };
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ /**
3
+ * Query Optimizers Module
4
+ * Provides various query optimization features including:
5
+ * - Query hint support
6
+ * - Explain query plans
7
+ * - Slow query logging
8
+ * - Query batch/bulk optimization
9
+ * - Prepared statement caching
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.defaultOptimizerConfig = exports.createQueryOptimizer = exports.QueryOptimizer = exports.createPreparedStatementCache = exports.PreparedStatementCache = exports.optimizeBatchDelete = exports.optimizeBatchUpdate = exports.optimizeBatchInsert = exports.BatchQueryOptimizer = exports.createSlowQueryLogger = exports.SlowQueryLogger = exports.createExplainPlanGenerator = exports.ExplainFormat = exports.ExplainPlanGenerator = exports.NO_MERGE = exports.MERGE_HASH = exports.JOIN_FIXED_ORDER = exports.USE_INDEX = exports.FORCE_INDEX = exports.INDEX_HINT = exports.HintType = exports.QueryHintManager = void 0;
13
+ var query_hints_1 = require("./query-hints");
14
+ Object.defineProperty(exports, "QueryHintManager", { enumerable: true, get: function () { return query_hints_1.QueryHintManager; } });
15
+ Object.defineProperty(exports, "HintType", { enumerable: true, get: function () { return query_hints_1.HintType; } });
16
+ Object.defineProperty(exports, "INDEX_HINT", { enumerable: true, get: function () { return query_hints_1.INDEX_HINT; } });
17
+ Object.defineProperty(exports, "FORCE_INDEX", { enumerable: true, get: function () { return query_hints_1.FORCE_INDEX; } });
18
+ Object.defineProperty(exports, "USE_INDEX", { enumerable: true, get: function () { return query_hints_1.USE_INDEX; } });
19
+ Object.defineProperty(exports, "JOIN_FIXED_ORDER", { enumerable: true, get: function () { return query_hints_1.JOIN_FIXED_ORDER; } });
20
+ Object.defineProperty(exports, "MERGE_HASH", { enumerable: true, get: function () { return query_hints_1.MERGE_HASH; } });
21
+ Object.defineProperty(exports, "NO_MERGE", { enumerable: true, get: function () { return query_hints_1.NO_MERGE; } });
22
+ var explain_plans_1 = require("./explain-plans");
23
+ Object.defineProperty(exports, "ExplainPlanGenerator", { enumerable: true, get: function () { return explain_plans_1.ExplainPlanGenerator; } });
24
+ Object.defineProperty(exports, "ExplainFormat", { enumerable: true, get: function () { return explain_plans_1.ExplainFormat; } });
25
+ Object.defineProperty(exports, "createExplainPlanGenerator", { enumerable: true, get: function () { return explain_plans_1.createExplainPlanGenerator; } });
26
+ var slow_query_logger_1 = require("./slow-query-logger");
27
+ Object.defineProperty(exports, "SlowQueryLogger", { enumerable: true, get: function () { return slow_query_logger_1.SlowQueryLogger; } });
28
+ Object.defineProperty(exports, "createSlowQueryLogger", { enumerable: true, get: function () { return slow_query_logger_1.createSlowQueryLogger; } });
29
+ var batch_optimizer_1 = require("./batch-optimizer");
30
+ Object.defineProperty(exports, "BatchQueryOptimizer", { enumerable: true, get: function () { return batch_optimizer_1.BatchQueryOptimizer; } });
31
+ Object.defineProperty(exports, "optimizeBatchInsert", { enumerable: true, get: function () { return batch_optimizer_1.optimizeBatchInsert; } });
32
+ Object.defineProperty(exports, "optimizeBatchUpdate", { enumerable: true, get: function () { return batch_optimizer_1.optimizeBatchUpdate; } });
33
+ Object.defineProperty(exports, "optimizeBatchDelete", { enumerable: true, get: function () { return batch_optimizer_1.optimizeBatchDelete; } });
34
+ var prepared_statement_cache_1 = require("./prepared-statement-cache");
35
+ Object.defineProperty(exports, "PreparedStatementCache", { enumerable: true, get: function () { return prepared_statement_cache_1.PreparedStatementCache; } });
36
+ Object.defineProperty(exports, "createPreparedStatementCache", { enumerable: true, get: function () { return prepared_statement_cache_1.createPreparedStatementCache; } });
37
+ var query_optimizer_1 = require("./query-optimizer");
38
+ Object.defineProperty(exports, "QueryOptimizer", { enumerable: true, get: function () { return query_optimizer_1.QueryOptimizer; } });
39
+ Object.defineProperty(exports, "createQueryOptimizer", { enumerable: true, get: function () { return query_optimizer_1.createQueryOptimizer; } });
40
+ /**
41
+ * Default configuration for query optimizers
42
+ */
43
+ exports.defaultOptimizerConfig = {
44
+ slowQueryThreshold: 1000, // ms
45
+ preparedStatementCacheSize: 500,
46
+ batchInsertChunkSize: 1000,
47
+ batchUpdateChunkSize: 500,
48
+ batchDeleteChunkSize: 500,
49
+ enableExplainPlans: process.env.NODE_ENV === 'development',
50
+ enableQueryHints: true,
51
+ };