@sixb/sqlite 0.1.0 → 0.1.1

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.js CHANGED
@@ -1108,6 +1108,110 @@ CREATE INDEX idx_agent_messages_project_thread_role
1108
1108
  ON agent_messages(project_id, thread_id, role, seq);
1109
1109
  `;
1110
1110
 
1111
+ // src/migrations/002-workflow-run-output.sql
1112
+ var _002_workflow_run_output_default = `ALTER TABLE workflow_runs ADD COLUMN output TEXT;
1113
+
1114
+ UPDATE workflow_runs AS run
1115
+ SET output = CASE
1116
+ WHEN EXISTS (
1117
+ SELECT 1
1118
+ FROM workflow_node_runs AS node
1119
+ WHERE node.project_id = run.project_id
1120
+ AND node.workflow_run_id = run.id
1121
+ AND node.status = 'succeeded'
1122
+ AND node.node_type <> 'action'
1123
+ ) THEN COALESCE(
1124
+ (
1125
+ SELECT node.output
1126
+ FROM workflow_node_runs AS node
1127
+ WHERE node.project_id = run.project_id
1128
+ AND node.workflow_run_id = run.id
1129
+ AND node.status = 'succeeded'
1130
+ AND node.node_type <> 'action'
1131
+ ORDER BY node.node_index DESC, node.id DESC
1132
+ LIMIT 1
1133
+ ),
1134
+ '{}'
1135
+ )
1136
+ ELSE run.input
1137
+ END
1138
+ WHERE run.status = 'succeeded';
1139
+ `;
1140
+
1141
+ // src/migrations/003-merge-sync-runs.sql
1142
+ var _003_merge_sync_runs_default = `DROP INDEX idx_sync_runs_project_started;
1143
+ DROP INDEX idx_sync_runs_project_dataset_started;
1144
+ DROP INDEX idx_sync_runs_project_sync_started;
1145
+ DROP INDEX idx_sync_runs_project_status_started;
1146
+
1147
+ ALTER TABLE sync_runs RENAME TO sync_runs_before_merge_mode;
1148
+
1149
+ CREATE TABLE sync_runs (
1150
+ project_id TEXT NOT NULL,
1151
+ id TEXT NOT NULL,
1152
+ sync_id TEXT NOT NULL,
1153
+ dataset_id TEXT NOT NULL,
1154
+ mode TEXT NOT NULL CHECK (mode IN ('snapshot', 'append', 'merge')),
1155
+ status TEXT NOT NULL CHECK (status IN ('running', 'succeeded', 'failed', 'cancelled')),
1156
+ started_at TEXT NOT NULL,
1157
+ finished_at TEXT,
1158
+ rows_read INTEGER CHECK (rows_read IS NULL OR rows_read >= 0),
1159
+ output_version_id TEXT,
1160
+ expected_latest_version_id TEXT,
1161
+ commit_message TEXT,
1162
+ error_name TEXT,
1163
+ error_message TEXT,
1164
+ checkpoint TEXT,
1165
+ PRIMARY KEY (project_id, id)
1166
+ );
1167
+
1168
+ INSERT INTO sync_runs (
1169
+ project_id,
1170
+ id,
1171
+ sync_id,
1172
+ dataset_id,
1173
+ mode,
1174
+ status,
1175
+ started_at,
1176
+ finished_at,
1177
+ rows_read,
1178
+ output_version_id,
1179
+ expected_latest_version_id,
1180
+ commit_message,
1181
+ error_name,
1182
+ error_message,
1183
+ checkpoint
1184
+ )
1185
+ SELECT
1186
+ project_id,
1187
+ id,
1188
+ sync_id,
1189
+ dataset_id,
1190
+ mode,
1191
+ status,
1192
+ started_at,
1193
+ finished_at,
1194
+ rows_read,
1195
+ output_version_id,
1196
+ expected_latest_version_id,
1197
+ commit_message,
1198
+ error_name,
1199
+ error_message,
1200
+ checkpoint
1201
+ FROM sync_runs_before_merge_mode;
1202
+
1203
+ DROP TABLE sync_runs_before_merge_mode;
1204
+
1205
+ CREATE INDEX idx_sync_runs_project_started
1206
+ ON sync_runs(project_id, started_at DESC);
1207
+ CREATE INDEX idx_sync_runs_project_dataset_started
1208
+ ON sync_runs(project_id, dataset_id, started_at DESC);
1209
+ CREATE INDEX idx_sync_runs_project_sync_started
1210
+ ON sync_runs(project_id, sync_id, started_at DESC);
1211
+ CREATE INDEX idx_sync_runs_project_status_started
1212
+ ON sync_runs(project_id, status, started_at DESC);
1213
+ `;
1214
+
1111
1215
  // src/migrations.ts
1112
1216
  var MIGRATIONS_TABLE_SQL = `
