Skip to content

Commit 8151d82

Browse files
committed
Improve Create Type
1 parent 68d52b3 commit 8151d82

File tree

7 files changed

+55
-31
lines changed

7 files changed

+55
-31
lines changed

libs/aml/resources/full.aml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ type slug | anonymous type
7979
type uid int {tags: [generic]} # alias type
8080
type cms.post_status (draft, published, archived) # enum type
8181
type position {x int, y int} # struct type
82-
type box `(INTERNALLENGTH = 16, INPUT = lower, OUTPUT = lower)` # custom type
82+
type box `(INPUT = lower, OUTPUT = lower, INTERNALLENGTH = 16)` # custom type
8383

8484
namespace social.
8585

libs/aml/resources/full.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@
224224
{"name": "uid", "alias": "int", "extra": {"line": 79, "statement": 15, "tags": ["generic"], "comment": "alias type"}},
225225
{"schema": "cms", "name": "post_status", "values": ["draft", "published", "archived"], "extra": {"line": 80, "statement": 16, "comment": "enum type"}},
226226
{"name": "position", "attrs": [{"name": "x", "type": "int"}, {"name": "y", "type": "int"}], "extra": {"line": 81, "statement": 17, "comment": "struct type"}},
227-
{"name": "box", "definition": "(INTERNALLENGTH = 16, INPUT = lower, OUTPUT = lower)", "extra": {"line": 82, "statement": 18, "comment": "custom type"}}
227+
{"name": "box", "definition": "(INPUT = lower, OUTPUT = lower, INTERNALLENGTH = 16)", "extra": {"line": 82, "statement": 18, "comment": "custom type"}}
228228
],
229229
"extra": {
230230
"comments": [{"line": 1, "comment": ""}, {"line": 2, "comment": "Full Schema AML"}, {"line": 3, "comment": ""}],

libs/aml/resources/full.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ STRUCT:
165165

166166
### box
167167

168-
EXPRESSION: (INTERNALLENGTH = 16, INPUT = lower, OUTPUT = lower)
168+
EXPRESSION: (INPUT = lower, OUTPUT = lower, INTERNALLENGTH = 16)
169169

170170
## Diagram
171171

libs/parser-sql/resources/full.postgres.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ COMMENT ON TYPE slug IS 'anonymous type';
1616
-- CREATE TYPE uid AS int; -- type alias not supported on PostgreSQL
1717
CREATE TYPE cms.post_status AS ENUM ('draft', 'published', 'archived');
1818
CREATE TYPE position AS (x int, y int);
19-
CREATE TYPE box (INTERNALLENGTH = 16, INPUT = lower, OUTPUT = lower);
19+
CREATE TYPE box (INPUT = lower, OUTPUT = lower, INTERNALLENGTH = 16);
2020

2121
--
2222
-- Full Schema AML

libs/parser-sql/src/postgresAst.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export type CommentStatementAst = { kind: 'Comment', object: { kind: CommentObje
1616
export type CreateExtensionStatementAst = { kind: 'CreateExtension', ifNotExists?: TokenInfo, name: IdentifierAst, with?: TokenInfo, schema?: {name: IdentifierAst} & TokenInfo, version?: {number: StringAst | IdentifierAst} & TokenInfo, cascade?: TokenInfo } & TokenInfo
1717
export type CreateIndexStatementAst = { kind: 'CreateIndex', unique?: TokenInfo, concurrently?: TokenInfo, ifNotExists?: TokenInfo, index?: IdentifierAst, only?: TokenInfo, schema?: IdentifierAst, table: IdentifierAst, using?: {method: IdentifierAst} & TokenInfo, columns: IndexColumnAst[], include?: {columns: IdentifierAst[]} & TokenInfo, where?: {predicate: ExpressionAst} & TokenInfo } & TokenInfo
1818
export type CreateTableStatementAst = { kind: 'CreateTable', schema?: IdentifierAst, table: IdentifierAst, columns: TableColumnAst[], constraints?: TableConstraintAst[] } & TokenInfo
19-
export type CreateTypeStatementAst = { kind: 'CreateType', schema?: IdentifierAst, type: IdentifierAst, struct?: {attrs: TypeColumnAst[]} & TokenInfo, enum?: {values: StringAst[]} & TokenInfo } & TokenInfo
19+
export type CreateTypeStatementAst = { kind: 'CreateType', schema?: IdentifierAst, type: IdentifierAst, struct?: {attrs: TypeColumnAst[]} & TokenInfo, enum?: {values: StringAst[]} & TokenInfo, base?: {name: IdentifierAst, value: ExpressionAst}[] } & TokenInfo
2020
export type DropStatementAst = { kind: 'Drop', object: { kind: DropObject } & TokenInfo, entities: TableRefAst[], concurrently?: TokenInfo, ifExists?: TokenInfo, mode?: { kind: DropMode } & TokenInfo } & TokenInfo
2121
export type InsertIntoStatementAst = { kind: 'InsertInto', schema?: IdentifierAst, table: IdentifierAst, columns?: IdentifierAst[], values: (ExpressionAst | { kind: 'Default' } & TokenInfo)[][], returning?: SelectClauseAst } & TokenInfo
2222
export type SelectStatementAst = { kind: 'Select', select: SelectClauseAst, from?: FromClauseAst, where?: WhereClauseAst } & TokenInfo

libs/parser-sql/src/postgresParser.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,19 @@ describe('postgresParser', () => {
240240
...token(0, 56)
241241
}]}})
242242
})
243+
// TODO: range
244+
test('base', () => {
245+
expect(parsePostgresAst("CREATE TYPE box (INPUT = my_box_in_function, OUTPUT = my_box_out_function, INTERNALLENGTH = 16);")).toEqual({result: {statements: [{
246+
kind: 'CreateType',
247+
type: identifier('box', 12, 14),
248+
base: [
249+
{name: identifier('INPUT', 17, 21), value: {column: identifier('my_box_in_function', 25, 42)}}, // FIXME: expressions should be different here (identifier instead of column)
250+
{name: identifier('OUTPUT', 45, 50), value: {column: identifier('my_box_out_function', 54, 72)}},
251+
{name: identifier('INTERNALLENGTH', 75, 88), value: integer(16, 92, 93)},
252+
],
253+
...token(0, 95)
254+
}]}})
255+
})
243256
})
244257
describe('dropStatement', () => {
245258
test('simplest', () => {

libs/parser-sql/src/postgresParser.ts

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -366,32 +366,12 @@ class PostgresParser extends EmbeddedActionsParser {
366366
const start = $.CONSUME(Create)
367367
$.CONSUME(Type)
368368
const table = $.SUBRULE($.tableRefRule)
369-
const content = $.OPTION(() => {
370-
const as = $.CONSUME(As)
371-
return $.OR([
372-
{ALT: () => {
373-
$.CONSUME(ParenLeft)
374-
const attrs: TypeColumnAst[] = []
375-
$.AT_LEAST_ONE_SEP({SEP: Comma, DEF: () => attrs.push(removeUndefined({
376-
name: $.SUBRULE($.identifierRule),
377-
type: $.SUBRULE($.columnTypeRule),
378-
collation: $.OPTION2(() => ({...tokenInfo($.CONSUME(Collate)), name: $.SUBRULE2($.identifierRule)}))
379-
}))})
380-
$.CONSUME(ParenRight)
381-
return {struct: {...tokenInfo(as), attrs: attrs.filter(isNotUndefined)}}
382-
}},
383-
{ALT: () => {
384-
const token = tokenInfo2(as, $.CONSUME(Enum))
385-
$.CONSUME2(ParenLeft)
386-
const values: StringAst[] = []
387-
$.AT_LEAST_ONE_SEP2({SEP: Comma, DEF: () => values.push($.SUBRULE($.stringRule))})
388-
$.CONSUME2(ParenRight)
389-
return {enum: {...token, values: values.filter(isNotUndefined)}}
390-
}},
391-
// TODO: RANGE
392-
// TODO: function
393-
])
394-
})
369+
const content = $.OPTION(() => $.OR([
370+
{ALT: () => ({struct: {...tokenInfo($.CONSUME(As)), attrs: $.SUBRULE(createTypeStructAttrs)}})},
371+
{ALT: () => ({enum: {...tokenInfo2($.CONSUME2(As), $.CONSUME(Enum)), values: $.SUBRULE(createTypeEnumValues)}})},
372+
// TODO: RANGE
373+
{ALT: () => ({base: $.SUBRULE(createTypeBase)})}
374+
]))
395375
const end = $.CONSUME(Semicolon)
396376
return removeEmpty({kind: 'CreateType' as const, schema: table.schema, type: table.table, ...content, ...tokenInfo2(start, end)})
397377
})
@@ -621,6 +601,37 @@ class PostgresParser extends EmbeddedActionsParser {
621601
return removeUndefined({kind: 'ForeignKey' as const, ...tokenInfo(token), columns, ref, onUpdate, onDelete, constraint})
622602
})
623603

604+
const createTypeStructAttrs = $.RULE<() => TypeColumnAst[]>('createTypeStructAttrs', () => {
605+
$.CONSUME(ParenLeft)
606+
const attrs: TypeColumnAst[] = []
607+
$.AT_LEAST_ONE_SEP({SEP: Comma, DEF: () => attrs.push(removeUndefined({
608+
name: $.SUBRULE($.identifierRule),
609+
type: $.SUBRULE($.columnTypeRule),
610+
collation: $.OPTION(() => ({...tokenInfo($.CONSUME(Collate)), name: $.SUBRULE2($.identifierRule)}))
611+
}))})
612+
$.CONSUME(ParenRight)
613+
return attrs.filter(isNotUndefined)
614+
})
615+
const createTypeEnumValues = $.RULE<() => StringAst[]>('createTypeEnumValues', () => {
616+
$.CONSUME(ParenLeft)
617+
const values: StringAst[] = []
618+
$.AT_LEAST_ONE_SEP({SEP: Comma, DEF: () => values.push($.SUBRULE($.stringRule))})
619+
$.CONSUME(ParenRight)
620+
return values
621+
})
622+
const createTypeBase = $.RULE<() => {name: IdentifierAst, value: ExpressionAst}[]>('createTypeBase', () => {
623+
$.CONSUME(ParenLeft)
624+
const params: {name: IdentifierAst, value: ExpressionAst}[] = []
625+
$.AT_LEAST_ONE_SEP({SEP: Comma, DEF: () => {
626+
const name = $.SUBRULE($.identifierRule)
627+
$.CONSUME(Equal)
628+
const value = $.SUBRULE($.expressionRule)
629+
params.push({name, value})
630+
}})
631+
$.CONSUME(ParenRight)
632+
return params
633+
})
634+
624635
const constraintNameRule = $.RULE<() => ConstraintNameAst>('constraintNameRule', () => {
625636
const token = $.CONSUME(Constraint)
626637
const name = $.SUBRULE($.identifierRule)

0 commit comments

Comments
 (0)