release: v0.2.4 — 701 tests, 32 suites, 零死代码, 零空壳, 全模块接入
This commit is contained in:
+14
-13
@@ -9,6 +9,7 @@ import type { IStorageEngine } from '../interface';
|
||||
import type { QueryPlan, TableSchema, ColumnDef } from '../../constants';
|
||||
import { DatabaseError } from '../../constants';
|
||||
import { matchWhere, applyOrderBy, projectColumns } from '../../query/where-matcher';
|
||||
import { checkFieldType } from '../../table/schema';
|
||||
|
||||
import type { AriaEngineConfig, SSTableMeta } from './types';
|
||||
import { DEFAULT_ARIA_CONFIG } from './types';
|
||||
@@ -460,6 +461,7 @@ export class AriaEngine implements IStorageEngine {
|
||||
|
||||
async count(tableName: string, query?: QueryPlan): Promise<number> {
|
||||
this.ensureOpen();
|
||||
this.ensureTable(tableName);
|
||||
const rows = this.getAllRows(tableName);
|
||||
if (!query?.where || Object.keys(query.where).length === 0) return rows.length;
|
||||
return rows.filter((row) => matchWhere(row, query.where!)).length;
|
||||
@@ -609,22 +611,15 @@ export class AriaEngine implements IStorageEngine {
|
||||
throw new DatabaseError(`Column "${colName}" is required in table "${schema.name}"`, 'VALIDATION_ERROR');
|
||||
}
|
||||
if (value !== undefined && value !== null) {
|
||||
this.checkType(colName, colDef.type, value);
|
||||
this.checkType(colName, colDef.type, value, colDef);
|
||||
}
|
||||
if (value !== undefined) validated[colName] = value;
|
||||
}
|
||||
return validated;
|
||||
}
|
||||
|
||||
private checkType(colName: string, type: string, value: unknown): void {
|
||||
const jsType = typeof value;
|
||||
switch (type) {
|
||||
case 'string': if (jsType !== 'string') throw new DatabaseError(`Column "${colName}" expects string, got ${jsType}`, 'TYPE_ERROR'); break;
|
||||
case 'number': if (jsType !== 'number') throw new DatabaseError(`Column "${colName}" expects number, got ${jsType}`, 'TYPE_ERROR'); break;
|
||||
case 'boolean': if (jsType !== 'boolean') throw new DatabaseError(`Column "${colName}" expects boolean, got ${jsType}`, 'TYPE_ERROR'); break;
|
||||
case 'date': if (jsType !== 'string' || isNaN(Date.parse(value as string))) throw new DatabaseError(`Column "${colName}" expects valid date`, 'TYPE_ERROR'); break;
|
||||
case 'json': if (jsType !== 'object') throw new DatabaseError(`Column "${colName}" expects object/array, got ${jsType}`, 'TYPE_ERROR'); break;
|
||||
}
|
||||
private checkType(colName: string, type: string, value: unknown, colDef?: ColumnDef): void {
|
||||
checkFieldType('', colName, type as any, value, colDef);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
@@ -873,8 +868,12 @@ export class AriaEngine implements IStorageEngine {
|
||||
}
|
||||
// $gt / $gte / $lt / $lte → 范围扫描
|
||||
if ('$gt' in c || '$gte' in c || '$lt' in c || '$lte' in c) {
|
||||
const startKey = c.$gt ? `${String(Number(c.$gt) + 1)}:` : c.$gte ? `${String(c.$gte)}:` : `${col}:`;
|
||||
const endKey = c.$lt ? `${String(Number(c.$lt) - 1)}:\uffff` : c.$lte ? `${String(c.$lte)}:\uffff` : `${col}:\uffff`;
|
||||
let startKey = '';
|
||||
let endKey = '\uffff';
|
||||
if (c.$gt !== undefined) startKey = `${String(Number(c.$gt) + 1)}:`;
|
||||
else if (c.$gte !== undefined) startKey = `${String(c.$gte)}:`;
|
||||
if (c.$lt !== undefined) endKey = `${String(Number(c.$lt) - 1)}:\uffff`;
|
||||
else if (c.$lte !== undefined) endKey = `${String(c.$lte)}:\uffff`;
|
||||
return this.indexScanToRows(tableName, pkCol, idxLsm, col, startKey, endKey);
|
||||
}
|
||||
}
|
||||
@@ -887,7 +886,9 @@ export class AriaEngine implements IStorageEngine {
|
||||
tableName: string, pkCol: string, idxLsm: LSM,
|
||||
_col: string, startKey: string, endKey: string,
|
||||
): Record<string, unknown>[] {
|
||||
const entries = idxLsm.rangeScan(startKey, endKey);
|
||||
// 使用前缀扫描:endKey 需要包含 \uffff 以匹配所有带后缀的 key
|
||||
const actualEndKey = endKey.includes('\uffff') ? endKey : `${endKey}\uffff`;
|
||||
const entries = idxLsm.rangeScan(startKey, actualEndKey);
|
||||
const rows: Record<string, unknown>[] = [];
|
||||
for (const [, idxEntry] of entries) {
|
||||
const pk = (idxEntry as any).pk as string;
|
||||
|
||||
Reference in New Issue
Block a user