1113
1217
  CREATE TABLE IF NOT EXISTS sixb_migrations (
@@ -1125,7 +1229,11 @@ var SQLITE_STORAGE_ADAPTER_ID = "SixbSqliteStorage";
1125
1229
  var SQLITE_STORAGE_FILE = "storage.sqlite";
1126
1230
  var sqliteStorageMigrations = defineMigrations({
1127
1231
  adapterId: SQLITE_STORAGE_ADAPTER_ID,
1128
- steps: [sqliteSql("001-initial-schema", _001_initial_schema_default)]
1232
+ steps: [
1233
+ sqliteSql("001-initial-schema", _001_initial_schema_default),
1234
+ sqliteSql("002-workflow-run-output", _002_workflow_run_output_default),
1235
+ sqliteSql("003-merge-sync-runs", _003_merge_sync_runs_default)
1236
+ ]
1129
1237
  });
1130
1238
  function sqliteStoragePath(basePath) {
1131
1239
  return `${basePath}/${SQLITE_STORAGE_FILE}`;
@@ -5722,22 +5830,30 @@ class SqliteMaterializationStateReader {
5722
5830
  FROM json_each(?)
5723
5831
  `;
5724
5832
  const effectiveRows = this.db.query(`WITH requested AS (${requestedObjects})
5725
- SELECT objects.* FROM objects
5726
- JOIN requested USING (object_type_id, primary_id)
5727
- WHERE objects.project_id = ?`).all(requested, this.projectId);
5833
+ SELECT objects.* FROM requested
5834
+ CROSS JOIN objects
5835
+ ON objects.project_id = ?
5836
+ AND objects.object_type_id = requested.object_type_id
5837
+ AND objects.primary_id = requested.primary_id`).all(requested, this.projectId);
5728
5838
  const sourceRows = this.db.query(`WITH requested AS (${requestedObjects})
5729
- SELECT rows.* FROM ontology_source_rows AS rows
5730
- JOIN requested USING (object_type_id, primary_id)
5839
+ SELECT rows.* FROM requested
5840
+ CROSS JOIN ontology_source_rows AS rows
5841
+ ON rows.project_id = ?
5842
+ AND rows.entity_kind = 'object'
5843
+ AND rows.object_type_id = requested.object_type_id
5844
+ AND rows.primary_id = requested.primary_id
5731
5845
  JOIN ontology_sources AS sources
5732
5846
  ON sources.project_id = rows.project_id
5733
5847
  AND sources.source_id = rows.source_id
5734
5848
  AND sources.materialization_id = rows.materialization_id
5735
- WHERE rows.project_id = ? AND rows.entity_kind = 'object'
5736
- AND sources.status = 'active'`).all(requested, this.projectId);
5849
+ WHERE sources.status = 'active'`).all(requested, this.projectId);
5737
5850
  const overrideRows = this.db.query(`WITH requested AS (${requestedObjects})
5738
- SELECT overrides.* FROM ontology_overrides AS overrides
5739
- JOIN requested USING (object_type_id, primary_id)
5740
- WHERE overrides.project_id = ? AND overrides.entity_kind = 'object'`).all(requested, this.projectId);
5851
+ SELECT overrides.* FROM requested
5852
+ CROSS JOIN ontology_overrides AS overrides
5853
+ ON overrides.project_id = ?
5854
+ AND overrides.entity_kind = 'object'
5855
+ AND overrides.object_type_id = requested.object_type_id
5856
+ AND overrides.primary_id = requested.primary_id`).all(requested, this.projectId);
5741
5857
  const telemetryRows = this.db.query(`WITH requested AS (${requestedObjects}), ranked AS (
5742
5858
  SELECT timeseries.*,
5743
5859
  ROW_NUMBER() OVER (
@@ -5745,11 +5861,11 @@ class SqliteMaterializationStateReader {
5745
5861
  timeseries.property_id
5746
5862
  ORDER BY timeseries.at DESC
5747
5863
  ) AS rank
5748
- FROM timeseries
5749
- JOIN requested
5750
- ON requested.object_type_id = timeseries.object_type_id
5751
- AND requested.primary_id = timeseries.object_id
5752
- WHERE timeseries.project_id = ?
5864
+ FROM requested
5865
+ CROSS JOIN timeseries
5866
+ ON timeseries.project_id = ?
5867
+ AND timeseries.object_type_id = requested.object_type_id
5868
+ AND timeseries.object_id = requested.primary_id
5753
5869
  )
5754
5870
  SELECT * FROM ranked WHERE rank = 1`).all(requested, this.projectId);
5755
5871
  const effective = new Map(effectiveRows.map((row) => [objectRefKey(objectRefFromColumns(row)), row]));
@@ -5807,26 +5923,39 @@ class SqliteMaterializationStateReader {
5807
5923
  FROM json_each(?)
5808
5924
  `;
5809
5925
  const effectiveRows = this.db.query(`WITH requested AS (${effectiveRequest})
5810
- SELECT links.* FROM links
5811
- JOIN requested USING (source_type_id, source_id, link_id, target_type_id, target_id)
5812
- WHERE links.project_id = ?`).all(requested, this.projectId);
5926
+ SELECT links.* FROM requested
5927
+ CROSS JOIN links
5928
+ ON links.project_id = ?
5929
+ AND links.source_type_id = requested.source_type_id
5930
+ AND links.source_id = requested.source_id
5931
+ AND links.link_id = requested.link_id
5932
+ AND links.target_type_id = requested.target_type_id
5933
+ AND links.target_id = requested.target_id`).all(requested, this.projectId);
5813
5934
  const sourceRows = this.db.query(`WITH requested AS (${sourceRequest})
5814
- SELECT rows.* FROM ontology_source_rows AS rows
5815
- JOIN requested USING (
5816
- source_type_id, source_primary_id, link_id, target_type_id, target_primary_id
5817
- )
5935
+ SELECT rows.* FROM requested
5936
+ CROSS JOIN ontology_source_rows AS rows
5937
+ ON rows.project_id = ?
5938
+ AND rows.entity_kind = 'link'
5939
+ AND rows.source_type_id = requested.source_type_id
5940
+ AND rows.source_primary_id = requested.source_primary_id
5941
+ AND rows.link_id = requested.link_id
5942
+ AND rows.target_type_id = requested.target_type_id
5943
+ AND rows.target_primary_id = requested.target_primary_id
5818
5944
  JOIN ontology_sources AS sources
5819
5945
  ON sources.project_id = rows.project_id
5820
5946
  AND sources.source_id = rows.source_id
5821
5947
  AND sources.materialization_id = rows.materialization_id
5822
- WHERE rows.project_id = ? AND rows.entity_kind = 'link'
5823
- AND sources.status = 'active'`).all(requested, this.projectId);
5948
+ WHERE sources.status = 'active'`).all(requested, this.projectId);
5824
5949
  const overrideRows = this.db.query(`WITH requested AS (${sourceRequest})
5825
- SELECT overrides.* FROM ontology_overrides AS overrides
5826
- JOIN requested USING (
5827
- source_type_id, source_primary_id, link_id, target_type_id, target_primary_id
5828
- )
5829
- WHERE overrides.project_id = ? AND overrides.entity_kind = 'link'`).all(requested, this.projectId);
5950
+ SELECT overrides.* FROM requested
5951
+ CROSS JOIN ontology_overrides AS overrides
5952
+ ON overrides.project_id = ?
5953
+ AND overrides.entity_kind = 'link'
5954
+ AND overrides.source_type_id = requested.source_type_id
5955
+ AND overrides.source_primary_id = requested.source_primary_id
5956
+ AND overrides.link_id = requested.link_id
5957
+ AND overrides.target_type_id = requested.target_type_id
5958
+ AND overrides.target_primary_id = requested.target_primary_id`).all(requested, this.projectId);
5830
5959
  const effective = new Map(effectiveRows.map((row) => [linkRefKey(linkRefFromColumns(row)), row]));
