sqlite-hub 0.12.0 → 0.17.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 (64) hide show
  1. package/README.md +118 -23
  2. package/bin/sqlite-hub.js +1041 -224
  3. package/frontend/index.html +1 -0
  4. package/frontend/js/api.js +32 -2
  5. package/frontend/js/app.js +989 -13
  6. package/frontend/js/components/modal.js +644 -15
  7. package/frontend/js/components/pageHeader.js +14 -16
  8. package/frontend/js/components/queryEditor.js +9 -1
  9. package/frontend/js/components/queryHistoryPanel.js +126 -131
  10. package/frontend/js/components/queryResults.js +79 -17
  11. package/frontend/js/components/rowEditorPanel.js +204 -10
  12. package/frontend/js/components/sidebar.js +102 -18
  13. package/frontend/js/components/tableDesignerEditor.js +69 -11
  14. package/frontend/js/router.js +8 -0
  15. package/frontend/js/store.js +868 -9
  16. package/frontend/js/utils/copyColumnExport.js +117 -0
  17. package/frontend/js/utils/exportFilenames.js +32 -0
  18. package/frontend/js/utils/filePathPreview.js +315 -0
  19. package/frontend/js/utils/format.js +1 -1
  20. package/frontend/js/utils/markdownDocuments.js +248 -0
  21. package/frontend/js/utils/rowEditorJson.js +65 -0
  22. package/frontend/js/utils/sqlFormatter.js +691 -0
  23. package/frontend/js/utils/tableDesigner.js +178 -6
  24. package/frontend/js/utils/textCellStats.js +20 -0
  25. package/frontend/js/utils/timestampPreview.js +264 -0
  26. package/frontend/js/views/charts.js +3 -1
  27. package/frontend/js/views/data.js +34 -2
  28. package/frontend/js/views/documents.js +300 -0
  29. package/frontend/js/views/editor.js +48 -1
  30. package/frontend/js/views/settings.js +39 -6
  31. package/frontend/js/views/structure.js +154 -212
  32. package/frontend/styles/base.css +6 -0
  33. package/frontend/styles/components.css +476 -2
  34. package/frontend/styles/structure-graph.css +0 -3
  35. package/frontend/styles/tailwind.generated.css +1 -1
  36. package/frontend/styles/tokens.css +1 -1
  37. package/frontend/styles/views.css +422 -0
  38. package/package.json +3 -3
  39. package/server/routes/documents.js +163 -0
  40. package/server/routes/settings.js +22 -6
  41. package/server/server.js +6 -0
  42. package/server/services/sqlite/introspection.js +10 -0
  43. package/server/services/sqlite/sqlExecutor.js +29 -0
  44. package/server/services/sqlite/tableDesigner/changeAnalysis.js +25 -1
  45. package/server/services/sqlite/tableDesigner/schemaMapping.js +105 -10
  46. package/server/services/sqlite/tableDesigner/validation.js +60 -2
  47. package/server/services/sqlite/tableDesignerService.js +1 -1
  48. package/server/services/storage/appStateStore.js +313 -0
  49. package/tests/check-constraint-options.test.js +14 -0
  50. package/tests/cli-args.test.js +100 -0
  51. package/tests/copy-column-modal.test.js +83 -0
  52. package/tests/database-documents.test.js +85 -0
  53. package/tests/export-filenames.test.js +34 -0
  54. package/tests/file-path-preview.test.js +165 -0
  55. package/tests/markdown-documents.test.js +79 -0
  56. package/tests/row-editor-json.test.js +82 -0
  57. package/tests/row-editor-timestamp-preview.test.js +192 -0
  58. package/tests/settings-metadata.test.js +16 -0
  59. package/tests/settings-view.test.js +32 -0
  60. package/tests/sql-formatter.test.js +173 -0
  61. package/tests/sql-highlight.test.js +38 -0
  62. package/tests/table-designer-v2-unique-constraints.test.js +78 -0
  63. package/tests/text-cell-stats.test.js +38 -0
  64. package/fill.js +0 -526
