@xnetjs/sqlite 0.1.0 → 0.1.2
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.
|
@@ -591,6 +591,9 @@ var ElectronSQLiteAdapter = class {
|
|
|
591
591
|
for (const property of input.properties) {
|
|
592
592
|
ops.push(
|
|
593
593
|
() => this.getOrPrepare(
|
|
594
|
+
// Full LWW ordering triple (lamport → wallTime → author), matching
|
|
595
|
+
// `shouldReplace` in @xnetjs/data. A lamport-only guard let arrival
|
|
596
|
+
// order decide same-lamport conflicts, diverging replicas (0272).
|
|
594
597
|
`INSERT INTO node_properties
|
|
595
598
|
(node_id, property_key, value, lamport_time, updated_by, updated_at)
|
|
596
599
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
@@ -599,7 +602,11 @@ var ElectronSQLiteAdapter = class {
|
|
|
599
602
|
lamport_time = excluded.lamport_time,
|
|
600
603
|
updated_by = excluded.updated_by,
|
|
601
604
|
updated_at = excluded.updated_at
|
|
602
|
-
WHERE excluded.lamport_time > node_properties.lamport_time
|
|
605
|
+
WHERE excluded.lamport_time > node_properties.lamport_time
|
|
606
|
+
OR (excluded.lamport_time = node_properties.lamport_time
|
|
607
|
+
AND (excluded.updated_at > node_properties.updated_at
|
|
608
|
+
OR (excluded.updated_at = node_properties.updated_at
|
|
609
|
+
AND excluded.updated_by > node_properties.updated_by)))`
|
|
603
610
|
).run(
|
|
604
611
|
property.nodeId,
|
|
605
612
|
property.propertyKey,
|
package/dist/adapters/web.js
CHANGED
|
@@ -489,6 +489,9 @@ var WebSQLiteAdapter = class {
|
|
|
489
489
|
}
|
|
490
490
|
for (const property of input.properties) {
|
|
491
491
|
await this.run(
|
|
492
|
+
// Full LWW ordering triple (lamport → wallTime → author), matching
|
|
493
|
+
// `shouldReplace` in @xnetjs/data. A lamport-only guard let arrival
|
|
494
|
+
// order decide same-lamport conflicts, diverging replicas (0272).
|
|
492
495
|
`INSERT INTO node_properties
|
|
493
496
|
(node_id, property_key, value, lamport_time, updated_by, updated_at)
|
|
494
497
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
@@ -497,7 +500,11 @@ var WebSQLiteAdapter = class {
|
|
|
497
500
|
lamport_time = excluded.lamport_time,
|
|
498
501
|
updated_by = excluded.updated_by,
|
|
499
502
|
updated_at = excluded.updated_at
|
|
500
|
-
WHERE excluded.lamport_time > node_properties.lamport_time
|
|
503
|
+
WHERE excluded.lamport_time > node_properties.lamport_time
|
|
504
|
+
OR (excluded.lamport_time = node_properties.lamport_time
|
|
505
|
+
AND (excluded.updated_at > node_properties.updated_at
|
|
506
|
+
OR (excluded.updated_at = node_properties.updated_at
|
|
507
|
+
AND excluded.updated_by > node_properties.updated_by)))`,
|
|
501
508
|
[
|
|
502
509
|
property.nodeId,
|
|
503
510
|
property.propertyKey,
|
package/dist/index.d.ts
CHANGED
|
@@ -163,8 +163,9 @@ interface SQLiteRuntimeCapabilities {
|
|
|
163
163
|
/**
|
|
164
164
|
* Get information about all indexes in the database. Cached per adapter and keyed
|
|
165
165
|
* on `PRAGMA schema_version`, so repeated calls between DDL changes pay one cheap
|
|
166
|
-
* version probe instead of
|
|
167
|
-
*
|
|
166
|
+
* version probe instead of a rebuild (exploration 0253). Concurrent callers share
|
|
167
|
+
* a single in-flight probe+build, and a cold build is a single batched statement
|
|
168
|
+
* — worst case one diagnostic run costs 2 worker round-trips, not 1 + 1 + N.
|
|
168
169
|
*/
|
|
169
170
|
declare function getIndexInfo(db: SQLiteAdapter): Promise<IndexInfo[]>;
|
|
170
171
|
/**
|
package/dist/index.js
CHANGED
|
@@ -79,12 +79,35 @@ async function readSchemaVersion(db) {
|
|
|
79
79
|
return 0;
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
async function
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
async function fetchIndexInfoBatched(db) {
|
|
83
|
+
const rows = await db.query(
|
|
84
|
+
`SELECT m.name AS index_name, m.tbl_name AS table_name, m.sql AS index_sql,
|
|
85
|
+
ii.seqno AS seqno, ii.name AS column_name
|
|
86
|
+
FROM sqlite_master AS m
|
|
87
|
+
LEFT JOIN pragma_index_info(m.name) AS ii
|
|
88
|
+
WHERE m.type = 'index' AND m.name NOT LIKE 'sqlite_%'
|
|
89
|
+
ORDER BY m.name, ii.seqno`
|
|
90
|
+
);
|
|
91
|
+
const byName = /* @__PURE__ */ new Map();
|
|
92
|
+
for (const row of rows) {
|
|
93
|
+
let info = byName.get(row.index_name);
|
|
94
|
+
if (!info) {
|
|
95
|
+
info = {
|
|
96
|
+
name: row.index_name,
|
|
97
|
+
tableName: row.table_name,
|
|
98
|
+
unique: row.index_sql?.includes("UNIQUE") ?? false,
|
|
99
|
+
columns: [],
|
|
100
|
+
partial: row.index_sql?.includes("WHERE") ?? false
|
|
101
|
+
};
|
|
102
|
+
byName.set(row.index_name, info);
|
|
103
|
+
}
|
|
104
|
+
if (row.seqno !== null) {
|
|
105
|
+
info.columns.push(row.column_name);
|
|
106
|
+
}
|
|
87
107
|
}
|
|
108
|
+
return [...byName.values()];
|
|
109
|
+
}
|
|
110
|
+
async function fetchIndexInfoPerIndex(db) {
|
|
88
111
|
const indexes = await db.query(
|
|
89
112
|
"SELECT name, tbl_name, sql FROM sqlite_master WHERE type='index' AND name NOT LIKE 'sqlite_%'"
|
|
90
113
|
);
|
|
@@ -99,9 +122,39 @@ async function getIndexInfo(db) {
|
|
|
99
122
|
partial: idx.sql?.includes("WHERE") ?? false
|
|
100
123
|
});
|
|
101
124
|
}
|
|
102
|
-
indexInfoCache.set(db, { schemaVersion, indexes: result });
|
|
103
125
|
return result;
|
|
104
126
|
}
|
|
127
|
+
async function getIndexInfo(db) {
|
|
128
|
+
let entry = indexInfoCache.get(db);
|
|
129
|
+
if (!entry) {
|
|
130
|
+
entry = {};
|
|
131
|
+
indexInfoCache.set(db, entry);
|
|
132
|
+
}
|
|
133
|
+
if (entry.inFlight) {
|
|
134
|
+
return entry.inFlight;
|
|
135
|
+
}
|
|
136
|
+
const cacheEntry = entry;
|
|
137
|
+
const inFlight = (async () => {
|
|
138
|
+
const schemaVersion = await readSchemaVersion(db);
|
|
139
|
+
if (cacheEntry.resolved && cacheEntry.resolved.schemaVersion === schemaVersion) {
|
|
140
|
+
return cacheEntry.resolved.indexes;
|
|
141
|
+
}
|
|
142
|
+
let indexes;
|
|
143
|
+
try {
|
|
144
|
+
indexes = await fetchIndexInfoBatched(db);
|
|
145
|
+
} catch {
|
|
146
|
+
indexes = await fetchIndexInfoPerIndex(db);
|
|
147
|
+
}
|
|
148
|
+
cacheEntry.resolved = { schemaVersion, indexes };
|
|
149
|
+
return indexes;
|
|
150
|
+
})();
|
|
151
|
+
entry.inFlight = inFlight;
|
|
152
|
+
try {
|
|
153
|
+
return await inFlight;
|
|
154
|
+
} finally {
|
|
155
|
+
cacheEntry.inFlight = void 0;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
105
158
|
async function analyzeQuery(db, sql, params) {
|
|
106
159
|
const plan = await db.query(`EXPLAIN QUERY PLAN ${sql}`, params);
|
|
107
160
|
const steps = plan.map((row) => ({
|