mirror of
https://github.com/ruvnet/RuVector.git
synced 2026-05-27 00:25:10 +00:00
* fix(rvlite): Resolve getrandom WASM conflict with hnsw_rs patch Resolves the getrandom version conflict that prevented rvlite from compiling to WASM. The issue was caused by hnsw_rs 0.3.3 using rand 0.9 -> getrandom 0.3, while the workspace uses rand 0.8 -> getrandom 0.2. Changes: - Add [patch.crates-io] to workspace Cargo.toml for hnsw_rs - Include patched hnsw_rs 0.3.3 with rand 0.8 dependency - Modify hnsw_rs/Cargo.toml: rand = "0.8" (was "0.9") Note: This patch is applied but not actively used since rvlite disables the HNSW feature via default-features = false. The patch ensures compatibility if HNSW is enabled in the future. Build Status: ✅ WASM compiles successfully ✅ Bundle size: 96 KB gzipped (with ruvector-core) ✅ Full vector operations working ✅ No getrandom conflicts Related: - rvlite uses ruvector-core with memory-only feature - Avoids hnsw_rs dependency via default-features = false - Target-specific getrandom dependency enables "js" feature 🤖 Generated with Claude Code * feat(rvlite): Add multi-query language support (SPARQL, SQL, Cypher) This comprehensive update adds support for three query languages to rvlite, making it a versatile WASM-powered vector database with knowledge graph capabilities. The implementation includes full parsers, AST representations, and executors for each language. ## SPARQL Implementation - W3C SPARQL 1.1 compliant query parser - Triple pattern matching with subject/predicate/object - SELECT, CONSTRUCT, ASK, and DESCRIBE query forms - FILTER expressions with comparison and logical operators - OPTIONAL patterns and UNION support - ORDER BY, LIMIT, OFFSET modifiers - Built-in RDF triple store with in-memory indexing ## SQL Implementation - Standard SQL SELECT with projections and aliases - WHERE clause with complex boolean expressions - JOIN support (INNER, LEFT, RIGHT, FULL, CROSS) - Aggregate functions (COUNT, SUM, AVG, MIN, MAX) - GROUP BY and HAVING clauses - ORDER BY with ASC/DESC, LIMIT/OFFSET - Subqueries and nested expressions - Vector similarity search via special syntax ## Cypher Implementation - Neo4j-compatible Cypher query language - MATCH patterns with node and relationship traversal - CREATE, MERGE, SET, DELETE operations - WHERE clause filtering - RETURN with aliases and expressions - ORDER BY, SKIP, LIMIT modifiers - Variable-length path patterns - Property graph store with adjacency indexing ## Additional Changes - Interactive React dashboard with visualization - Supply chain simulation demo - Graph visualization components - IndexedDB persistence layer for browser storage - WASM getrandom conflict resolution for hnsw_rs - SONA time compatibility for cross-platform builds - NPM package for rvlite distribution - Documentation for all query implementations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
113 lines
4.7 KiB
JavaScript
113 lines
4.7 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* SQL Test Script - Test CREATE TABLE and SQL operations in WASM
|
|
*/
|
|
|
|
import { readFile } from 'fs/promises';
|
|
import { fileURLToPath } from 'url';
|
|
import { dirname, join } from 'path';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
|
|
async function main() {
|
|
console.log('╔════════════════════════════════════════════════════════════╗');
|
|
console.log('║ RvLite WASM SQL Test Suite ║');
|
|
console.log('╚════════════════════════════════════════════════════════════╝\n');
|
|
|
|
// Load WASM
|
|
const wasmPath = join(__dirname, '../public/pkg/rvlite_bg.wasm');
|
|
const wasmBytes = await readFile(wasmPath);
|
|
|
|
const { default: initRvLite, RvLite, RvLiteConfig } = await import('../public/pkg/rvlite.js');
|
|
await initRvLite(wasmBytes);
|
|
console.log('WASM loaded successfully!\n');
|
|
|
|
const config = new RvLiteConfig(384);
|
|
const db = new RvLite(config);
|
|
|
|
const tests = [];
|
|
|
|
function test(name, fn) {
|
|
try {
|
|
fn();
|
|
tests.push({ name, passed: true });
|
|
console.log(` \x1b[32m✓\x1b[0m ${name}`);
|
|
} catch (error) {
|
|
tests.push({ name, passed: false, error: error.message });
|
|
console.log(` \x1b[31m✗\x1b[0m ${name}`);
|
|
console.log(` Error: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
console.log('═══════════════════════════════════════════════════════════════');
|
|
console.log('SQL Parser Tests');
|
|
console.log('═══════════════════════════════════════════════════════════════');
|
|
|
|
// Test 1: CREATE TABLE with VECTOR column (3-dimensional for test)
|
|
test('CREATE TABLE with VECTOR', () => {
|
|
const result = db.sql("CREATE TABLE docs (id TEXT, content TEXT, embedding VECTOR(3))");
|
|
console.log(' Result:', JSON.stringify(result));
|
|
});
|
|
|
|
// Test 2: INSERT with correct vector dimensions
|
|
test('INSERT INTO table', () => {
|
|
const result = db.sql("INSERT INTO docs (id, content, embedding) VALUES ('doc1', 'hello world', [1.0, 2.0, 3.0])");
|
|
console.log(' Result:', JSON.stringify(result));
|
|
});
|
|
|
|
// Test 3: INSERT another vector
|
|
test('INSERT second vector', () => {
|
|
const result = db.sql("INSERT INTO docs (id, content, embedding) VALUES ('doc2', 'test content', [4.0, 5.0, 6.0])");
|
|
console.log(' Result:', JSON.stringify(result));
|
|
});
|
|
|
|
// Test 4: Vector search with L2 distance
|
|
test('Vector search with L2 distance', () => {
|
|
const result = db.sql("SELECT * FROM docs ORDER BY embedding <-> [1.0, 2.0, 3.0] LIMIT 5");
|
|
console.log(' Result:', JSON.stringify(result));
|
|
});
|
|
|
|
// Test 5: Vector search with cosine distance
|
|
test('Vector search with cosine distance', () => {
|
|
const result = db.sql("SELECT * FROM docs ORDER BY embedding <=> [0.5, 0.5, 0.5] LIMIT 5");
|
|
console.log(' Result:', JSON.stringify(result));
|
|
});
|
|
|
|
// Test 6: Vector search with filter
|
|
test('Vector search with filter', () => {
|
|
const result = db.sql("SELECT * FROM docs WHERE id = 'doc1' ORDER BY embedding <-> [1.0, 2.0, 3.0] LIMIT 5");
|
|
console.log(' Result:', JSON.stringify(result));
|
|
});
|
|
|
|
// Test 7: DROP TABLE
|
|
test('DROP TABLE', () => {
|
|
const result = db.sql("DROP TABLE docs");
|
|
console.log(' Result:', JSON.stringify(result));
|
|
});
|
|
|
|
// Cleanup
|
|
db.free();
|
|
|
|
// Summary
|
|
console.log('\n╔════════════════════════════════════════════════════════════╗');
|
|
console.log('║ TEST SUMMARY ║');
|
|
console.log('╚════════════════════════════════════════════════════════════╝\n');
|
|
|
|
const passed = tests.filter(t => t.passed).length;
|
|
const failed = tests.filter(t => !t.passed).length;
|
|
|
|
console.log(` Total: ${tests.length} tests`);
|
|
console.log(` \x1b[32mPassed: ${passed}\x1b[0m`);
|
|
console.log(` \x1b[31mFailed: ${failed}\x1b[0m`);
|
|
|
|
if (failed > 0) {
|
|
console.log('\n Failed tests:');
|
|
tests.filter(t => !t.passed).forEach(t => {
|
|
console.log(` - ${t.name}: ${t.error}`);
|
|
});
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
main().catch(console.error);
|