5831
5960
  const sources = activeSourceMap(sourceRows);
5832
5961
  const overrides = new Map(overrideRows.map((row) => [linkRefKey(linkRefFromOverrideColumns(row)), storedLinkOverride(row)]));
@@ -5860,9 +5989,13 @@ class SqliteMaterializationStateReader {
5860
5989
  json_extract(value, '$.at') AS at
5861
5990
  FROM json_each(?)
5862
5991
  )
5863
- SELECT timeseries.* FROM timeseries
5864
- JOIN requested USING (object_type_id, object_id, property_id, at)
5865
- WHERE timeseries.project_id = ?`).all(requested, this.projectId);
5992
+ SELECT timeseries.* FROM requested
5993
+ CROSS JOIN timeseries
5994
+ ON timeseries.project_id = ?
5995
+ AND timeseries.object_type_id = requested.object_type_id
5996
+ AND timeseries.object_id = requested.object_id
5997
+ AND timeseries.property_id = requested.property_id
5998
+ AND timeseries.at = requested.at`).all(requested, this.projectId);
5866
5999
  const found = new Map(rows.map((row) => {
5867
6000
  const point = storedPoint(row);
5868
6001
  return [telemetryPointSortKey(point.series, point.at), point];
@@ -5895,9 +6028,12 @@ class SqliteMaterializationStateReader {
5895
6028
  FROM json_each(?)
5896
6029
  )
5897
6030
  SELECT requested.scope_sort_key, links.*
5898
- FROM links
5899
- JOIN requested USING (source_type_id, source_id, link_id)
5900
- WHERE links.project_id = ?
6031
+ FROM requested
6032
+ CROSS JOIN links
6033
+ ON links.project_id = ?
6034
+ AND links.source_type_id = requested.source_type_id
6035
+ AND links.source_id = requested.source_id
6036
+ AND links.link_id = requested.link_id
5901
6037
  ORDER BY requested.scope_sort_key, ${linkSortExpression("links")}
5902
6038
  `).iterate(canonicalJson(requested), this.projectId);
5903
6039
  for (const row of rows) {
@@ -6041,17 +6177,23 @@ class SqliteMaterializationStateReader {
6041
6177
  if (materializationIds.length === 0 || refs.length === 0) {
6042
6178
  return { owned: new Set, byMaterialization: new Map };
6043
6179
  }
6044
- const requestedKeys = canonicalJson(refs.map((ref) => projectionEntityKey(ref)));
6180
+ const requestedEntities = canonicalJson(refs.map((ref) => ({ entityKind: ref.kind, entityKey: projectionEntityKey(ref) })));
6045
6181
  const requestedMaterializations = canonicalJson([...new Set(materializationIds)]);
6046
6182
  const rows = this.db.query(`WITH requested_entities AS (
6047
- SELECT value AS entity_key FROM json_each(?)
6183
+ SELECT DISTINCT json_extract(value, '$.entityKind') AS entity_kind,
6184
+ json_extract(value, '$.entityKey') AS entity_key
6185
+ FROM json_each(?)
6048
6186
  ), requested_materializations AS (
6049
6187
  SELECT value AS materialization_id FROM json_each(?)
6050
6188
  )
6051
- SELECT rows.* FROM ontology_source_rows AS rows
6052
- JOIN requested_entities USING (entity_key)
6053
- JOIN requested_materializations USING (materialization_id)
6054
- WHERE rows.project_id = ? AND rows.source_id = ?`).all(requestedKeys, requestedMaterializations, this.projectId, sourceId);
6189
+ SELECT rows.* FROM requested_materializations
6190
+ CROSS JOIN requested_entities
6191
+ CROSS JOIN ontology_source_rows AS rows
6192
+ ON rows.project_id = ?
6193
+ AND rows.source_id = ?
6194
+ AND rows.materialization_id = requested_materializations.materialization_id
6195
+ AND rows.entity_kind = requested_entities.entity_kind
6196
+ AND rows.entity_key = requested_entities.entity_key`).all(requestedEntities, requestedMaterializations, this.projectId, sourceId);
6055
6197
  const owned = new Set;
6056
6198
  const byMaterialization = new Map;
6057
6199
  for (const row of rows) {
@@ -8670,8 +8812,8 @@ class SqliteSyncRunStorage {
8670
8812
  if (input.output && input.output.datasetId !== existing.dataset_id) {
8671
8813
  throw new SyncRunError(`[SixbSqlite] Sync run '${input.id}' output dataset '${input.output.datasetId}' does not match '${existing.dataset_id}'.`);
8672
8814
  }
8673
- if (!input.output && (existing.mode !== "append" || input.rowsRead !== 0)) {
8674
- throw new SyncRunError(`[SixbSqlite] Sync run '${input.id}' may omit its output only for an empty append.`);
8815
+ if (!input.output && input.rowsRead !== 0 && existing.mode !== "merge") {
8816
+ throw new SyncRunError(`[SixbSqlite] Sync run '${input.id}' may omit its output with rows read only for an initial merge no-op.`);
8675
8817
  }
8676
8818
  }
8677
8819
  this.db.query(`
@@ -9541,10 +9683,12 @@ class SqliteWorkflowRunStorage {
9541
9683
  SET
9542
9684
  status = ?,
9543
9685
  finished_at = ?,
9544
- error = ?
9545
- , execution_token = NULL, execution_queue_lease_expires_at = NULL
9686
+ output = ?,
9687
+ error = ?,
9688
+ execution_token = NULL,
9689
+ execution_queue_lease_expires_at = NULL
9546
9690
  WHERE project_id = ? AND id = ?
9547
- `).run(input.status, (input.finishedAt ?? new Date).toISOString(), input.status === "succeeded" ? null : input.error ?? null, input.projectId, input.id);
9691
+ `).run(input.status, (input.finishedAt ?? new Date).toISOString(), input.status === "succeeded" ? serializeRecord2(input.output) : null, input.status === "succeeded" ? null : input.error ?? null, input.projectId, input.id);
9548
9692
  const updated = this.db.query("SELECT * FROM workflow_runs WHERE project_id = ? AND id = ?").get(input.projectId, input.id);
9549
9693
  return rowToWorkflowRunRecord(updated);
9550
9694
  })();
@@ -9954,6 +10098,7 @@ function rowToWorkflowRunRecord(row) {
9954
10098
  workflowId: row.workflow_id,
9955
10099
  status: row.status,
9956
10100
  input: parseRecord2(row.input),
10101
+ output: row.output ? parseRecord2(row.output) : undefined,
9957
10102
  queuedAt: row.queued_at ? new Date(row.queued_at) : undefined,
9958
10103
  startedAt: new Date(row.started_at),
9959
10104
  finishedAt: row.finished_at ? new Date(row.finished_at) : undefined,
@@ -10201,4 +10346,4 @@ export {
10201
10346
  SqliteStorage
10202
10347
  };
10203
10348
 
10204
- //# debugId=983F7BC9E5B8E71164756E2164756E21
10349
+ //# debugId=531479881454EA0264756E2164756E21