{"id":16798,"library":"database-js-sqlparser","title":"database-js-sqlparser: SQL Parser for database-js Drivers","description":"database-js-sqlparser (current stable version 1.0.0) provides common SQL parsing functionality for `database-js` drivers that interact with non-database backends, such as in-memory data structures, local files, or APIs. It is not a database itself; rather, it acts as an abstract base class, translating standard SQL (including CREATE/DROP TABLE, SELECT, INSERT, UPDATE, DELETE) into calls to an underlying storage mechanism. Developers must extend this class and implement several asynchronous methods (e.g., `ready`, `close`, `load`, `store`, `remove`, `create`) to provide the actual data persistence. The library supports a subset of SQL, including basic CRUD operations, inner/left/right joins, grouping, filtering, ordering, and limiting. Its release cadence is not explicitly stated, but as a foundational 1.0.0 library, it is likely stable with less frequent, more deliberate updates. A key differentiator is its focus on providing a SQL interface over arbitrary JavaScript storage, abstracting away the specifics of the backend.","status":"active","version":"1.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/mlaanderson/database-js-sqlparser","tags":["javascript","database-js","driver"],"install":[{"cmd":"npm install database-js-sqlparser","lang":"bash","label":"npm"},{"cmd":"yarn add database-js-sqlparser","lang":"bash","label":"yarn"},{"cmd":"pnpm add database-js-sqlparser","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"This package is designed to be extended by drivers within the `database-js` ecosystem, forming a core component for SQL parsing in that context.","package":"database-js","optional":false}],"imports":[{"note":"The library primarily uses a CommonJS `module.exports = SQLParser;` pattern. For ESM, it is typically consumed as a default import for compatibility.","wrong":"import { SQLParser } from 'database-js-sqlparser';","symbol":"SQLParser","correct":"import SQLParser from 'database-js-sqlparser';"},{"note":"This is the native CommonJS export pattern for the `SQLParser` class.","symbol":"SQLParser (CommonJS)","correct":"const SQLParser = require('database-js-sqlparser');"},{"note":"The primary usage pattern is to extend the `SQLParser` class to implement custom storage logic.","symbol":"extending SQLParser","correct":"class MyDriver extends SQLParser { /* ... */ }"}],"quickstart":{"code":"import SQLParser from 'database-js-sqlparser';\n\nclass InMemoryDriver extends SQLParser {\n    constructor() {\n        super();\n        this.tables = {}; // Simple in-memory storage\n        this.lastId = 0;\n    }\n\n    ready() {\n        console.log('InMemoryDriver: Ready.');\n        return Promise.resolve(true);\n    }\n\n    close() {\n        console.log('InMemoryDriver: Closing...');\n        this.tables = {};\n        this.lastId = 0;\n        return Promise.resolve(true);\n    }\n\n    async load(tableName) {\n        console.log(`InMemoryDriver: Loading from table '${tableName}'`);\n        return Promise.resolve(Object.values(this.tables[tableName] || {}));\n    }\n\n    async store(tableName, index, row) {\n        console.log(`InMemoryDriver: Storing in table '${tableName}', index: ${index}`);\n        if (!this.tables[tableName]) {\n            throw new Error(`Table '${tableName}' does not exist.`);\n        }\n\n        let id = index;\n        if (id === null || id === undefined) {\n            this.lastId++;\n            id = this.lastId;\n            row.id = id; // Assuming 'id' is a common primary key column\n        }\n\n        this.tables[tableName][id] = { ...row, id };\n        return Promise.resolve(id);\n    }\n\n    async remove(tableName, index) {\n        console.log(`InMemoryDriver: Removing from table '${tableName}', index: ${index}`);\n        if (!this.tables[tableName] || !this.tables[tableName][index]) {\n            throw new Error(`Row with index '${index}' not found in table '${tableName}'.`);\n        }\n        delete this.tables[tableName][index];\n        return Promise.resolve(index);\n    }\n\n    async create(tableName, definition) {\n        console.log(`InMemoryDriver: Creating table '${tableName}' with definition:`, definition);\n        if (this.tables[tableName]) {\n            throw new Error(`Table '${tableName}' already exists.`);\n        }\n        this.tables[tableName] = {}; // Initialize with an empty object for rows\n        // In a real scenario, 'definition' would be used to validate column types.\n        return Promise.resolve(true);\n    }\n\n    async drop(tableName) {\n        console.log(`InMemoryDriver: Dropping table '${tableName}'`);\n        if (!this.tables[tableName]) {\n            throw new Error(`Table '${tableName}' does not exist.`);\n        }\n        delete this.tables[tableName];\n        return Promise.resolve(true);\n    }\n}\n\nasync function runExample() {\n    const driver = new InMemoryDriver();\n    await driver.ready();\n\n    // Simulate SQL operations by calling internal methods (in a real scenario, database-js would do this)\n    // This is for demonstration of implementing the driver methods\n    await driver.create('users', [\n        { name: 'id', type: 'INTEGER' },\n        { name: 'name', type: 'VARCHAR(255)' },\n        { name: 'age', type: 'INTEGER' }\n    ]);\n\n    let userId1 = await driver.store('users', null, { name: 'Alice', age: 30 });\n    let userId2 = await driver.store('users', null, { name: 'Bob', age: 25 });\n\n    console.log('All users after inserts:', await driver.load('users'));\n\n    await driver.store('users', userId1, { name: 'Alicia', age: 31, id: userId1 }); // Update\n    console.log('Users after update:', await driver.load('users'));\n\n    await driver.remove('users', userId2);\n    console.log('Users after delete:', await driver.load('users'));\n\n    await driver.drop('users');\n    console.log('Driver closing...');\n    await driver.close();\n}\n\nrunExample().catch(console.error);\n","lang":"javascript","description":"This quickstart demonstrates how to extend the `SQLParser` class to create a custom in-memory `database-js` driver. It implements the required `ready`, `close`, `load`, `store`, `remove`, `create`, and `drop` methods, simulating basic table and row management in RAM. It shows how the abstract methods translate SQL operations to direct storage interactions."},"warnings":[{"fix":"Always extend the `SQLParser` class and implement all seven required asynchronous methods (`ready`, `close`, `load`, `store`, `remove`, `create`, `drop`) to provide concrete storage logic.","message":"This package is an abstract SQL parser and *does not provide any data storage or database connectivity itself*. It must be extended by a custom driver that implements the underlying storage mechanism.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure that SQL queries submitted to drivers built on `database-js-sqlparser` only use `INNER JOIN`, `LEFT JOIN`, or `RIGHT JOIN`.","message":"The SQL parser has limitations: it does not support `FULL JOIN` or `OUTER JOIN` clauses.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always ensure that columns passed to aggregate functions like `SUM` contain valid numeric data types to avoid unexpected results.","message":"When using aggregate functions like `SUM`, providing non-numeric columns may not throw an error but will result in an `undefined` return value for that aggregate.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Be mindful of these differences when defining table schemas and inserting string data to avoid unexpected padding or data loss.","message":"Column types `CHARACTER(n)` and `VARCHAR(n)` handle length constraints differently. `CHARACTER(n)` will pad or truncate to `n` length, while `VARCHAR(n)` will only truncate to `n` length without padding.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Implement all seven abstract methods (`ready`, `close`, `load`, `store`, `remove`, `create`, `drop`) in your custom driver class that extends `SQLParser`.","cause":"An extending driver class failed to implement one of the required abstract methods (e.g., `load`, `store`, `remove`, `create`, `drop`, `ready`, `close`).","error":"TypeError: this.load is not a function"},{"fix":"Review the supported SQL syntax in the `database-js-sqlparser` documentation and rewrite the query to use only supported features. Debug by simplifying the query to isolate the unsupported part.","cause":"The SQL query contains syntax not supported by `database-js-sqlparser` (e.g., `FULL JOIN`, unsupported functions, or dialect-specific clauses).","error":"Error: SQLParseError: Syntax error near 'UNSUPPORTED_KEYWORD'"},{"fix":"Always use `await` when calling asynchronous methods (like `ready()`, `load()`, `store()`, etc.) on your `SQLParser`-based driver, or chain `.then()` and `.catch()` to handle the Promise resolution.","cause":"Operations on the `SQLParser` or its extending driver methods are asynchronous, but the calling code did not `await` their results or handle the returned Promises correctly.","error":"Promise { <pending> }"}],"ecosystem":"npm","meta_description":null}