Merge pull request #17 from h-sphere/feat/sqljs

feat: Reworking Database to SQLJS
This commit is contained in:
Kacper Kula 2024-11-06 20:47:20 +00:00 committed by GitHub
commit cb289ff65f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 912 additions and 15130 deletions

8
.gitignore vendored
View file

@ -22,9 +22,5 @@ data.json
.DS_Store
docs/.vitepress/dist
docs/.vitepress/cache
rebuild
better_sqlite3.node
better_sqlite3*.node
database.sqlite
coverage/
coverage/
dist/

View file

@ -1,3 +1,7 @@
# 0.10.0
SQLSeal is not compatible with mobile! Plugin now uses SQL.JS instead of better-sqlite3 which is written in Web Assembly so no longer native binaries are needed. This makes plugin portable.
Also reworked implementation of the parser from Antlr4TS into Antlr4.
# 0.9.2
Adding checkbox method to display boolean values as checkboxes
Fixing how updates are parsed

View file

@ -3,13 +3,8 @@
SQLSeal allows to transform your CSV files located in your vault into fully-fledged SQL database. You can use SQL statements to query this data however you like.
## Installation
Once the library is published in Obsidian Official Community Repository: just head to Community Tab in your Obisidian Settings page and search for "SQLSeal".
Note: Please note that this plugin is in early phase. Basic functionality should work just fine but I do not take any responsibility for potential data loss and damage to your Vault.
On the first try plugin will download better_sqlite3.node binary to run database locally. This is due to the Obsidian restrictions to bundle everything in the `main.js`. The whole process of generating it is public and you can check it in the GitHub workflows.
The plugin creates database file in configuration folder `.obsidian` named `sqlseal.db`.
You can install plugin from the Community Plugins directly from Obsidian, just look for SQLSeal in the marketplace.
### Manual Instalation
To manually install the package, open [Releases](https://github.com/h-sphere/sql-seal/releases) and download .zip of the last one. Unzip it in your vault under `.obsidian/Plugins/sqlseal`.
@ -29,6 +24,9 @@ You can define multiple tables in a single snippet. You can also point to the ta
For more comprehensive documentation head to [hypersphere.blog/sql-seal](https://hypersphere.blog/sql-seal).
# Disclaimer
The plugin authors do not take any resposibility for any potential data loss. Always backup your files before usage. That said, plugin does not modify any files in the Vault so you should be fine :)
# Stay in Touch!
If you have any questions about the project, ideas or want to share your use-cases, [join our Discord Channel](https://discord.gg/ZMRnFeAWXb)!

View file

@ -1,23 +1,44 @@
import esbuild from "esbuild";
import process from "process";
import builtins from "builtin-modules";
import replacePlugin from "esbuild-plugin-replace-regex";
import { readFileSync } from 'fs';
import { join } from 'path';
const patchStr = `
const os = require("os")
const arch = os.arch()
const platform = os.platform()
const libPath = app.vault.adapter.getFullPath(app.vault.configDir)
addon = DEFAULT_ADDON || (DEFAULT_ADDON = require(path.resolve(libPath, \`plugins/sqlseal/better_sqlite3-\${platform}-\${arch}.node\`)));
`;
const banner =
`/*
const banner = `/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
`;
const wasmPlugin = {
name: 'wasm',
setup(build) {
// Handle direct importing of wasm files
build.onResolve({ filter: /\.wasm$/ }, args => {
if (args.resolveDir === '') return;
return {
path: join(args.resolveDir, args.path),
namespace: 'wasm-binary',
};
});
// Load and encode the wasm file
build.onLoad({ filter: /\.wasm$/, namespace: 'wasm-binary' }, async (args) => {
const contents = readFileSync(args.path);
const wasmBase64 = contents.toString('base64');
return {
contents: `
const wasmBase64 = "${wasmBase64}";
const wasmBinary = Uint8Array.from(atob(wasmBase64), c => c.charCodeAt(0));
export default wasmBinary;
`,
loader: 'js',
};
});
},
};
const prod = (process.argv[2] === "production");
const context = await esbuild.context({
@ -40,7 +61,8 @@ const context = await esbuild.context({
"@lezer/common",
"@lezer/highlight",
"@lezer/lr",
...builtins],
...builtins
],
format: "cjs",
target: "es2018",
logLevel: "info",
@ -48,12 +70,7 @@ const context = await esbuild.context({
treeShaking: true,
outfile: "main.js",
plugins: [
replacePlugin({
filter: /.*/,
patterns: [
[/addon\s=\sDEFAULT_ADDON\s\|\|\s\(DEFAULT_ADDON\s=\srequire.*;/, patchStr]
]
})
wasmPlugin
]
});

View file

@ -1,11 +1,11 @@
{
"id": "sqlseal",
"name": "SQLSeal",
"version": "0.9.2",
"version": "0.10.0",
"minAppVersion": "0.15.0",
"description": "Use SQL in your notes to query your vault files and CSV content.",
"author": "hypersphere",
"authorUrl": "https://hypersphere.blog/",
"fundingUrl": "ko-fi.com/hypersphere",
"isDesktopOnly": true
"isDesktopOnly": false
}

9441
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,13 +1,13 @@
{
"name": "sqlseal",
"version": "0.9.2",
"version": "0.10.0",
"description": "A plugin for Obsidian that allows you to run SQL queries on your notes.",
"main": "main.js",
"scripts": {
"dev": "node esbuild.config.mjs",
"typecheck": "tsc -noEmit -skipLibCheck",
"build": " node esbuild.config.mjs production",
"build-grammar": "antlr4ts -o src/grammar -Dlanguage=TypeScript -visitor SqlSealLang.g4",
"build-grammar": "npx antlr4-tool -o src/grammar --visitor SqlSealLang.g4",
"version": "node version-bump.mjs && git add manifest.json versions.json",
"rebuild": "electron-rebuild -f -w better-sqlite3",
"docs:dev": "vitepress dev docs",
@ -20,20 +20,20 @@
"license": "MIT",
"devDependencies": {
"@jest/globals": "^29.7.0",
"@types/better-sqlite3": "^7.6.10",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.17.7",
"@types/node": "^22.5.0",
"@types/papaparse": "^5.3.14",
"@types/sql.js": "^1.4.9",
"@typescript-eslint/eslint-plugin": "5.29.0",
"@typescript-eslint/parser": "5.29.0",
"antlr4-tool": "^1.1.1",
"antlr4ts-cli": "0.5.0-alpha.4",
"builtin-modules": "3.3.0",
"electron": "^30.0.0",
"electron-rebuild": "^3.2.9",
"esbuild": "0.17.3",
"esbuild-plugin-replace": "^1.4.0",
"esbuild-plugin-replace-regex": "^0.0.2",
"jest": "^29.7.0",
"obsidian": "latest",
"prettier": "3.2.5",
@ -46,11 +46,14 @@
"dependencies": {
"@ag-grid-community/theming": "^32.3.2",
"ag-grid-community": "^32.3.2",
"antlr4ts": "0.5.0-alpha.4",
"better-sqlite3": "^11.2.1",
"antlr4": "^4.13.2",
"antlr4ts-browser": "0.5.0-alpha.4",
"antlr4ts-browser-cli": "0.5.0-alpha.7",
"json5": "^2.2.3",
"lodash": "^4.17.21",
"node-sql-parser": "^5.0.0",
"papaparse": "^5.4.1"
"papaparse": "^5.4.1",
"sql.js": "^1.12.0",
"util": "^0.12.5"
}
}

File diff suppressed because it is too large Load diff

View file

@ -36,10 +36,7 @@ export class SqlSealCodeblockHandler {
const frontmatter = resolveFrontmatter(ctx, this.app)
const renderSelect = async () => {
try {
const stmt = this.db.db.prepare(statement)
const columns = stmt.columns().map(column => column.name);
const data = stmt.all(frontmatter ?? {})
const { data, columns } = this.db.select(statement, frontmatter ?? {})
api.setGridOption('columnDefs', columns.map(c => ({ field: c })))
api.setGridOption('rowData', data)
api.setGridOption('loading', false)

View file

@ -1,4 +1,3 @@
import Database from "better-sqlite3"
import { App } from "obsidian"
import path from 'path'
import Papa from 'papaparse'
@ -8,6 +7,8 @@ import { dataToCamelCase, fetchBlobData, FieldTypes, predictJson, predictType, t
import os from 'os'
import fs from 'fs'
import { sanitise } from "./utils/sanitiseColumn"
import initSqlJs, { BindParams, Database, Statement } from 'sql.js'
import wasmBinary from '../node_modules/sql.js/dist/sql-wasm.wasm'
export interface FieldDefinition {
name: string;
@ -43,7 +44,8 @@ const formatData = (data: Record<string, any>) => {
export class SqlSealDatabase {
private savedDatabases: Record<string, any> = {}
db: Database.Database
db: Database
private SQL: initSqlJs.SqlJsStatic
private isConnected = false
private connectingPromise: Promise<void>;
private connectingPromiseResolve: (value: void | PromiseLike<void>) => void
@ -51,7 +53,6 @@ export class SqlSealDatabase {
}
async connect() {
if (this.isConnected) {
return Promise.resolve()
@ -64,47 +65,24 @@ export class SqlSealDatabase {
this.connectingPromise = new Promise((resolve) => {
this.connectingPromiseResolve = resolve
})
//@ts-ignore
// const dbPath = normalizePath(this.app.vault.adapter.basePath + '/' + this.app.vault.configDir + '/sqlseal.db')
const arch = os.arch()
const platform = os.platform()
const better_sql_version = 'v11.2.1'
const dbNodeFilePath = path.resolve(this.app.vault.adapter.basePath, this.app.vault.configDir, `plugins/sqlseal/better_sqlite3-${platform}-${arch}.node`)
// check if file "better_sqlite3.node" exists in the plugin folder, if not, download it from better sqlite release.
try {
if (!fs.existsSync(dbNodeFilePath)) {
const url = `https://github.com/h-sphere/bettersql3-builds/releases/download/processed-${better_sql_version}/better-sqlite3-${better_sql_version}-electron-v${process.versions.modules}-${platform}-${arch}.node`
await fetchBlobData(url, dbNodeFilePath)
}
await sleep(500)
const dbPath = path.resolve(this.app.vault.adapter.basePath, this.app.vault.configDir, `plugins/sqlseal/database.sqlite`)
this.db = new Database(dbPath, { verbose: this.verbose ? console.log : undefined })
this.SQL = await initSqlJs({
wasmBinary: wasmBinary
})
this.db = new this.SQL.Database()
await this.defineCustomFunctions()
this.isConnected = true
this.connectingPromiseResolve()
} catch (e) {
console.error(`Error while loading SQLSeal. Please reload Obsiidan. If it repeats, please create new issue on GitHub: https://github.com/h-sphere/sql-seal/issues . Please quote following parameters:
Architecture: ${arch}
Platform: ${platform}
Electron Version: ${process.versions.modules}
BetterSQLite Version: ${better_sql_version}
Error: ${e}
`, e)
console.error('Error initializing SQLite database:', e)
}
}
private async defineCustomFunctions() {
this.db.function('a', (href: string, name: string) => {
this.db.create_function('a', (href: string, name: string) => {
const linkObject = {
type: 'link',
href: href,
@ -113,7 +91,7 @@ export class SqlSealDatabase {
return `SQLSEALCUSTOM(${JSON.stringify(linkObject)})`;
});
this.db.function('a', (href: string) => {
this.db.create_function('a', (href: string) => {
const linkObject = {
type: 'link',
href: href,
@ -122,7 +100,7 @@ export class SqlSealDatabase {
return `SQLSEALCUSTOM(${JSON.stringify(linkObject)})`;
});
this.db.function('img', (href: string) => {
this.db.create_function('img', (href: string) => {
const imgObject = {
type: 'img',
href: href
@ -130,7 +108,7 @@ export class SqlSealDatabase {
return `SQLSEALCUSTOM(${JSON.stringify(imgObject)})`
})
this.db.function('img', (href: string, path: string) => {
this.db.create_function('img', (href: string, path: string) => {
const imgObject = {
type: 'img',
path,
@ -139,7 +117,7 @@ export class SqlSealDatabase {
return `SQLSEALCUSTOM(${JSON.stringify(imgObject)})`
})
this.db.function('checkbox', (val: string) => {
this.db.create_function('checkbox', (val: string) => {
const imgObject = {
type: 'checkbox',
value: val
@ -167,7 +145,7 @@ export class SqlSealDatabase {
async addNewColumns(name: string, data: Array<Record<string, unknown>>) {
const schema = await this.getSchema(data)
const currentSchema = this.db.prepare(`PRAGMA table_info(${name})`).all()
const currentSchema = this.toObjectsArray(this.db.prepare(`PRAGMA table_info(${name})`))
const currentFields = currentSchema.map((f: any) => f.name)
const newFields = Object.keys(schema).filter(f => !currentFields.includes(f))
@ -180,50 +158,43 @@ export class SqlSealDatabase {
alter.run()
}
private toObjectsArray(stmt: Statement) {
const ret = []
while(stmt.step()) {
ret.push(stmt.getAsObject())
}
return ret
}
private recordToBindParams(record: Record<string, unknown>) {
const bindParams = Object.fromEntries(Object.entries(record).map(([key, val]) => ([`@${key}`, val]))) as BindParams
return bindParams
}
updateData(name: string, data: Array<Record<string, unknown>>) {
const fields = Object.keys(data.reduce((acc, obj) => ({ ...acc, ...obj }), {}));
const update = this.db.prepare(`UPDATE ${name} SET ${fields.map((key: string) => `${key} = @${key}`).join(', ')} WHERE id = @id`);
const updateMany = this.db.transaction((pData: Array<Record<string, any>>) => {
pData.forEach(data => {
try {
update.run(formatData(data))
} catch (e) {
console.error(e)
}
})
data.forEach((d: Record<string, unknown>) => {
const stmt = this.db.prepare(`UPDATE ${name} SET ${fields.map((key: string) => `${key} = @${key}`).join(', ')} WHERE id = @id`)
stmt.run(this.recordToBindParams(d))
})
return updateMany(data)
}
deleteData(name: string, data: Array<Record<string, unknown>>, key: string = 'id') {
const deleteStmt = this.db.prepare(`DELETE FROM ${name} WHERE ${key} = @${key}`);
const deleteMany = this.db.transaction((pData: Array<Record<string, any>>) => {
pData.forEach(data => {
try {
deleteStmt.run(data)
} catch (e) {
console.error(e)
}
})
data.forEach(d => {
const stmt = this.db.prepare(`DELETE FROM ${name} WHERE ${key} = @${key}`);
stmt.run({
[`@${key}`]: d[key]
} as BindParams)
})
return deleteMany(data)
}
async insertData(name: string, inData: Array<Record<string, unknown>>) {
const insertMany = this.db.transaction((pData: Array<Record<string, any>>) => {
// FIXME: should we do this as a transaction or not?
pData.forEach(data => {
const columns = Object.keys(data)
const insert = this.db.prepare(`INSERT INTO ${name} (${columns.join(', ')}) VALUES (${columns.map((key: string) => '@' + key).join(', ')})`);
const d = formatData(data)
insert.run(d)
})
inData.forEach(d => {
const columns = Object.keys(d)
const insertStatement = this.db.prepare(`INSERT INTO ${name} (${columns.join(', ')}) VALUES (${columns.map((key: string) => '@' + key).join(', ')})`);
insertStatement.run(this.recordToBindParams(formatData(d)))
})
insertMany(inData)
}
dropTable(name: string) {
@ -292,6 +263,15 @@ export class SqlSealDatabase {
return name
}
select(statement: string, frontmatter: Record<string, unknown>) {
const stmt = this.db.prepare(statement)
stmt.bind(this.recordToBindParams(frontmatter ?? {}))
return {
data: this.toObjectsArray(stmt) as Record<string, any>[],
columns: stmt.getColumnNames()
}
}
/**
* @deprecated
* @param unprefixedName

File diff suppressed because one or more lines are too long

View file

@ -53,4 +53,4 @@ mode names:
DEFAULT_MODE
atn:
[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 2, 15, 82, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 7, 11, 66, 10, 11, 12, 11, 14, 11, 69, 11, 11, 3, 12, 6, 12, 72, 10, 12, 13, 12, 14, 12, 73, 3, 13, 6, 13, 77, 10, 13, 13, 13, 14, 13, 78, 3, 14, 3, 14, 2, 2, 2, 15, 3, 2, 3, 5, 2, 4, 7, 2, 5, 9, 2, 6, 11, 2, 7, 13, 2, 8, 15, 2, 9, 17, 2, 10, 19, 2, 11, 21, 2, 12, 23, 2, 13, 25, 2, 14, 27, 2, 15, 3, 2, 6, 5, 2, 67, 92, 97, 97, 99, 124, 6, 2, 50, 59, 67, 92, 97, 97, 99, 124, 7, 2, 47, 59, 67, 92, 94, 94, 97, 97, 99, 124, 5, 2, 11, 12, 15, 15, 34, 34, 2, 84, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 3, 29, 3, 2, 2, 2, 5, 31, 3, 2, 2, 2, 7, 33, 3, 2, 2, 2, 9, 35, 3, 2, 2, 2, 11, 37, 3, 2, 2, 2, 13, 43, 3, 2, 2, 2, 15, 48, 3, 2, 2, 2, 17, 53, 3, 2, 2, 2, 19, 56, 3, 2, 2, 2, 21, 63, 3, 2, 2, 2, 23, 71, 3, 2, 2, 2, 25, 76, 3, 2, 2, 2, 27, 80, 3, 2, 2, 2, 29, 30, 7, 63, 2, 2, 30, 4, 3, 2, 2, 2, 31, 32, 7, 42, 2, 2, 32, 6, 3, 2, 2, 2, 33, 34, 7, 43, 2, 2, 34, 8, 3, 2, 2, 2, 35, 36, 7, 46, 2, 2, 36, 10, 3, 2, 2, 2, 37, 38, 7, 86, 2, 2, 38, 39, 7, 67, 2, 2, 39, 40, 7, 68, 2, 2, 40, 41, 7, 78, 2, 2, 41, 42, 7, 71, 2, 2, 42, 12, 3, 2, 2, 2, 43, 44, 7, 104, 2, 2, 44, 45, 7, 107, 2, 2, 45, 46, 7, 110, 2, 2, 46, 47, 7, 103, 2, 2, 47, 14, 3, 2, 2, 2, 48, 49, 7, 89, 2, 2, 49, 50, 7, 75, 2, 2, 50, 51, 7, 86, 2, 2, 51, 52, 7, 74, 2, 2, 52, 16, 3, 2, 2, 2, 53, 54, 7, 67, 2, 2, 54, 55, 7, 85, 2, 2, 55, 18, 3, 2, 2, 2, 56, 57, 7, 85, 2, 2, 57, 58, 7, 71, 2, 2, 58, 59, 7, 78, 2, 2, 59, 60, 7, 71, 2, 2, 60, 61, 7, 69, 2, 2, 61, 62, 7, 86, 2, 2, 62, 20, 3, 2, 2, 2, 63, 67, 9, 2, 2, 2, 64, 66, 9, 3, 2, 2, 65, 64, 3, 2, 2, 2, 66, 69, 3, 2, 2, 2, 67, 65, 3, 2, 2, 2, 67, 68, 3, 2, 2, 2, 68, 22, 3, 2, 2, 2, 69, 67, 3, 2, 2, 2, 70, 72, 9, 4, 2, 2, 71, 70, 3, 2, 2, 2, 72, 73, 3, 2, 2, 2, 73, 71, 3, 2, 2, 2, 73, 74, 3, 2, 2, 2, 74, 24, 3, 2, 2, 2, 75, 77, 9, 5, 2, 2, 76, 75, 3, 2, 2, 2, 77, 78, 3, 2, 2, 2, 78, 76, 3, 2, 2, 2, 78, 79, 3, 2, 2, 2, 79, 26, 3, 2, 2, 2, 80, 81, 11, 2, 2, 2, 81, 28, 3, 2, 2, 2, 6, 2, 67, 73, 78, 2]
[4, 0, 13, 80, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 5, 9, 64, 8, 9, 10, 9, 12, 9, 67, 9, 9, 1, 10, 4, 10, 70, 8, 10, 11, 10, 12, 10, 71, 1, 11, 4, 11, 75, 8, 11, 11, 11, 12, 11, 76, 1, 12, 1, 12, 0, 0, 13, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 1, 0, 4, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 5, 0, 45, 57, 65, 90, 92, 92, 95, 95, 97, 122, 3, 0, 9, 10, 13, 13, 32, 32, 82, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 1, 27, 1, 0, 0, 0, 3, 29, 1, 0, 0, 0, 5, 31, 1, 0, 0, 0, 7, 33, 1, 0, 0, 0, 9, 35, 1, 0, 0, 0, 11, 41, 1, 0, 0, 0, 13, 46, 1, 0, 0, 0, 15, 51, 1, 0, 0, 0, 17, 54, 1, 0, 0, 0, 19, 61, 1, 0, 0, 0, 21, 69, 1, 0, 0, 0, 23, 74, 1, 0, 0, 0, 25, 78, 1, 0, 0, 0, 27, 28, 5, 61, 0, 0, 28, 2, 1, 0, 0, 0, 29, 30, 5, 40, 0, 0, 30, 4, 1, 0, 0, 0, 31, 32, 5, 41, 0, 0, 32, 6, 1, 0, 0, 0, 33, 34, 5, 44, 0, 0, 34, 8, 1, 0, 0, 0, 35, 36, 5, 84, 0, 0, 36, 37, 5, 65, 0, 0, 37, 38, 5, 66, 0, 0, 38, 39, 5, 76, 0, 0, 39, 40, 5, 69, 0, 0, 40, 10, 1, 0, 0, 0, 41, 42, 5, 102, 0, 0, 42, 43, 5, 105, 0, 0, 43, 44, 5, 108, 0, 0, 44, 45, 5, 101, 0, 0, 45, 12, 1, 0, 0, 0, 46, 47, 5, 87, 0, 0, 47, 48, 5, 73, 0, 0, 48, 49, 5, 84, 0, 0, 49, 50, 5, 72, 0, 0, 50, 14, 1, 0, 0, 0, 51, 52, 5, 65, 0, 0, 52, 53, 5, 83, 0, 0, 53, 16, 1, 0, 0, 0, 54, 55, 5, 83, 0, 0, 55, 56, 5, 69, 0, 0, 56, 57, 5, 76, 0, 0, 57, 58, 5, 69, 0, 0, 58, 59, 5, 67, 0, 0, 59, 60, 5, 84, 0, 0, 60, 18, 1, 0, 0, 0, 61, 65, 7, 0, 0, 0, 62, 64, 7, 1, 0, 0, 63, 62, 1, 0, 0, 0, 64, 67, 1, 0, 0, 0, 65, 63, 1, 0, 0, 0, 65, 66, 1, 0, 0, 0, 66, 20, 1, 0, 0, 0, 67, 65, 1, 0, 0, 0, 68, 70, 7, 2, 0, 0, 69, 68, 1, 0, 0, 0, 70, 71, 1, 0, 0, 0, 71, 69, 1, 0, 0, 0, 71, 72, 1, 0, 0, 0, 72, 22, 1, 0, 0, 0, 73, 75, 7, 3, 0, 0, 74, 73, 1, 0, 0, 0, 75, 76, 1, 0, 0, 0, 76, 74, 1, 0, 0, 0, 76, 77, 1, 0, 0, 0, 77, 24, 1, 0, 0, 0, 78, 79, 9, 0, 0, 0, 79, 26, 1, 0, 0, 0, 4, 0, 65, 71, 76, 0]

View file

@ -1,21 +1,17 @@
// Generated from SqlSealLang.g4 by ANTLR 4.9.0-SNAPSHOT
import { ATN } from "antlr4ts/atn/ATN";
import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer";
import { CharStream } from "antlr4ts/CharStream";
import { Lexer } from "antlr4ts/Lexer";
import { LexerATNSimulator } from "antlr4ts/atn/LexerATNSimulator";
import { NotNull } from "antlr4ts/Decorators";
import { Override } from "antlr4ts/Decorators";
import { RuleContext } from "antlr4ts/RuleContext";
import { Vocabulary } from "antlr4ts/Vocabulary";
import { VocabularyImpl } from "antlr4ts/VocabularyImpl";
import * as Utils from "antlr4ts/misc/Utils";
export class SqlSealLangLexer extends Lexer {
// Generated from SqlSealLang.g4 by ANTLR 4.13.2
// noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols
import {
ATN,
ATNDeserializer,
CharStream,
DecisionState, DFA,
Lexer,
LexerATNSimulator,
RuleContext,
PredictionContextCache,
Token
} from "antlr4";
export default class SqlSealLangLexer extends Lexer {
public static readonly T__0 = 1;
public static readonly T__1 = 2;
public static readonly T__2 = 3;
@ -29,103 +25,81 @@ export class SqlSealLangLexer extends Lexer {
public static readonly FILE_URL = 11;
public static readonly WS = 12;
public static readonly ANY = 13;
public static readonly EOF = Token.EOF;
// tslint:disable:no-trailing-whitespace
public static readonly channelNames: string[] = [
"DEFAULT_TOKEN_CHANNEL", "HIDDEN",
];
// tslint:disable:no-trailing-whitespace
public static readonly modeNames: string[] = [
"DEFAULT_MODE",
];
public static readonly channelNames: string[] = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN" ];
public static readonly literalNames: (string | null)[] = [ null, "'='",
"'('", "')'",
"','", "'TABLE'",
"'file'", "'WITH'",
"'AS'", "'SELECT'" ];
public static readonly symbolicNames: (string | null)[] = [ null, null,
null, null,
null, "TABLE",
"FILE", "WITH",
"AS", "SELECT",
"ID", "FILE_URL",
"WS", "ANY" ];
public static readonly modeNames: string[] = [ "DEFAULT_MODE", ];
public static readonly ruleNames: string[] = [
"T__0", "T__1", "T__2", "T__3", "TABLE", "FILE", "WITH", "AS", "SELECT",
"ID", "FILE_URL", "WS", "ANY",
];
private static readonly _LITERAL_NAMES: Array<string | undefined> = [
undefined, "'='", "'('", "')'", "','", "'TABLE'", "'file'", "'WITH'",
"'AS'", "'SELECT'",
];
private static readonly _SYMBOLIC_NAMES: Array<string | undefined> = [
undefined, undefined, undefined, undefined, undefined, "TABLE", "FILE",
"WITH", "AS", "SELECT", "ID", "FILE_URL", "WS", "ANY",
];
public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(SqlSealLangLexer._LITERAL_NAMES, SqlSealLangLexer._SYMBOLIC_NAMES, []);
// @Override
// @NotNull
public get vocabulary(): Vocabulary {
return SqlSealLangLexer.VOCABULARY;
}
// tslint:enable:no-trailing-whitespace
constructor(input: CharStream) {
super(input);
this._interp = new LexerATNSimulator(SqlSealLangLexer._ATN, this);
this._interp = new LexerATNSimulator(this, SqlSealLangLexer._ATN, SqlSealLangLexer.DecisionsToDFA, new PredictionContextCache());
}
// @Override
public get grammarFileName(): string { return "SqlSealLang.g4"; }
// @Override
public get literalNames(): (string | null)[] { return SqlSealLangLexer.literalNames; }
public get symbolicNames(): (string | null)[] { return SqlSealLangLexer.symbolicNames; }
public get ruleNames(): string[] { return SqlSealLangLexer.ruleNames; }
// @Override
public get serializedATN(): string { return SqlSealLangLexer._serializedATN; }
public get serializedATN(): number[] { return SqlSealLangLexer._serializedATN; }
// @Override
public get channelNames(): string[] { return SqlSealLangLexer.channelNames; }
// @Override
public get modeNames(): string[] { return SqlSealLangLexer.modeNames; }
public static readonly _serializedATN: string =
"\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x02\x0FR\b\x01\x04" +
"\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04" +
"\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r" +
"\x04\x0E\t\x0E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04\x03\x04\x03\x05" +
"\x03\x05\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x07\x03\x07" +
"\x03\x07\x03\x07\x03\x07\x03\b\x03\b\x03\b\x03\b\x03\b\x03\t\x03\t\x03" +
"\t\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\v\x03\v\x07\vB\n\v\f" +
"\v\x0E\vE\v\v\x03\f\x06\fH\n\f\r\f\x0E\fI\x03\r\x06\rM\n\r\r\r\x0E\rN" +
"\x03\x0E\x03\x0E\x02\x02\x02\x0F\x03\x02\x03\x05\x02\x04\x07\x02\x05\t" +
"\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t\x11\x02\n\x13\x02\v\x15\x02\f\x17" +
"\x02\r\x19\x02\x0E\x1B\x02\x0F\x03\x02\x06\x05\x02C\\aac|\x06\x022;C\\" +
"aac|\x07\x02/;C\\^^aac|\x05\x02\v\f\x0F\x0F\"\"\x02T\x02\x03\x03\x02\x02" +
"\x02\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02" +
"\x02\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02" +
"\x02\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x15\x03\x02\x02\x02" +
"\x02\x17\x03\x02\x02\x02\x02\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02" +
"\x03\x1D\x03\x02\x02\x02\x05\x1F\x03\x02\x02\x02\x07!\x03\x02\x02\x02" +
"\t#\x03\x02\x02\x02\v%\x03\x02\x02\x02\r+\x03\x02\x02\x02\x0F0\x03\x02" +
"\x02\x02\x115\x03\x02\x02\x02\x138\x03\x02\x02\x02\x15?\x03\x02\x02\x02" +
"\x17G\x03\x02\x02\x02\x19L\x03\x02\x02\x02\x1BP\x03\x02\x02\x02\x1D\x1E" +
"\x07?\x02\x02\x1E\x04\x03\x02\x02\x02\x1F \x07*\x02\x02 \x06\x03\x02\x02" +
"\x02!\"\x07+\x02\x02\"\b\x03\x02\x02\x02#$\x07.\x02\x02$\n\x03\x02\x02" +
"\x02%&\x07V\x02\x02&\'\x07C\x02\x02\'(\x07D\x02\x02()\x07N\x02\x02)*\x07" +
"G\x02\x02*\f\x03\x02\x02\x02+,\x07h\x02\x02,-\x07k\x02\x02-.\x07n\x02" +
"\x02./\x07g\x02\x02/\x0E\x03\x02\x02\x0201\x07Y\x02\x0212\x07K\x02\x02" +
"23\x07V\x02\x0234\x07J\x02\x024\x10\x03\x02\x02\x0256\x07C\x02\x0267\x07" +
"U\x02\x027\x12\x03\x02\x02\x0289\x07U\x02\x029:\x07G\x02\x02:;\x07N\x02" +
"\x02;<\x07G\x02\x02<=\x07E\x02\x02=>\x07V\x02\x02>\x14\x03\x02\x02\x02" +
"?C\t\x02\x02\x02@B\t\x03\x02\x02A@\x03\x02\x02\x02BE\x03\x02\x02\x02C" +
"A\x03\x02\x02\x02CD\x03\x02\x02\x02D\x16\x03\x02\x02\x02EC\x03\x02\x02" +
"\x02FH\t\x04\x02\x02GF\x03\x02\x02\x02HI\x03\x02\x02\x02IG\x03\x02\x02" +
"\x02IJ\x03\x02\x02\x02J\x18\x03\x02\x02\x02KM\t\x05\x02\x02LK\x03\x02" +
"\x02\x02MN\x03\x02\x02\x02NL\x03\x02\x02\x02NO\x03\x02\x02\x02O\x1A\x03" +
"\x02\x02\x02PQ\v\x02\x02\x02Q\x1C\x03\x02\x02\x02\x06\x02CIN\x02";
public static __ATN: ATN;
public static readonly _serializedATN: number[] = [4,0,13,80,6,-1,2,0,7,
0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,
9,2,10,7,10,2,11,7,11,2,12,7,12,1,0,1,0,1,1,1,1,1,2,1,2,1,3,1,3,1,4,1,4,
1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,7,1,8,
1,8,1,8,1,8,1,8,1,8,1,8,1,9,1,9,5,9,64,8,9,10,9,12,9,67,9,9,1,10,4,10,70,
8,10,11,10,12,10,71,1,11,4,11,75,8,11,11,11,12,11,76,1,12,1,12,0,0,13,1,
1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,1,0,4,3,0,
65,90,95,95,97,122,4,0,48,57,65,90,95,95,97,122,5,0,45,57,65,90,92,92,95,
95,97,122,3,0,9,10,13,13,32,32,82,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,
7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,
0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,1,27,1,0,0,0,3,29,
1,0,0,0,5,31,1,0,0,0,7,33,1,0,0,0,9,35,1,0,0,0,11,41,1,0,0,0,13,46,1,0,
0,0,15,51,1,0,0,0,17,54,1,0,0,0,19,61,1,0,0,0,21,69,1,0,0,0,23,74,1,0,0,
0,25,78,1,0,0,0,27,28,5,61,0,0,28,2,1,0,0,0,29,30,5,40,0,0,30,4,1,0,0,0,
31,32,5,41,0,0,32,6,1,0,0,0,33,34,5,44,0,0,34,8,1,0,0,0,35,36,5,84,0,0,
36,37,5,65,0,0,37,38,5,66,0,0,38,39,5,76,0,0,39,40,5,69,0,0,40,10,1,0,0,
0,41,42,5,102,0,0,42,43,5,105,0,0,43,44,5,108,0,0,44,45,5,101,0,0,45,12,
1,0,0,0,46,47,5,87,0,0,47,48,5,73,0,0,48,49,5,84,0,0,49,50,5,72,0,0,50,
14,1,0,0,0,51,52,5,65,0,0,52,53,5,83,0,0,53,16,1,0,0,0,54,55,5,83,0,0,55,
56,5,69,0,0,56,57,5,76,0,0,57,58,5,69,0,0,58,59,5,67,0,0,59,60,5,84,0,0,
60,18,1,0,0,0,61,65,7,0,0,0,62,64,7,1,0,0,63,62,1,0,0,0,64,67,1,0,0,0,65,
63,1,0,0,0,65,66,1,0,0,0,66,20,1,0,0,0,67,65,1,0,0,0,68,70,7,2,0,0,69,68,
1,0,0,0,70,71,1,0,0,0,71,69,1,0,0,0,71,72,1,0,0,0,72,22,1,0,0,0,73,75,7,
3,0,0,74,73,1,0,0,0,75,76,1,0,0,0,76,74,1,0,0,0,76,77,1,0,0,0,77,24,1,0,
0,0,78,79,9,0,0,0,79,26,1,0,0,0,4,0,65,71,76,0];
private static __ATN: ATN;
public static get _ATN(): ATN {
if (!SqlSealLangLexer.__ATN) {
SqlSealLangLexer.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(SqlSealLangLexer._serializedATN));
SqlSealLangLexer.__ATN = new ATNDeserializer().deserialize(SqlSealLangLexer._serializedATN);
}
return SqlSealLangLexer.__ATN;
}
}
static DecisionsToDFA = SqlSealLangLexer._ATN.decisionToState.map( (ds: DecisionState, index: number) => new DFA(ds, index) );
}

View file

@ -1,23 +1,23 @@
// Generated from SqlSealLang.g4 by ANTLR 4.9.0-SNAPSHOT
// Generated from SqlSealLang.g4 by ANTLR 4.13.2
import {ParseTreeListener} from "antlr4";
import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener";
import { ParseContext } from "./SqlSealLangParser";
import { StatementContext } from "./SqlSealLangParser";
import { TableStatementContext } from "./SqlSealLangParser";
import { QueryStatementContext } from "./SqlSealLangParser";
import { WithClauseContext } from "./SqlSealLangParser";
import { CteDefinitionContext } from "./SqlSealLangParser";
import { SelectStatementContext } from "./SqlSealLangParser";
import { SelectBodyContext } from "./SqlSealLangParser";
import { ParseContext } from "./SqlSealLangParser.js";
import { StatementContext } from "./SqlSealLangParser.js";
import { TableStatementContext } from "./SqlSealLangParser.js";
import { QueryStatementContext } from "./SqlSealLangParser.js";
import { WithClauseContext } from "./SqlSealLangParser.js";
import { CteDefinitionContext } from "./SqlSealLangParser.js";
import { SelectStatementContext } from "./SqlSealLangParser.js";
import { SelectBodyContext } from "./SqlSealLangParser.js";
/**
* This interface defines a complete listener for a parse tree produced by
* `SqlSealLangParser`.
*/
export interface SqlSealLangListener extends ParseTreeListener {
export default class SqlSealLangListener extends ParseTreeListener {
/**
* Enter a parse tree produced by `SqlSealLangParser.parse`.
* @param ctx the parse tree
@ -28,7 +28,6 @@ export interface SqlSealLangListener extends ParseTreeListener {
* @param ctx the parse tree
*/
exitParse?: (ctx: ParseContext) => void;
/**
* Enter a parse tree produced by `SqlSealLangParser.statement`.
* @param ctx the parse tree
@ -39,7 +38,6 @@ export interface SqlSealLangListener extends ParseTreeListener {
* @param ctx the parse tree
*/
exitStatement?: (ctx: StatementContext) => void;
/**
* Enter a parse tree produced by `SqlSealLangParser.tableStatement`.
* @param ctx the parse tree
@ -50,7 +48,6 @@ export interface SqlSealLangListener extends ParseTreeListener {
* @param ctx the parse tree
*/
exitTableStatement?: (ctx: TableStatementContext) => void;
/**
* Enter a parse tree produced by `SqlSealLangParser.queryStatement`.
* @param ctx the parse tree
@ -61,7 +58,6 @@ export interface SqlSealLangListener extends ParseTreeListener {
* @param ctx the parse tree
*/
exitQueryStatement?: (ctx: QueryStatementContext) => void;
/**
* Enter a parse tree produced by `SqlSealLangParser.withClause`.
* @param ctx the parse tree
@ -72,7 +68,6 @@ export interface SqlSealLangListener extends ParseTreeListener {
* @param ctx the parse tree
*/
exitWithClause?: (ctx: WithClauseContext) => void;
/**
* Enter a parse tree produced by `SqlSealLangParser.cteDefinition`.
* @param ctx the parse tree
@ -83,7 +78,6 @@ export interface SqlSealLangListener extends ParseTreeListener {
* @param ctx the parse tree
*/
exitCteDefinition?: (ctx: CteDefinitionContext) => void;
/**
* Enter a parse tree produced by `SqlSealLangParser.selectStatement`.
* @param ctx the parse tree
@ -94,7 +88,6 @@ export interface SqlSealLangListener extends ParseTreeListener {
* @param ctx the parse tree
*/
exitSelectStatement?: (ctx: SelectStatementContext) => void;
/**
* Enter a parse tree produced by `SqlSealLangParser.selectBody`.
* @param ctx the parse tree

File diff suppressed because it is too large Load diff

View file

@ -1,16 +1,16 @@
// Generated from SqlSealLang.g4 by ANTLR 4.9.0-SNAPSHOT
// Generated from SqlSealLang.g4 by ANTLR 4.13.2
import {ParseTreeVisitor} from 'antlr4';
import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor";
import { ParseContext } from "./SqlSealLangParser";
import { StatementContext } from "./SqlSealLangParser";
import { TableStatementContext } from "./SqlSealLangParser";
import { QueryStatementContext } from "./SqlSealLangParser";
import { WithClauseContext } from "./SqlSealLangParser";
import { CteDefinitionContext } from "./SqlSealLangParser";
import { SelectStatementContext } from "./SqlSealLangParser";
import { SelectBodyContext } from "./SqlSealLangParser";
import { ParseContext } from "./SqlSealLangParser.js";
import { StatementContext } from "./SqlSealLangParser.js";
import { TableStatementContext } from "./SqlSealLangParser.js";
import { QueryStatementContext } from "./SqlSealLangParser.js";
import { WithClauseContext } from "./SqlSealLangParser.js";
import { CteDefinitionContext } from "./SqlSealLangParser.js";
import { SelectStatementContext } from "./SqlSealLangParser.js";
import { SelectBodyContext } from "./SqlSealLangParser.js";
/**
@ -20,56 +20,49 @@ import { SelectBodyContext } from "./SqlSealLangParser";
* @param <Result> The return type of the visit operation. Use `void` for
* operations with no return type.
*/
export interface SqlSealLangVisitor<Result> extends ParseTreeVisitor<Result> {
export default class SqlSealLangVisitor<Result> extends ParseTreeVisitor<Result> {
/**
* Visit a parse tree produced by `SqlSealLangParser.parse`.
* @param ctx the parse tree
* @return the visitor result
*/
visitParse?: (ctx: ParseContext) => Result;
/**
* Visit a parse tree produced by `SqlSealLangParser.statement`.
* @param ctx the parse tree
* @return the visitor result
*/
visitStatement?: (ctx: StatementContext) => Result;
/**
* Visit a parse tree produced by `SqlSealLangParser.tableStatement`.
* @param ctx the parse tree
* @return the visitor result
*/
visitTableStatement?: (ctx: TableStatementContext) => Result;
/**
* Visit a parse tree produced by `SqlSealLangParser.queryStatement`.
* @param ctx the parse tree
* @return the visitor result
*/
visitQueryStatement?: (ctx: QueryStatementContext) => Result;
/**
* Visit a parse tree produced by `SqlSealLangParser.withClause`.
* @param ctx the parse tree
* @return the visitor result
*/
visitWithClause?: (ctx: WithClauseContext) => Result;
/**
* Visit a parse tree produced by `SqlSealLangParser.cteDefinition`.
* @param ctx the parse tree
* @return the visitor result
*/
visitCteDefinition?: (ctx: CteDefinitionContext) => Result;
/**
* Visit a parse tree produced by `SqlSealLangParser.selectStatement`.
* @param ctx the parse tree
* @return the visitor result
*/
visitSelectStatement?: (ctx: SelectStatementContext) => Result;
/**
* Visit a parse tree produced by `SqlSealLangParser.selectBody`.
* @param ctx the parse tree

View file

@ -1,8 +1,9 @@
import { ANTLRErrorListener, CharStreams, CommonTokenStream, RecognitionException, Recognizer } from 'antlr4ts';
import { SqlSealLangLexer } from './SqlSealLangLexer';
import { QueryStatementContext, TableStatementContext, SqlSealLangParser, ParseContext, StatementContext, WithClauseContext, SelectStatementContext } from './SqlSealLangParser';
import { SqlSealLangVisitor } from './SqlSealLangVisitor';
import { AbstractParseTreeVisitor } from 'antlr4ts/tree/AbstractParseTreeVisitor';
import { CommonTokenStream, ErrorListener, ParseTreeVisitor, RecognitionException } from 'antlr4';
import SqlSealLangLexer from './SqlSealLangLexer';
import { QueryStatementContext, TableStatementContext, ParseContext, StatementContext, WithClauseContext, SelectStatementContext } from './SqlSealLangParser';
import SqlSealLangParser from './SqlSealLangParser';
import SqlSealLangVisitor from './SqlSealLangVisitor';
import { CharStream, TokenStream } from 'antlr4';
export interface TableStatement {
name: string;
@ -17,10 +18,10 @@ export interface ParsedLanguage {
}
class ErrorListener implements ANTLRErrorListener<any> {
class SQLSealErrorListener extends ErrorListener<any> {
private errors: string[] = [];
syntaxError(recognizer: Recognizer<any, any>, offendingSymbol: any, line: number, charPositionInLine: number, msg: string, e: RecognitionException | undefined): void {
syntaxError(recognizer: any, offendingSymbol: any, line: number, charPositionInLine: number, msg: string, e: RecognitionException | undefined): void {
this.errors.push(`Line ${line}:${charPositionInLine} ${msg}`);
}
@ -31,9 +32,13 @@ class ErrorListener implements ANTLRErrorListener<any> {
getErrors(): string {
return this.errors.join('\n');
}
reportAttemtpingFullContext() {
}
}
export class SqlSealLangVisitorImpl extends AbstractParseTreeVisitor<ParsedLanguage> implements SqlSealLangVisitor<ParsedLanguage> {
export class SqlSealLangVisitorImpl extends ParseTreeVisitor<ParsedLanguage> implements SqlSealLangVisitor<ParsedLanguage> {
private tables: TableStatement[] = [];
private queryPart: string | null = null;
@ -42,7 +47,7 @@ export class SqlSealLangVisitorImpl extends AbstractParseTreeVisitor<ParsedLangu
}
visitParse(ctx: ParseContext): ParsedLanguage {
ctx.statement().forEach(stmt => this.visit(stmt));
ctx.statement_list().forEach(stmt => this.visit(stmt));
return this.defaultResult();
}
@ -56,11 +61,11 @@ export class SqlSealLangVisitorImpl extends AbstractParseTreeVisitor<ParsedLangu
}
visitTableStatement(ctx: TableStatementContext): ParsedLanguage {
const tableName = ctx.ID().text;
const fileUrl = ctx.FILE_URL().text;
const tableName = ctx.ID().getText();
const fileUrl = ctx.FILE_URL().getText();
// Reconstruct the original table statement with whitespace
const tableStmt = ctx.children!.map(child => child.text).join('');
const tableStmt = ctx.children!.map(child => child.getText()).join('');
this.tables.push({
name: tableName,
@ -73,7 +78,7 @@ export class SqlSealLangVisitorImpl extends AbstractParseTreeVisitor<ParsedLangu
visitQueryStatement(ctx: QueryStatementContext): ParsedLanguage {
// Reconstruct the original query statement with whitespace and all characters
this.queryPart = ctx.children!.map(child => child.text).join('');
this.queryPart = ctx.children!.map(child => child.getText()).join('');
return this.defaultResult();
}
@ -89,12 +94,16 @@ export class SqlSealLangVisitorImpl extends AbstractParseTreeVisitor<ParsedLangu
}
export function parseLanguage(input: string): ParsedLanguage {
const chars = CharStreams.fromString(input);
const lexer = new SqlSealLangLexer(chars);
const chars = new CharStream(input); // replace this with a FileStream as required
// const lexer = new MyGrammarLexer(chars);
// const tokens = new CommonTokenStream(lexer);
// const parser = new MyGrammarParser(tokens);
const lexer = new SqlSealLangLexer(new CharStream(input));
const tokens = new CommonTokenStream(lexer);
const parser = new SqlSealLangParser(tokens);
const errorListener = new ErrorListener();
const errorListener = new SQLSealErrorListener();
parser.removeErrorListeners();
parser.addErrorListener(errorListener);

View file

@ -38,15 +38,14 @@ export class SyncModel {
}
getSync(filename: string, tableName: string) {
const data = this.db.db.prepare(`
SELECT *
const { data } = this.db.select(`SELECT *
FROM sqlseal_sync
WHERE filename = @filename
AND name = @name
`).all({
filename: filename,
name: tableName,
})
AND name = @name`,
{
name: tableName,
filename: filename
})
if (data) {
return data[0] as SyncEntry
@ -55,6 +54,7 @@ export class SyncModel {
}
removeSync(filename: string, tableName: string) {
// FIXME: do not use exposed db, instead implement "exec" method inside the file.
this.db.db.prepare('DELETE FROM sqlseal_sync WHERE filename = :filename AND name = :name').run({
filename: filename,
name: tableName

View file

@ -8,7 +8,7 @@
"allowJs": true,
"noImplicitAny": true,
"moduleResolution": "node",
"importHelpers": true,
"importHelpers": false,
"isolatedModules": true,
"skipLibCheck": true,
"types": [],

View file

@ -10,5 +10,6 @@
"0.8.0": "0.15.0",
"0.9.0": "0.15.0",
"0.9.1": "0.15.0",
"0.9.2": "0.15.0"
"0.9.2": "0.15.0",
"0.10.0": "0.15.0"
}

4906
yarn.lock

File diff suppressed because it is too large Load diff