@@ -345,12 +345,20 @@ function getTableDetail(db, tableName, options = {}) {
345
345
  const foreignKeys = groupForeignKeys(
346
346
  db.prepare(`PRAGMA foreign_key_list(${quoteIdentifier(tableName)})`).all()
347
347
  );
348
+ const checkConstraints = extractCheckExpressions(entry.sql).map((expression, index) => ({
349
+ id: index,
350
+ expression: expression.trim(),
351
+ }));
348
352
 
349
353
  const indexList = db
350
354
  .prepare(`PRAGMA index_list(${quoteIdentifier(tableName)})`)
351
355
  .all()
352
356
  .map((indexEntry) => {
353
357
  let indexColumns = [];
358
+ const indexSql =
359
+ db
360
+ .prepare("SELECT sql FROM sqlite_master WHERE type = 'index' AND name = ?")
361
+ .get(indexEntry.name)?.sql ?? null;
354
362
 
355
363
  try {
356
364
  indexColumns = db
@@ -380,6 +388,7 @@ function getTableDetail(db, tableName, options = {}) {
380
388
  unique: Boolean(indexEntry.unique),
381
389
  origin: indexEntry.origin,
382
390
  partial: Boolean(indexEntry.partial),
391
+ sql: indexSql,
383
392
  columns: indexColumns,
384
393
  };
385
394
  });
@@ -402,6 +411,7 @@ function getTableDetail(db, tableName, options = {}) {
402
411
  withoutRowId,
403
412
  strict: Boolean(tableListEntry?.strict),
404
413
  columns,
414
+ checkConstraints,
405
415
  foreignKeys,
406
416
  indexes: indexList,
407
417
  indexCount: indexList.length,
@@ -204,6 +204,13 @@ function mapEditableColumns(tableDetail, columnDefinitions) {
204
204
  const tableColumnsByName = new Map(
205
205
  tableDetail.columns.map((column) => [column.name, column])
206
206
  );
207
+ const foreignKeyColumnNames = new Set(
208
+ (tableDetail.foreignKeys ?? []).flatMap((foreignKey) =>
209
+ (foreignKey.mappings ?? [])
210
+ .map((mapping) => String(mapping.from ?? "").trim())
211
+ .filter(Boolean)
212
+ )
213
+ );
207
214
  const identityColumns = new Set(
208
215
  tableDetail.identityStrategy?.type === "primaryKey"
209
216
  ? tableDetail.identityStrategy.columns ?? []
@@ -223,12 +230,31 @@ function mapEditableColumns(tableDetail, columnDefinitions) {
223
230
  visible: isRowId ? true : Boolean(columnMeta?.visible),
224
231
  generated: Boolean(columnMeta?.generated),
225
232
  identity: identityColumns.has(definition.column),
233
+ declaredType: columnMeta?.declaredType ?? "",
234
+ affinity: columnMeta?.affinity ?? "",
235
+ primaryKeyPosition: Number(columnMeta?.primaryKeyPosition ?? 0),
236
+ foreignKey: foreignKeyColumnNames.has(definition.column),
226
237
  notNull: Boolean(columnMeta?.notNull),
227
238
  allowedValues: columnMeta?.allowedValues ?? [],
228
239
  };
229
240
  });
230
241
  }
231
242
 
243
+ function buildTableMeta(tableDetail) {
244
+ return {
245
+ columns: (tableDetail.columns ?? []).map((column) => ({
246
+ name: column.name,
247
+ declaredType: column.declaredType,
248
+ affinity: column.affinity,
249
+ primaryKeyPosition: Number(column.primaryKeyPosition ?? 0),
250
+ foreignKey: (tableDetail.foreignKeys ?? []).some((foreignKey) =>
251
+ (foreignKey.mappings ?? []).some((mapping) => mapping.from === column.name)
252
+ ),
253
+ })),
254
+ foreignKeys: tableDetail.foreignKeys ?? [],
255
+ };
256
+ }
257
+
232
258
  function hasRequiredIdentityColumns(tableDetail, editableColumns) {
233
259
  const availableSourceColumns = new Set(editableColumns.map((column) => column.sourceColumn));
234
260
 
@@ -301,6 +327,7 @@ function resolveEditableResult(db, columnDefinitions, serializedRows) {
301
327
  reason: getEditableResultReason(tableDetail),
302
328
  columns: editableColumns,
303
329
  identityStrategy: tableDetail.identityStrategy,
330
+ tableMeta: buildTableMeta(tableDetail),
304
331
  };
305
332
  }
306
333
 
@@ -319,6 +346,7 @@ function resolveEditableResult(db, columnDefinitions, serializedRows) {
319
346
  reason: "",
320
347
  columns: editableColumns,
321
348
  identityStrategy: tableDetail.identityStrategy,
349
+ tableMeta: buildTableMeta(tableDetail),
322
350
  rows,
323
351
  };
324
352
  }
@@ -378,6 +406,7 @@ class SqlExecutor {
378
406
  reason: editableResult.reason ?? "",
379
407
  columns: editableResult.columns ?? [],
380
408
  identityStrategy: editableResult.identityStrategy ?? null,
409
+ tableMeta: editableResult.tableMeta ?? null,
381
410
  }
382
411
  : null,
383
412
  };
