autotel-drizzle 0.0.50 → 0.0.52
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.
- package/README.md +86 -0
- package/dist/drizzle-BzeOQKBq.cjs +669 -0
- package/dist/drizzle-C3xQFzy2.js +526 -0
- package/dist/drizzle.cjs +1 -1
- package/dist/drizzle.d.cts +59 -27
- package/dist/drizzle.d.ts +59 -27
- package/dist/drizzle.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/dist/drizzle-C2xv1qdm.js +0 -268
- package/dist/drizzle-D46sVvOa.cjs +0 -411
package/README.md
CHANGED
|
@@ -109,6 +109,7 @@ await db.select().from(users).where(eq(users.id, 123));
|
|
|
109
109
|
maxQueryTextLength?: number // Max SQL length (default: 1000)
|
|
110
110
|
peerName?: string // Database host
|
|
111
111
|
peerPort?: number // Database port
|
|
112
|
+
explain?: 'plan' | 'analyze' | false // Capture the postgres query plan (default: false)
|
|
112
113
|
}
|
|
113
114
|
```
|
|
114
115
|
|
|
@@ -118,9 +119,94 @@ await db.select().from(users).where(eq(users.id, 123));
|
|
|
118
119
|
- `db.operation` - Operation name (SELECT, INSERT, UPDATE, DELETE)
|
|
119
120
|
- `db.name` - Database name
|
|
120
121
|
- `db.statement` - SQL query text (if `captureQueryText: true`)
|
|
122
|
+
- `db.statement.hash` - Stable hash of the statement, present even when the text is suppressed
|
|
121
123
|
- `net.peer.name` - Database host
|
|
122
124
|
- `net.peer.port` - Database port
|
|
123
125
|
|
|
126
|
+
## Drivers
|
|
127
|
+
|
|
128
|
+
Tested against postgres 16, mysql 8, and sqlite, driving each through drizzle's
|
|
129
|
+
own query builder, its relational API, and raw `db.execute`. Every driver below
|
|
130
|
+
emits one span per query, names the operation, and tags `db.collection.name`.
|
|
131
|
+
|
|
132
|
+
| Driver | Queries | Transaction span | Query plans |
|
|
133
|
+
| --- | --- | --- | --- |
|
|
134
|
+
| `node-postgres` | yes | yes | yes |
|
|
135
|
+
| `postgres.js` | yes | yes | yes |
|
|
136
|
+
| `pglite` | yes | yes | yes |
|
|
137
|
+
| `mysql2` | yes | yes | postgres only |
|
|
138
|
+
| `better-sqlite3` | yes | yes, synchronous | postgres only |
|
|
139
|
+
| `libsql` | yes | yes | postgres only |
|
|
140
|
+
|
|
141
|
+
Nothing about the instrumentation is dialect-specific except `explain`, which
|
|
142
|
+
sends postgres syntax and so turns itself off unless `dbSystem` is
|
|
143
|
+
`'postgresql'`. Table names are read from double-quoted, backtick-quoted, and
|
|
144
|
+
unquoted identifiers alike, so mysql groups by table the same way postgres does.
|
|
145
|
+
|
|
146
|
+
better-sqlite3 runs transactions synchronously and rejects a callback that
|
|
147
|
+
returns a promise. That is the driver's own rule and applies with or without
|
|
148
|
+
instrumentation; the wrapper keeps synchronous calls synchronous so those
|
|
149
|
+
transactions still commit.
|
|
150
|
+
|
|
151
|
+
## Query Plans
|
|
152
|
+
|
|
153
|
+
A span records what you asked postgres for. It does not record what postgres
|
|
154
|
+
did. Add an index and `db.statement` is unchanged, byte for byte, with the same
|
|
155
|
+
`db.statement.hash`; the duration moves and nothing on the span says why.
|
|
156
|
+
|
|
157
|
+
`explain` puts the planner's answer on the span:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
instrumentDrizzleClient(db, {
|
|
161
|
+
dbSystem: 'postgresql',
|
|
162
|
+
explain: 'analyze', // or 'plan' to plan without executing
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The same query, before and after `CREATE INDEX`:
|
|
167
|
+
|
|
168
|
+
| Attribute | Before | After |
|
|
169
|
+
| --- | --- | --- |
|
|
170
|
+
| `db.statement.hash` | `372269a8881e921a` | `372269a8881e921a` |
|
|
171
|
+
| `db.plan.hash` | `0b50591ce9f68f51` | `eb8765b8d1c4af5a` |
|
|
172
|
+
| `db.plan.node` | `Seq Scan` | `Bitmap Heap Scan` |
|
|
173
|
+
| `db.plan.indexes` | | `idx_comments_post_id` |
|
|
174
|
+
| `db.plan.seq_scan` | `true` | `false` |
|
|
175
|
+
| `db.plan.rows_examined` | `200199` | `1001` |
|
|
176
|
+
| `db.plan.rows_returned` | `1001` | `1001` |
|
|
177
|
+
| `db.plan.blocks` | `1861` | `1005` |
|
|
178
|
+
| `db.plan.cost` | | planner's total cost estimate |
|
|
179
|
+
| `db.plan.rows_estimated` | | rows the planner expected |
|
|
180
|
+
| `db.plan.execution_ms` | | measured time (`'analyze'` only) |
|
|
181
|
+
|
|
182
|
+
An unchanged statement hash beside a changed plan hash is a planner decision.
|
|
183
|
+
Grouping `db.plan.indexes` by `db.statement.hash` answers which queries an index
|
|
184
|
+
is serving.
|
|
185
|
+
|
|
186
|
+
`rows_examined` counts at the leaves of the plan, and counts the rows a scan
|
|
187
|
+
read and discarded. A parent node reports the rows its children handed up, so
|
|
188
|
+
summing every level counts one row per level; and the rows an index saves you
|
|
189
|
+
from reading never appear in the rows the query returns. `blocks` counts cached
|
|
190
|
+
and disk reads together, because a scan that walks a table already in memory
|
|
191
|
+
still walked the table.
|
|
192
|
+
|
|
193
|
+
### Cost and safety
|
|
194
|
+
|
|
195
|
+
Both modes add a round trip per query, and `'analyze'` executes the statement a
|
|
196
|
+
second time to measure it. Both are off by default. Use them in development, in
|
|
197
|
+
CI, or behind a sample of production traffic.
|
|
198
|
+
|
|
199
|
+
- `'analyze'` runs on read-only statements only, so a traced insert never runs
|
|
200
|
+
twice. A leading `WITH` qualifies only when no writing keyword appears
|
|
201
|
+
anywhere in the statement, because `WITH gone AS (DELETE ... RETURNING *)
|
|
202
|
+
SELECT` opens exactly like a read.
|
|
203
|
+
- The plan is collected before the span opens, so the extra round trip stays out
|
|
204
|
+
of the duration the span reports.
|
|
205
|
+
- A failed `EXPLAIN` is swallowed. The query still runs and still gets its span.
|
|
206
|
+
- Ignored unless `dbSystem` is `'postgresql'`.
|
|
207
|
+
- Inside a transaction the plan is taken on the transaction's own connection, so
|
|
208
|
+
it sees the rows the query will see.
|
|
209
|
+
|
|
124
210
|
## Security Considerations
|
|
125
211
|
|
|
126
212
|
### Query Text Capture
|