Skip to content

Commit

Permalink
Create PostgreSQL parser (#327)
Browse files Browse the repository at this point in the history
  • Loading branch information
loicknuchel authored Nov 9, 2024
1 parent 5f89bc9 commit 57feaf1
Show file tree
Hide file tree
Showing 21 changed files with 4,470 additions and 15 deletions.
4 changes: 2 additions & 2 deletions backend/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ config :azimutt,
azimutt_github_issues_new: "https://github.com/azimuttapp/azimutt/issues/new",
environment: config_env(),
# TODO: find an automated process to build it
version: "2.1.11",
version_date: "2024-10-15T00:00:00.000Z",
version: "2.1.12",
version_date: "2024-11-09T00:00:00.000Z",
commit_hash: System.cmd("git", ["log", "-1", "--pretty=format:%h"]) |> elem(0) |> String.trim(),
commit_message: System.cmd("git", ["log", "-1", "--pretty=format:%s"]) |> elem(0) |> String.trim(),
commit_date: System.cmd("git", ["log", "-1", "--pretty=format:%aI"]) |> elem(0) |> String.trim(),
Expand Down
2 changes: 1 addition & 1 deletion backend/lib/azimutt.ex
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ defmodule Azimutt do
%{id: "aml", name: "AML", parse: true, generate: true},
%{id: "dbml", name: "DBML", parse: false, generate: false},
%{id: "json", name: "JSON", parse: true, generate: true},
%{id: "postgres", name: "PostgreSQL", parse: false, generate: true},
%{id: "postgres", name: "PostgreSQL", parse: true, generate: true},
%{id: "mysql", name: "MySQL", parse: false, generate: false},
%{id: "oracle", name: "Oracle", parse: false, generate: false},
%{id: "sqlserver", name: "SQL Server", parse: false, generate: false},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ defmodule AzimuttWeb.Api.CleverCloudController do
end
end

def migrations(conn, params) do
def migrations(_conn, params) do
Logger.info("Api.CleverCloudController.migrations: #{inspect(params)}")
:ok
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script src="https://cdn.jsdelivr.net/npm/@azimutt/aml@0.1.8/out/bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@azimutt/parser-sql@0.1.1/out/bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@azimutt/parser-sql@0.1.2/out/bundle.min.js"></script>
<!--<script src="/elm/aml.min.js"></script>-->
<!--<script src="/elm/sql.min.js"></script>-->
<!--<script src="/elm/prisma.min.js"></script>-->
Expand Down Expand Up @@ -95,6 +95,7 @@
if (lang === 'aml') return aml.parseAml(content)
if (lang === 'amlv1') return aml.parseAml(content).mapError(errs => errs.filter(e => e.kind !== 'LegacySyntax'))
if (lang === 'json') return aml.parseJsonDatabase(content)
if (lang === 'postgres') return sql.parseSql(content, 'postgres')
return {errors: [{message: 'Unsupported source dialect: ' + lang, kind: 'UnsupportedDialect', level: 'error', offset: {start: 0, end: 100}, position: {start: {line: 1, column: 1}, end: {line: 10, column: 10}}}]}
} catch (e) {
return {errors: [{message: 'Failed to parse ' + lang + (e && e.message ? ': ' + e.message : ''), kind: 'DialectError', level: 'error', offset: {start: 0, end: 100}, position: {start: {line: 1, column: 1}, end: {line: 10, column: 10}}}]}
Expand Down
2 changes: 1 addition & 1 deletion libs/aml/resources/full.aml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ type slug | anonymous type
type uid int {tags: [generic]} # alias type
type cms.post_status (draft, published, archived) # enum type
type position {x int, y int} # struct type
type box `(INTERNALLENGTH = 16, INPUT = lower, OUTPUT = lower)` # custom type
type box `(INPUT = lower, OUTPUT = lower, INTERNALLENGTH = 16)` # custom type

namespace social.

Expand Down
2 changes: 1 addition & 1 deletion libs/aml/resources/full.json
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@
{"name": "uid", "alias": "int", "extra": {"line": 79, "statement": 15, "tags": ["generic"], "comment": "alias type"}},
{"schema": "cms", "name": "post_status", "values": ["draft", "published", "archived"], "extra": {"line": 80, "statement": 16, "comment": "enum type"}},
{"name": "position", "attrs": [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}], "extra": {"line": 81, "statement": 17, "comment": "struct type"}},
{"name": "box", "definition": "(INTERNALLENGTH = 16, INPUT = lower, OUTPUT = lower)", "extra": {"line": 82, "statement": 18, "comment": "custom type"}}
{"name": "box", "definition": "(INPUT = lower, OUTPUT = lower, INTERNALLENGTH = 16)", "extra": {"line": 82, "statement": 18, "comment": "custom type"}}
],
"extra": {
"comments": [{"line": 1, "comment": ""}, {"line": 2, "comment": "Full Schema AML"}, {"line": 3, "comment": ""}],
Expand Down
2 changes: 1 addition & 1 deletion libs/aml/resources/full.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ STRUCT:

### box

EXPRESSION: (INTERNALLENGTH = 16, INPUT = lower, OUTPUT = lower)
EXPRESSION: (INPUT = lower, OUTPUT = lower, INTERNALLENGTH = 16)

## Diagram

Expand Down
2 changes: 1 addition & 1 deletion libs/aml/src/amlParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ function tokenPosition(token: IToken): TokenPosition {
}

function pos(value: number | undefined): number {
return value !== undefined && !isNaN(value) ? value : defaultPos
return value !== undefined && !Number.isNaN(value) ? value : defaultPos
}

// utils functions
Expand Down
6 changes: 3 additions & 3 deletions libs/models/src/parserResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const tokenPosition = (offsetStart: number, offsetEnd: number, positionSt
({offset: {start: offsetStart, end: offsetEnd}, position: {start: {line: positionStartLine, column: positionStartColumn}, end: {line: positionEndLine, column: positionEndColumn}}})

export const mergePositions = (positions: (TokenPosition | undefined)[]): TokenPosition => {
const pos: TokenPosition[] = positions.filter(isNotUndefined)
const pos: TokenPosition[] = positions.filter(isNotUndefined).filter(p => !!p.offset)
return ({
offset: {start: posStart(pos.map(p => p.offset.start)), end: posEnd(pos.map(p => p.offset.end))},
position: {
Expand All @@ -84,11 +84,11 @@ export const positionEndAdd = <T extends TokenPosition>(pos: T, value: number):
})

const posStart = (values: number[]): number => {
const valid = values.filter(n => n >= 0 && !isNaN(n) && isFinite(n))
const valid = values.filter(n => n >= 0 && !Number.isNaN(n) && Number.isFinite(n))
return valid.length > 0 ? Math.min(...valid) : 0
}

const posEnd = (values: number[]): number => {
const valid = values.filter(n => n >= 0 && !isNaN(n) && isFinite(n))
const valid = values.filter(n => n >= 0 && !Number.isNaN(n) && Number.isFinite(n))
return valid.length > 0 ? Math.max(...valid) : 0
}
2 changes: 1 addition & 1 deletion libs/parser-sql/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@azimutt/parser-sql",
"version": "0.1.1",
"version": "0.1.2",
"description": "Parse and Generate SQL.",
"keywords": [],
"homepage": "https://azimutt.app",
Expand Down
28 changes: 28 additions & 0 deletions libs/parser-sql/resources/complex.postgres.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
--
-- A file with several statements more or less complex to check the parser is works fine.
-- They don't make sense for a particular db ^^
--

/*
* first query
* Author: Loïc
*/
select id /* primary key */, name
from users -- table
where role = 'admin';

DROP TABLE IF EXISTS users, public.posts CASCADE;

CREATE TABLE users (
id int PRIMARY KEY,
first_name varchar NOT NULL,
last_name varchar NOT NULL,
CONSTRAINT name_uniq UNIQUE (first_name, last_name),
email varchar UNIQUE CHECK ( email LIKE '%@%' ),
role varchar DEFAULT 'guest'
);

CREATE TABLE public.posts (
id int PRIMARY KEY,
author int CONSTRAINT posts_author_fk REFERENCES users(id)
);
2 changes: 1 addition & 1 deletion libs/parser-sql/resources/full.postgres.sql
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ COMMENT ON TYPE slug IS 'anonymous type';
-- CREATE TYPE uid AS int; -- type alias not supported on PostgreSQL
CREATE TYPE cms.post_status AS ENUM ('draft', 'published', 'archived');
CREATE TYPE position AS (x int, y int);
CREATE TYPE box (INTERNALLENGTH = 16, INPUT = lower, OUTPUT = lower);
CREATE TYPE box (INPUT = lower, OUTPUT = lower, INTERNALLENGTH = 16);

--
-- Full Schema AML
Expand Down
4 changes: 4 additions & 0 deletions libs/parser-sql/src/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import {ParserError, ParserErrorLevel, TokenPosition} from "@azimutt/models";

export const duplicated = (name: string, definedAtLine: number | undefined, position: TokenPosition): ParserError =>
({message: `${name} already defined${definedAtLine !== undefined ? ` at line ${definedAtLine}` : ''}`, kind: 'Duplicated', level: ParserErrorLevel.enum.warning, offset: position.offset, position: position.position})
Loading

0 comments on commit 57feaf1

Please sign in to comment.