@@ -26,6 +26,17 @@ function hasColumnChanged(originalColumn, draftColumn) {
26
26
  );
27
27
  }
28
28
 
29
+ function hasConstraintChanged(constraint) {
30
+ return (
31
+ normalizeComparableValue(constraint.name) !==
32
+ normalizeComparableValue(constraint.originalName ?? constraint.name) ||
33
+ normalizeComparableValue(constraint.expression || constraint.sql) !==
34
+ normalizeComparableValue(
35
+ constraint.originalExpression ?? constraint.originalSql ?? constraint.expression ?? constraint.sql
36
+ )
37
+ );
38
+ }
39
+
29
40
  function hasMeaningfulNewDraftContent(draft) {
30
41
  return (
31
42
  Boolean(String(draft.tableName ?? "").trim()) ||
@@ -149,7 +160,7 @@ function analyzeEditDraft(draft, originalDraft) {
149
160
  warnings.push(
150
161
  buildRiskyChangeWarning(
151
162
  "Column Rename Requires Rebuild",
152
- `Renaming column ${originalColumn.name} to ${column.name} is intentionally blocked in Table Designer v1.`
163
+ `Renaming column ${originalColumn.name} to ${column.name} is intentionally blocked in Table Designer v2.`
153
164
  )
154
165
  );
155
166
  }
@@ -265,6 +276,19 @@ function analyzeEditDraft(draft, originalDraft) {
265
276
  );
266
277
  });
267
278
 
279
+ [...(draft.uniqueConstraints ?? []), ...(draft.checkConstraints ?? [])].forEach((constraint) => {
280
+ if (!hasConstraintChanged(constraint)) {
281
+ return;
282
+ }
283
+
284
+ warnings.push(
285
+ buildRiskyChangeWarning(
286
+ "Constraint Change Requires Rebuild",
287
+ `Changing ${constraint.originalName || constraint.name || "a table constraint"} requires a SQLite table rebuild.`
288
+ )
289
+ );
290
+ });
291
+
268
292
  const dirty = Boolean(executableStatements.length || warnings.length);
269
293
 
