@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 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 refuses all three on a `float`/`double`, and on a `decimal` refuses
160
- * them outright rather than storing `0.00`: measured on MySQL 8.4.11 in `STRICT_TRANS_TABLES`,
161
- * all three answer `Incorrect decimal value`. SQLite returns both infinities and silently turns
162
- * `NaN` into NULL, which is real and is filed on its own: a column needs both halves of that
163
- * answer or none.
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 refuses all three on a `float`/`double`, and on a `decimal` refuses
160
- * them outright rather than storing `0.00`: measured on MySQL 8.4.11 in `STRICT_TRANS_TABLES`,
161
- * all three answer `Incorrect decimal value`. SQLite returns both infinities and silently turns
162
- * `NaN` into NULL, which is real and is filed on its own: a column needs both halves of that
163
- * answer or none.
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drzl/analyzer",
3
- "version": "1.21.1",
3
+ "version": "1.21.3",
4
4
  "private": false,
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",