@drzl/analyzer 1.21.1 → 1.21.3
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/dist/index.cjs +14 -0
- package/dist/index.d.cts +29 -6
- package/dist/index.d.ts +29 -6
- package/dist/index.js +14 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -48,6 +48,12 @@ function qualifiedTableName(table) {
|
|
|
48
48
|
function qualifiedForeignTable(fk) {
|
|
49
49
|
return fk.foreignSchema ? `${fk.foreignSchema}.${fk.foreignTable}` : fk.foreignTable;
|
|
50
50
|
}
|
|
51
|
+
function temporalTextFormat(entityKind, kind) {
|
|
52
|
+
const pg = entityKind.startsWith("Pg");
|
|
53
|
+
const mysql = entityKind.startsWith("MySql");
|
|
54
|
+
if (kind === "stamp") return pg || mysql ? "temporalText" : void 0;
|
|
55
|
+
return pg ? "temporalText" : void 0;
|
|
56
|
+
}
|
|
51
57
|
function renderSqlLiteral(v) {
|
|
52
58
|
if (v === null || v === void 0) return "NULL";
|
|
53
59
|
if (typeof v === "number" || typeof v === "bigint") return String(v);
|
|
@@ -221,6 +227,7 @@ function describeV1Column(column) {
|
|
|
221
227
|
case "date":
|
|
222
228
|
out.tsType = js === "string" ? "string" : "Date";
|
|
223
229
|
out.dbType = codec?.startsWith("timestamp") ? "TIMESTAMP" : "DATE";
|
|
230
|
+
if (out.tsType === "string") out.format = temporalTextFormat(entityKind, "stamp");
|
|
224
231
|
break;
|
|
225
232
|
case "timestamp":
|
|
226
233
|
// `datetime` is the same fact under MySQL's name for it, and it had no arm, so every column
|
|
@@ -235,14 +242,17 @@ function describeV1Column(column) {
|
|
|
235
242
|
case "datetime":
|
|
236
243
|
out.tsType = js === "string" ? "string" : "Date";
|
|
237
244
|
out.dbType = "TIMESTAMP";
|
|
245
|
+
if (out.tsType === "string") out.format = temporalTextFormat(entityKind, "stamp");
|
|
238
246
|
break;
|
|
239
247
|
case "time":
|
|
240
248
|
out.tsType = "string";
|
|
241
249
|
out.dbType = "TIME";
|
|
250
|
+
out.format = temporalTextFormat(entityKind, "time");
|
|
242
251
|
break;
|
|
243
252
|
case "interval":
|
|
244
253
|
out.tsType = "string";
|
|
245
254
|
out.dbType = "INTERVAL";
|
|
255
|
+
out.format = temporalTextFormat(entityKind, "interval");
|
|
246
256
|
break;
|
|
247
257
|
case "inet":
|
|
248
258
|
case "cidr":
|
|
@@ -719,6 +729,10 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
|
|
|
719
729
|
out.integer = true;
|
|
720
730
|
}
|
|
721
731
|
if (/^(Pg)?UUID$/i.test(ctor) || /Uuid$/i.test(ctor)) out.format = "uuid";
|
|
732
|
+
if (/^Pg(TimestampString|DateString|Time|Interval)$/.test(ctor)) out.format = "temporalText";
|
|
733
|
+
if (/^MySql(TimestampString|DateTimeString|DateString)$/.test(ctor)) {
|
|
734
|
+
out.format = "temporalText";
|
|
735
|
+
}
|
|
722
736
|
return out;
|
|
723
737
|
}
|
|
724
738
|
mapColumnType(column) {
|
package/dist/index.d.cts
CHANGED
|
@@ -156,11 +156,34 @@ interface Column {
|
|
|
156
156
|
* `declaredDecimalRange` reads both numbers now, the two are distinguishable, and each says what
|
|
157
157
|
* its own server does.
|
|
158
158
|
*
|
|
159
|
-
* Postgres and Gel. MySQL
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
159
|
+
* Postgres and Gel. MySQL is a `false` on every one of these, and the reason is worth writing
|
|
160
|
+
* down carefully, because the two client paths give different answers and only one of them is
|
|
161
|
+
* the path a driver takes.
|
|
162
|
+
*
|
|
163
|
+
* Measured on MySQL 8.4.11 in `STRICT_TRANS_TABLES`, through mysql2's `execute()`, which is the
|
|
164
|
+
* binary prepared path drizzle uses:
|
|
165
|
+
*
|
|
166
|
+
* float, double all three refused, `Out of range value`
|
|
167
|
+
* decimal(10,2) all three STORED AS 0.00, silently, `SHOW WARNINGS` empty
|
|
168
|
+
* int `NaN` stored as 0 silently; both infinities refused
|
|
169
|
+
* bigint `NaN` stored as the int64 minimum silently; both infinities refused
|
|
170
|
+
*
|
|
171
|
+
* A control rules out ordinary overflow as the explanation: a finite `1e308` into the same
|
|
172
|
+
* `decimal(10,2)` is refused. So on three of those five, the server takes the row and stores a
|
|
173
|
+
* number nobody sent. This comment used to say a decimal "refuses them outright", which is the
|
|
174
|
+
* *text* path's answer: through the `mysql` CLI the same value answers `Incorrect decimal value`.
|
|
175
|
+
* Both statements are true of their own path, and only one of them describes what a validator
|
|
176
|
+
* sits in front of.
|
|
177
|
+
*
|
|
178
|
+
* The flag stays `false` on all of them, so the emitted schemas refuse all three. That is
|
|
179
|
+
* deliberately not the "never be stricter than the server" rule the range work follows: the
|
|
180
|
+
* server is not accepting the value here, it is accepting the row and storing a different value,
|
|
181
|
+
* and a validator whose whole job is to say what the database will do with a write cannot call
|
|
182
|
+
* that acceptance. Nothing is lost either way, since every generator's plain number type already
|
|
183
|
+
* refuses the three.
|
|
184
|
+
*
|
|
185
|
+
* SQLite returns both infinities and silently turns `NaN` into NULL, which is real and is filed
|
|
186
|
+
* on its own: a column needs both halves of that answer or none.
|
|
164
187
|
*
|
|
165
188
|
* Gel joined on a measurement of its own rather than on being Postgres-backed: a live Gel 7.1
|
|
166
189
|
* stored `nan`, `inf` and `-inf` in both `std::float32` and `std::float64` and handed all three
|
|
@@ -185,7 +208,7 @@ interface Column {
|
|
|
185
208
|
* `'1_000'` included, and by MySQL as a decimal number it then rounds, so `'12.5'` is a row on
|
|
186
209
|
* one server and an error on the other.
|
|
187
210
|
*/
|
|
188
|
-
format?: 'uuid' | 'numeric' | 'pgBigint' | 'mysqlBigint';
|
|
211
|
+
format?: 'uuid' | 'numeric' | 'pgBigint' | 'mysqlBigint' | 'temporalText';
|
|
189
212
|
/**
|
|
190
213
|
* The column's default, when it is a literal a schema can reproduce.
|
|
191
214
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -156,11 +156,34 @@ interface Column {
|
|
|
156
156
|
* `declaredDecimalRange` reads both numbers now, the two are distinguishable, and each says what
|
|
157
157
|
* its own server does.
|
|
158
158
|
*
|
|
159
|
-
* Postgres and Gel. MySQL
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
159
|
+
* Postgres and Gel. MySQL is a `false` on every one of these, and the reason is worth writing
|
|
160
|
+
* down carefully, because the two client paths give different answers and only one of them is
|
|
161
|
+
* the path a driver takes.
|
|
162
|
+
*
|
|
163
|
+
* Measured on MySQL 8.4.11 in `STRICT_TRANS_TABLES`, through mysql2's `execute()`, which is the
|
|
164
|
+
* binary prepared path drizzle uses:
|
|
165
|
+
*
|
|
166
|
+
* float, double all three refused, `Out of range value`
|
|
167
|
+
* decimal(10,2) all three STORED AS 0.00, silently, `SHOW WARNINGS` empty
|
|
168
|
+
* int `NaN` stored as 0 silently; both infinities refused
|
|
169
|
+
* bigint `NaN` stored as the int64 minimum silently; both infinities refused
|
|
170
|
+
*
|
|
171
|
+
* A control rules out ordinary overflow as the explanation: a finite `1e308` into the same
|
|
172
|
+
* `decimal(10,2)` is refused. So on three of those five, the server takes the row and stores a
|
|
173
|
+
* number nobody sent. This comment used to say a decimal "refuses them outright", which is the
|
|
174
|
+
* *text* path's answer: through the `mysql` CLI the same value answers `Incorrect decimal value`.
|
|
175
|
+
* Both statements are true of their own path, and only one of them describes what a validator
|
|
176
|
+
* sits in front of.
|
|
177
|
+
*
|
|
178
|
+
* The flag stays `false` on all of them, so the emitted schemas refuse all three. That is
|
|
179
|
+
* deliberately not the "never be stricter than the server" rule the range work follows: the
|
|
180
|
+
* server is not accepting the value here, it is accepting the row and storing a different value,
|
|
181
|
+
* and a validator whose whole job is to say what the database will do with a write cannot call
|
|
182
|
+
* that acceptance. Nothing is lost either way, since every generator's plain number type already
|
|
183
|
+
* refuses the three.
|
|
184
|
+
*
|
|
185
|
+
* SQLite returns both infinities and silently turns `NaN` into NULL, which is real and is filed
|
|
186
|
+
* on its own: a column needs both halves of that answer or none.
|
|
164
187
|
*
|
|
165
188
|
* Gel joined on a measurement of its own rather than on being Postgres-backed: a live Gel 7.1
|
|
166
189
|
* stored `nan`, `inf` and `-inf` in both `std::float32` and `std::float64` and handed all three
|
|
@@ -185,7 +208,7 @@ interface Column {
|
|
|
185
208
|
* `'1_000'` included, and by MySQL as a decimal number it then rounds, so `'12.5'` is a row on
|
|
186
209
|
* one server and an error on the other.
|
|
187
210
|
*/
|
|
188
|
-
format?: 'uuid' | 'numeric' | 'pgBigint' | 'mysqlBigint';
|
|
211
|
+
format?: 'uuid' | 'numeric' | 'pgBigint' | 'mysqlBigint' | 'temporalText';
|
|
189
212
|
/**
|
|
190
213
|
* The column's default, when it is a literal a schema can reproduce.
|
|
191
214
|
*
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,12 @@ function qualifiedTableName(table) {
|
|
|
5
5
|
function qualifiedForeignTable(fk) {
|
|
6
6
|
return fk.foreignSchema ? `${fk.foreignSchema}.${fk.foreignTable}` : fk.foreignTable;
|
|
7
7
|
}
|
|
8
|
+
function temporalTextFormat(entityKind, kind) {
|
|
9
|
+
const pg = entityKind.startsWith("Pg");
|
|
10
|
+
const mysql = entityKind.startsWith("MySql");
|
|
11
|
+
if (kind === "stamp") return pg || mysql ? "temporalText" : void 0;
|
|
12
|
+
return pg ? "temporalText" : void 0;
|
|
13
|
+
}
|
|
8
14
|
function renderSqlLiteral(v) {
|
|
9
15
|
if (v === null || v === void 0) return "NULL";
|
|
10
16
|
if (typeof v === "number" || typeof v === "bigint") return String(v);
|
|
@@ -178,6 +184,7 @@ function describeV1Column(column) {
|
|
|
178
184
|
case "date":
|
|
179
185
|
out.tsType = js === "string" ? "string" : "Date";
|
|
180
186
|
out.dbType = codec?.startsWith("timestamp") ? "TIMESTAMP" : "DATE";
|
|
187
|
+
if (out.tsType === "string") out.format = temporalTextFormat(entityKind, "stamp");
|
|
181
188
|
break;
|
|
182
189
|
case "timestamp":
|
|
183
190
|
// `datetime` is the same fact under MySQL's name for it, and it had no arm, so every column
|
|
@@ -192,14 +199,17 @@ function describeV1Column(column) {
|
|
|
192
199
|
case "datetime":
|
|
193
200
|
out.tsType = js === "string" ? "string" : "Date";
|
|
194
201
|
out.dbType = "TIMESTAMP";
|
|
202
|
+
if (out.tsType === "string") out.format = temporalTextFormat(entityKind, "stamp");
|
|
195
203
|
break;
|
|
196
204
|
case "time":
|
|
197
205
|
out.tsType = "string";
|
|
198
206
|
out.dbType = "TIME";
|
|
207
|
+
out.format = temporalTextFormat(entityKind, "time");
|
|
199
208
|
break;
|
|
200
209
|
case "interval":
|
|
201
210
|
out.tsType = "string";
|
|
202
211
|
out.dbType = "INTERVAL";
|
|
212
|
+
out.format = temporalTextFormat(entityKind, "interval");
|
|
203
213
|
break;
|
|
204
214
|
case "inet":
|
|
205
215
|
case "cidr":
|
|
@@ -676,6 +686,10 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
|
|
|
676
686
|
out.integer = true;
|
|
677
687
|
}
|
|
678
688
|
if (/^(Pg)?UUID$/i.test(ctor) || /Uuid$/i.test(ctor)) out.format = "uuid";
|
|
689
|
+
if (/^Pg(TimestampString|DateString|Time|Interval)$/.test(ctor)) out.format = "temporalText";
|
|
690
|
+
if (/^MySql(TimestampString|DateTimeString|DateString)$/.test(ctor)) {
|
|
691
|
+
out.format = "temporalText";
|
|
692
|
+
}
|
|
679
693
|
return out;
|
|
680
694
|
}
|
|
681
695
|
mapColumnType(column) {
|