270
294
  return {
@@ -74,6 +74,95 @@ function buildSimpleForeignKeyMap(foreignKeys = []) {
74
74
  return map;
75
75
  }
76
76
 
77
+ function buildUniqueConstraintExpression(index = {}) {
78
+ const columns = (index.columns ?? [])
79
+ .map((column) => column?.name)
80
+ .filter(Boolean);
81
+
82
+ if (!columns.length) {
83
+ return "UNIQUE constraint";
84
+ }
85
+
86
+ return `UNIQUE (${columns.map((columnName) => quoteIdentifier(columnName)).join(", ")})`;
87
+ }
88
+
89
+ function mapComplexUniqueConstraint(index = {}) {
90
+ const sql = String(index.sql ?? "").trim();
91
+ const columns = (index.columns ?? [])
92
+ .map((column) => ({
93
+ name: column.name ?? "",
94
+ descending: Boolean(column.descending),
95
+ collation: column.collation ?? "",
96
+ }))
97
+ .filter((column) => column.name);
98
+
99
+ return {
100
+ id: `unique:${index.name}`,
101
+ name: index.name ?? "",
102
+ originalName: index.name ?? "",
103
+ columns,
104
+ partial: Boolean(index.partial),
105
+ origin: index.origin ?? "",
106
+ sql,
107
+ originalSql: sql,
108
+ expression: sql || buildUniqueConstraintExpression(index),
109
+ originalExpression: sql || buildUniqueConstraintExpression(index),
110
+ editable: true,
111
+ preserved: true,
112
+ };
113
+ }
114
+
115
+ function buildComplexUniqueConstraints(indexes = []) {
116
+ return indexes
117
+ .filter((index) => index?.unique && (index.partial || (index.columns?.length ?? 0) !== 1))
118
+ .map(mapComplexUniqueConstraint);
119
+ }
120
+
121
+ function expressionMentionsColumn(expression = "", columnName = "") {
122
+ const normalizedExpression = String(expression ?? "").toLowerCase();
123
+ const normalizedColumn = String(columnName ?? "").toLowerCase();
124
+
125
+ if (!normalizedColumn) {
126
+ return false;
127
+ }
128
+
129
+ return (
130
+ new RegExp(`(^|[^a-z0-9_$])${normalizedColumn.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}([^a-z0-9_$]|$)`).test(
131
+ normalizedExpression
132
+ ) ||
133
+ normalizedExpression.includes(`"${normalizedColumn.replaceAll('"', '""')}"`) ||
134
+ normalizedExpression.includes(`\`${normalizedColumn.replaceAll("`", "``")}\``) ||
135
+ normalizedExpression.includes(`[${normalizedColumn}]`)
136
+ );
137
+ }
138
+
139
+ function buildCheckConstraints(tableDetail) {
140
+ const visibleColumns = (tableDetail.columns ?? []).filter(
141
+ (column) => column.visible !== false && !column.generated
142
+ );
143
+
144
+ return (tableDetail.checkConstraints ?? []).map((constraint, index) => {
145
+ const expression = String(constraint.expression ?? "").trim();
146
+ const columns = visibleColumns
147
+ .filter((column) => expressionMentionsColumn(expression, column.name))
148
+ .map((column) => ({
149
+ name: column.name,
150
+ allowedValues: Array.isArray(column.allowedValues) ? column.allowedValues : [],
151
+ }));
152
+
153
+ return {
154
+ id: `check:${constraint.id ?? index}`,
155
+ name: `CHECK ${index + 1}`,
156
+ originalName: `CHECK ${index + 1}`,
157
+ columns,
158
+ expression: expression ? `CHECK (${expression})` : "CHECK constraint",
159
+ originalExpression: expression ? `CHECK (${expression})` : "CHECK constraint",
160
+ editable: true,
161
+ preserved: true,
162
+ };
163
+ });
164
+ }
165
+
77
166
  function buildSchemaWarnings(tableDetail) {
78
167
  const warnings = [];
79
168
  const generatedColumns = (tableDetail.columns ?? []).filter((column) => column.generated);
@@ -83,9 +172,7 @@ function buildSchemaWarnings(tableDetail) {
83
172
  const complexForeignKeys = (tableDetail.foreignKeys ?? []).filter(
84
173
  (foreignKey) => (foreignKey.mappings?.length ?? 0) !== 1
85
174
  );
86
- const complexUniqueIndexes = (tableDetail.indexes ?? []).filter(
87
- (index) => index.unique && (index.partial || (index.columns?.length ?? 0) !== 1)
88
- );
175
+ const complexUniqueConstraints = buildComplexUniqueConstraints(tableDetail.indexes);
89
176
 
90
177
  if (generatedColumns.length) {
91
178
  warnings.push(
@@ -93,7 +180,7 @@ function buildSchemaWarnings(tableDetail) {
93
180
  code: "GENERATED_COLUMNS_PRESENT",
94
181
  title: "Generated Columns Detected",
95
182
  message:
96
- "Generated or hidden columns are not editable in Table Designer v1. Safe operations like table rename or adding simple columns still work.",
183
+ "Generated or hidden columns are inspectable but not editable in Table Designer v2. Safe operations like table rename or adding simple columns still work.",
97
184
  })
98
185
  );
99
186
  }
@@ -104,7 +191,7 @@ function buildSchemaWarnings(tableDetail) {
104
191
  code: "COMPOSITE_PRIMARY_KEY_PRESENT",
105
192
  title: "Composite Primary Key Detected",
106
193
  message:
107
- "This table uses more than one primary key column. Table Designer v1 preserves it, but changing primary key structure requires a manual table rebuild.",
194
+ "This table uses more than one primary key column. Table Designer v2 preserves it, but changing primary key structure requires a manual table rebuild.",
108
195
  })
109
196
  );
110
197
  }
