jsql-neo 6.5.4 → 6.5.5

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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > **One engine to rule them all** — a Rust-powered embedded database that speaks your language:
4
4
  > MySQL, PostgreSQL, MongoDB, Redis, SQL, TypeScript, **and the browser**.
5
5
 
6
- > **v6.5.4** — stable release · [github.com/vexify-org/JSQL-neo](https://github.com/vexify-org/JSQL-neo) · [jsql.vexify.top](https://jsql.vexify.top)
6
+ > **v6.5.5** — stable release · [github.com/vexify-org/JSQL-neo](https://github.com/vexify-org/JSQL-neo) · [jsql.vexify.top](https://jsql.vexify.top)
7
7
 
8
8
  ![Engines](https://img.shields.io/badge/engines-Native%20%7C%20WASM%20%7C%20Pure%20JS-7ee787)
9
9
  ![MySQL](https://img.shields.io/badge/protocol-MySQL%20compatible-1f6feb)
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * JSQL-NEO v6.5.4 — Rust-Powered Embedded Database (WASM + HTTP)
2
+ * JSQL-NEO v6.5.5 — Rust-Powered Embedded Database (WASM + HTTP)
3
3
  *
4
4
  * @example
5
5
  * const jsql = require('jsql-neo');
@@ -725,24 +725,59 @@ class JSQL {
725
725
  /**
726
726
  * 校验 UPDATE 后的主键 / UNIQUE 值不与其它行冲突。
727
727
  * 逐行比对(未建索引也正确);值未变化时跳过。
728
+ *
729
+ * 6.5.5 性能修复(对齐 native_client.js 的 6.4.8 修复,那次漏了 wasm 侧):
730
+ * 旧写法无条件 `this.find(table, {}, {limit: 1e9})` 把整张表导出成 JSON,
731
+ * 再逐字段 find/some。updateById 于是在 10 万行的表上要 ~590ms/次 ——
732
+ * 比读整张表还贵,而它本来只需要定位一行。
733
+ * UPDATE t SET age = 30 WHERE id = 1 ← age 不是键,不可能冲突,却付了全表钱
734
+ *
735
+ * 新逻辑(性能从 O(表行数) 降回 O(1)):
736
+ * 1. 只筛出 pk + unique 列,且**确实出现在 updateData 里**的(touched);
737
+ * 一个都没碰 → 直接 return,整张表一个字都不读;
738
+ * 2. 先用主键把**自己那一行**取回来(一条走 pk 的 find,limit 1,O(1))。
739
+ * 所有 touched 列的新值都和现值相同 → 值没变,同样直接 return
740
+ * (幂等更新不误报,也不再触发全表扫描);
741
+ * 3. 真的动了键,才退化成整表扫描逐字段比对(正确性优先)。
728
742
  */
729
743
  async _assertNoKeyConflict(table, id, data, selfSeq) {
730
744
  const schema = this._schemas[table];
731
745
  if (!schema) return;
732
746
  const fields = Object.keys(schema).filter(f => schema[f] && (schema[f].primaryKey || schema[f].unique));
733
747
  if (!fields.length) return;
748
+ // 只在**确实要改主键 / UNIQUE 列**时才做冲突检查。
749
+ const touched = fields.filter(f => Object.prototype.hasOwnProperty.call(data, f));
750
+ if (!touched.length) return;
751
+
752
+ // 自己那一行:走主键的 find(limit 1),不整表导出。
753
+ let self = null;
754
+ try {
755
+ const pk = this._pkOf(table);
756
+ if (pk) {
757
+ const one = await this.find(table, { [pk]: this._coercePkId(table, id) }, { limit: 1, offset: 0 });
758
+ self = Array.isArray(one) ? (one[0] || null) : null;
759
+ }
760
+ } catch (_) {
761
+ self = null; // 取不到就走下面的全量比对
762
+ }
763
+ // 所有 touched 列的值都没变 → 幂等更新,不可能产生新冲突,无需扫表。
764
+ if (self && touched.every(f => self[f] === data[f])) return;
765
+
734
766
  let rows;
735
767
  try {
736
768
  rows = await this.find(table, {}, { limit: 1e9, offset: 0 });
737
769
  } catch (_) {
738
770
  return; // 读不到就不拦,交给底层报错
739
771
  }
772
+ if (!Array.isArray(rows)) return;
773
+ // 把自己那一行找出来并从比对中排除。注意:self 来自上一次 find,
774
+ // 与 rows 里的对象不是同一个引用,所以必须按 id 重新定位,不能直接 r !== self。
775
+ const selfRow = self || rows.find(r => r && String(r.id) === String(id)) || null;
740
776
  for (const f of fields) {
741
777
  if (!Object.prototype.hasOwnProperty.call(data, f)) continue;
742
778
  const nv = data[f];
743
- const self = rows.find(r => r && String(r.id) === String(id));
744
- if (self && self[f] === nv) continue; // 值没变
745
- if (rows.some(r => r && r !== self && r[f] === nv)) {
779
+ if (selfRow && selfRow[f] === nv) continue; // 值没变
780
+ if (rows.some(r => r && r !== selfRow && r[f] === nv)) {
746
781
  const e = new Error(`Duplicate entry '${nv}' for key '${f}'`);
747
782
  e.code = 'ER_DUP_ENTRY';
748
783
  e.errno = 1062;
Binary file
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jsql-neo",
3
- "version": "6.5.4",
4
- "description": "JSQL-NEO — Rust-powered embedded database with WASM, REST API, B-Tree indexes, WAL, crash recovery",
3
+ "version": "6.5.5",
4
+ "description": "JSQL-NEO \u2014 Rust-powered embedded database with WASM, REST API, B-Tree indexes, WAL, crash recovery",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
7
  "exports": {
@@ -97,4 +97,4 @@
97
97
  "devDependencies": {
98
98
  "c8": "^10.1.2"
99
99
  }
100
- }
100
+ }