@@ -115,18 +202,19 @@ function buildSchemaWarnings(tableDetail) {
115
202
  code: "COMPLEX_FOREIGN_KEYS_PRESENT",
116
203
  title: "Complex Foreign Keys Detected",
117
204
  message:
118
- "Composite or multi-mapping foreign keys cannot be edited directly in Table Designer v1. They are preserved until a rebuild is done manually.",
205
+ "Composite or multi-mapping foreign keys cannot be edited directly in Table Designer v2. They are preserved until a rebuild is done manually.",
119
206
  })
120
207
  );
121
208
  }
122
209
 
123
- if (complexUniqueIndexes.length) {
210
+ if (complexUniqueConstraints.length) {
124
211
  warnings.push(
125
212
  createDesignerWarning({
126
213
  code: "COMPLEX_UNIQUE_CONSTRAINTS_PRESENT",
127
- title: "Complex Unique Constraints Detected",
214
+ title: "Table Designer v2 Unique Constraints",
128
215
  message:
129
- "Multi-column or partial UNIQUE constraints are outside Table Designer v1. They remain untouched unless you rebuild the table manually.",
216
+ "Multi-column and partial UNIQUE constraints are detected, shown in the v2 constraints panel, and preserved by SQLite-safe saves. Editing them still requires manual SQL review.",
217
+ tone: "muted",
130
218
  })
131
219
  );
132
220
  }
@@ -149,7 +237,7 @@ function buildSchemaWarnings(tableDetail) {
149
237
  code: "WITHOUT_ROWID_PRESENT",
150
238
  title: "WITHOUT ROWID Table",
151
239
  message:
152
- "WITHOUT ROWID tables can be inspected here, but rebuild-style changes are intentionally blocked in v1.",
240
+ "WITHOUT ROWID tables can be inspected here, but rebuild-style changes are intentionally blocked in v2.",
153
241
  tone: "muted",
154
242
  })
155
243
  );
@@ -189,6 +277,8 @@ function mapTableColumnToDraft(column, { uniqueColumns, foreignKeyMap }) {
189
277
  function buildTableDesignerDraft(tableDetail) {
190
278
  const uniqueColumns = buildSingleColumnUniqueSet(tableDetail.indexes);
191
279
  const foreignKeyMap = buildSimpleForeignKeyMap(tableDetail.foreignKeys);
280
+ const uniqueConstraints = buildComplexUniqueConstraints(tableDetail.indexes);
281
+ const checkConstraints = buildCheckConstraints(tableDetail);
192
282
  const columns = (tableDetail.columns ?? [])
193
283
  .filter((column) => column.visible !== false && !column.generated)
194
284
  .map((column) => mapTableColumnToDraft(column, { uniqueColumns, foreignKeyMap }));
@@ -199,6 +289,9 @@ function buildTableDesignerDraft(tableDetail) {
199
289
  originalTableName: tableDetail.name,
200
290
  tableName: tableDetail.name,
201
291
  columns,
292
+ uniqueConstraints,
293
+ checkConstraints,
294
+ designerVersion: 2,
202
295
  dirty: false,
203
296
  schemaWarnings,
204
297
  warnings: [...schemaWarnings],
@@ -227,6 +320,8 @@ function listDesignerTables(db) {
227
320
  module.exports = {
228
321
  SUPPORTED_TABLE_DESIGNER_TYPES,
229
322
  buildTableDesignerDraft,
323
+ buildComplexUniqueConstraints,
324
+ buildCheckConstraints,
230
325
  createDesignerWarning,
231
326
  listDesignerTables,
232
327
  normalizeDesignerType,
@@ -66,6 +66,53 @@ function normalizeColumnPayload(column = {}, index = 0) {
66
66
  };
67
67
  }
68
68
 
69
+ function normalizeUniqueConstraintPayload(constraint = {}, index = 0) {
70
+ return {
71
+ id: String(constraint.id ?? `unique:${index}`),
72
+ name: String(constraint.name ?? "").trim(),
73
+ originalName: String(constraint.originalName ?? constraint.name ?? "").trim(),
74
+ columns: Array.isArray(constraint.columns)
75
+ ? constraint.columns
76
+ .map((column) => ({
77
+ name: String(column?.name ?? "").trim(),
78
+ descending: normalizeBoolean(column?.descending),
79
+ collation: String(column?.collation ?? "").trim(),
80
+ }))
81
+ .filter((column) => column.name)
82
+ : [],
83
+ partial: normalizeBoolean(constraint.partial),
84
+ origin: String(constraint.origin ?? "").trim(),
85
+ sql: String(constraint.sql ?? "").trim(),
86
+ originalSql: String(constraint.originalSql ?? constraint.sql ?? "").trim(),
87
+ expression: String(constraint.expression ?? "").trim(),
88
+ originalExpression: String(constraint.originalExpression ?? constraint.expression ?? constraint.sql ?? "").trim(),
89
+ editable: normalizeBoolean(constraint.editable),
90
+ preserved: constraint.preserved === undefined ? true : normalizeBoolean(constraint.preserved),
91
+ };
92
+ }
93
+
94
+ function normalizeCheckConstraintPayload(constraint = {}, index = 0) {
95
+ return {
96
+ id: String(constraint.id ?? `check:${index}`),
97
+ name: String(constraint.name ?? `CHECK ${index + 1}`).trim(),
98
+ originalName: String(constraint.originalName ?? constraint.name ?? `CHECK ${index + 1}`).trim(),
99
+ columns: Array.isArray(constraint.columns)
100
+ ? constraint.columns
101
+ .map((column) => ({
102
+ name: String(column?.name ?? "").trim(),
103
+ allowedValues: Array.isArray(column?.allowedValues)
104
+ ? column.allowedValues.map((value) => String(value ?? ""))
105
+ : [],
106
+ }))
107
+ .filter((column) => column.name)
108
+ : [],
109
+ expression: String(constraint.expression ?? "").trim(),
110
+ originalExpression: String(constraint.originalExpression ?? constraint.expression ?? "").trim(),
111
+ editable: normalizeBoolean(constraint.editable),
112
+ preserved: constraint.preserved === undefined ? true : normalizeBoolean(constraint.preserved),
113
+ };
114
+ }
115
+
69
116
  function normalizeDraftPayload(payload = {}) {
70
117
  const mode = String(payload.mode ?? "create").trim() === "edit" ? "edit" : "create";
71
118
 
@@ -76,6 +123,17 @@ function normalizeDraftPayload(payload = {}) {
76
123
  columns: Array.isArray(payload.columns)
77
124
  ? payload.columns.map((column, index) => normalizeColumnPayload(column, index))
78
125
  : [],
126
+ uniqueConstraints: Array.isArray(payload.uniqueConstraints)
127
+ ? payload.uniqueConstraints.map((constraint, index) =>
128
+ normalizeUniqueConstraintPayload(constraint, index)
129
+ )
130
+ : [],
131
+ checkConstraints: Array.isArray(payload.checkConstraints)
132
+ ? payload.checkConstraints.map((constraint, index) =>
133
+ normalizeCheckConstraintPayload(constraint, index)
134
+ )
135
+ : [],
136
+ designerVersion: Number(payload.designerVersion) || 1,
79
137
  schemaWarnings: Array.isArray(payload.schemaWarnings) ? payload.schemaWarnings : [],
80
138
  warnings: Array.isArray(payload.warnings) ? payload.warnings : [],
81
139
  fillImportedRows: normalizeBoolean(payload.fillImportedRows),
@@ -112,7 +170,7 @@ function validatePrimaryKeys(draft, originalDraft) {
112
170
 
113
171
  if (!originalDraft) {
114
172
  throw new ValidationError(
115
- "Table Designer v1 supports a single primary key column when creating a table."
173
+ "Table Designer v2 supports a single primary key column when creating a table."
116
174
  );
117
175
  }
118
176
 
@@ -134,7 +192,7 @@ function validatePrimaryKeys(draft, originalDraft) {
134
192
 
135
193
  if (!isUnchangedCompositePrimaryKey) {
136
194
  throw new ValidationError(
137
- "Table Designer v1 does not support editing composite primary keys."
195
+ "Table Designer v2 does not support editing composite primary keys."
138
196
  );
139
197
  }
140
198
  }
@@ -109,7 +109,7 @@ class TableDesignerService {
109
109
 
110
110
  if (!analysis.executable) {
111
111
  throw new ValidationError(
112
- "This schema change set would require a SQLite table rebuild. Table Designer v1 keeps the SQL preview available but will not execute those changes automatically.",
112
+ "This schema change set would require a SQLite table rebuild. Table Designer v2 keeps the SQL preview available but will not execute those changes automatically.",
113
113
  {
114
114
  code: "TABLE_DESIGNER_REBUILD_REQUIRED",
115
115
  warnings: analysis.warnings,