grammar: add column constraints

This commit is contained in:
Dmitriy Pleshevskiy 2023-01-07 02:13:17 +03:00
parent 0f7f6211db
commit 8a50f066ab
Signed by: pleshevskiy
GPG key ID: 1B59187B161C0215
6 changed files with 2994 additions and 1721 deletions

View file

@ -25,19 +25,45 @@ module.exports = grammar({
optional($._if_not_exists), optional($._if_not_exists),
$.table_reference, $.table_reference,
$.column_definitions $.column_definitions
// TODO: INHERITS
// TODO: PARTITION BY
// TODO: USING
// TODO: WITH
// TODO: ON COMMIT
// TODO: TABLESPACE
), ),
column_definitions: ($) => column_definitions: ($) =>
seq( seq(
"(", "(",
optional(commaSepRepeat1(choice($.column_definition /*$.constraint*/))), optional(
commaSepRepeat1(choice($.column_definition /*, $.table_constraint*/))
),
")" ")"
), ),
column_definition: ($) => column_definition: ($) =>
seq(field("name", $.identifier), field("datatype", $._type)), seq(
field("name", $.identifier),
field("datatype", $._type),
repeat($.column_constraint)
),
//constraint: $ => seq(), column_constraint: ($) =>
seq(
optional(seq($.keyword_constraint, field("name", $.identifier))),
choice(
$._not_null,
$.keyword_null,
seq($.keyword_default, $._expression)
// TODO: CHECK
// TODO: GENERATED
// TODO: UNIQUE
// TODO: PRIMARY KEY
// TODO: FOREIGN KEY
)
// TODO: DEFERRABLE
),
table_reference: ($) => table_reference: ($) =>
seq( seq(
@ -45,8 +71,24 @@ module.exports = grammar({
field("name", $.identifier) field("name", $.identifier)
), ),
_expression: ($) =>
choice(
$.literal
// TODO: add more types
),
literal: ($) =>
choice(
$._number,
$._literal_string,
$.keyword_true,
$.keyword_false,
$.keyword_null
),
// keywords // keywords
_if_not_exists: ($) => seq($.keyword_if, $.keyword_not, $.keyword_exists), _if_not_exists: ($) => seq($.keyword_if, $.keyword_not, $.keyword_exists),
_not_null: ($) => seq($.keyword_not, $.keyword_null),
keyword_create: (_) => mkKeyword("create"), keyword_create: (_) => mkKeyword("create"),
keyword_table: (_) => mkKeyword("table"), keyword_table: (_) => mkKeyword("table"),
@ -55,6 +97,11 @@ module.exports = grammar({
keyword_if: (_) => mkKeyword("if"), keyword_if: (_) => mkKeyword("if"),
keyword_not: (_) => mkKeyword("not"), keyword_not: (_) => mkKeyword("not"),
keyword_exists: (_) => mkKeyword("exists"), keyword_exists: (_) => mkKeyword("exists"),
keyword_null: (_) => mkKeyword("null"),
keyword_constraint: (_) => mkKeyword("constraint"),
keyword_default: (_) => mkKeyword("default"),
keyword_true: (_) => mkKeyword("true"),
keyword_false: (_) => mkKeyword("false"),
// References: https://www.postgresql.org/docs/15/datatype.html // References: https://www.postgresql.org/docs/15/datatype.html
_type: ($) => _type: ($) =>
@ -177,10 +224,8 @@ module.exports = grammar({
seq(mkKeyword("timestamp"), $._with_time_zone) seq(mkKeyword("timestamp"), $._with_time_zone)
), ),
_without_time_zone: ($) => seq($._keyword_without, $._keyword_time_zone), _without_time_zone: ($) => seq(mkKeyword("without"), $._keyword_time_zone),
_with_time_zone: ($) => seq($._keyword_with, $._keyword_time_zone), _with_time_zone: ($) => seq(mkKeyword("with"), $._keyword_time_zone),
_keyword_without: (_) => mkKeyword("without"),
_keyword_with: (_) => mkKeyword("with"),
_keyword_time_zone: (_) => seq(mkKeyword("time"), mkKeyword("zone")), _keyword_time_zone: (_) => seq(mkKeyword("time"), mkKeyword("zone")),
// References: https://www.postgresql.org/docs/15/datatype-uuid.html // References: https://www.postgresql.org/docs/15/datatype-uuid.html
@ -198,9 +243,10 @@ module.exports = grammar({
// https://stackoverflow.com/questions/13014947/regex-to-match-a-c-style-multiline-comment // https://stackoverflow.com/questions/13014947/regex-to-match-a-c-style-multiline-comment
marginalia: (_) => seq("/*", /[^*]*\*+(?:[^/*][^*]*\*+)*/, "/"), marginalia: (_) => seq("/*", /[^*]*\*+(?:[^/*][^*]*\*+)*/, "/"),
_literal_string: ($) => choice(seq("'", /[^']*/, "'")),
_number: (_) => /\d+/, _number: (_) => /\d+/,
identifier: ($) => choice($._identifier, seq('"', $._identifier, '"')), identifier: ($) => choice($._identifier, seq('"', /[^"]+/, '"')),
_identifier: (_) => /([a-zA-Z_][0-9a-zA-Z_]*)/, _identifier: (_) => /([a-zA-Z_][0-9a-zA-Z_]*)/,
}, },

View file

@ -181,6 +181,69 @@
"type": "SYMBOL", "type": "SYMBOL",
"name": "_type" "name": "_type"
} }
},
{
"type": "REPEAT",
"content": {
"type": "SYMBOL",
"name": "column_constraint"
}
}
]
},
"column_constraint": {
"type": "SEQ",
"members": [
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "keyword_constraint"
},
{
"type": "FIELD",
"name": "name",
"content": {
"type": "SYMBOL",
"name": "identifier"
}
}
]
},
{
"type": "BLANK"
}
]
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_not_null"
},
{
"type": "SYMBOL",
"name": "keyword_null"
},
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "keyword_default"
},
{
"type": "SYMBOL",
"name": "_expression"
}
]
}
]
} }
] ]
}, },
@ -222,6 +285,40 @@
} }
] ]
}, },
"_expression": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "literal"
}
]
},
"literal": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_number"
},
{
"type": "SYMBOL",
"name": "_literal_string"
},
{
"type": "SYMBOL",
"name": "keyword_true"
},
{
"type": "SYMBOL",
"name": "keyword_false"
},
{
"type": "SYMBOL",
"name": "keyword_null"
}
]
},
"_if_not_exists": { "_if_not_exists": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
@ -239,6 +336,19 @@
} }
] ]
}, },
"_not_null": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "keyword_not"
},
{
"type": "SYMBOL",
"name": "keyword_null"
}
]
},
"keyword_create": { "keyword_create": {
"type": "PATTERN", "type": "PATTERN",
"value": "create|CREATE" "value": "create|CREATE"
@ -276,6 +386,26 @@
"type": "PATTERN", "type": "PATTERN",
"value": "exists|EXISTS" "value": "exists|EXISTS"
}, },
"keyword_null": {
"type": "PATTERN",
"value": "null|NULL"
},
"keyword_constraint": {
"type": "PATTERN",
"value": "constraint|CONSTRAINT"
},
"keyword_default": {
"type": "PATTERN",
"value": "default|DEFAULT"
},
"keyword_true": {
"type": "PATTERN",
"value": "true|TRUE"
},
"keyword_false": {
"type": "PATTERN",
"value": "false|FALSE"
},
"_type": { "_type": {
"type": "CHOICE", "type": "CHOICE",
"members": [ "members": [
@ -938,8 +1068,8 @@
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "SYMBOL", "type": "PATTERN",
"name": "_keyword_without" "value": "without|WITHOUT"
}, },
{ {
"type": "SYMBOL", "type": "SYMBOL",
@ -951,8 +1081,8 @@
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
{ {
"type": "SYMBOL", "type": "PATTERN",
"name": "_keyword_with" "value": "with|WITH"
}, },
{ {
"type": "SYMBOL", "type": "SYMBOL",
@ -960,14 +1090,6 @@
} }
] ]
}, },
"_keyword_without": {
"type": "PATTERN",
"value": "without|WITHOUT"
},
"_keyword_with": {
"type": "PATTERN",
"value": "with|WITH"
},
"_keyword_time_zone": { "_keyword_time_zone": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
@ -1027,6 +1149,28 @@
} }
] ]
}, },
"_literal_string": {
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "'"
},
{
"type": "PATTERN",
"value": "[^']*"
},
{
"type": "STRING",
"value": "'"
}
]
}
]
},
"_number": { "_number": {
"type": "PATTERN", "type": "PATTERN",
"value": "\\d+" "value": "\\d+"
@ -1046,8 +1190,8 @@
"value": "\"" "value": "\""
}, },
{ {
"type": "SYMBOL", "type": "PATTERN",
"name": "_identifier" "value": "[^\"]+"
}, },
{ {
"type": "STRING", "type": "STRING",

View file

@ -25,6 +25,48 @@
] ]
} }
}, },
{
"type": "column_constraint",
"named": true,
"fields": {
"name": {
"multiple": false,
"required": false,
"types": [
{
"type": "identifier",
"named": true
}
]
}
},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "keyword_constraint",
"named": true
},
{
"type": "keyword_default",
"named": true
},
{
"type": "keyword_not",
"named": true
},
{
"type": "keyword_null",
"named": true
},
{
"type": "literal",
"named": true
}
]
}
},
{ {
"type": "column_definition", "type": "column_definition",
"named": true, "named": true,
@ -137,6 +179,16 @@
} }
] ]
} }
},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "column_constraint",
"named": true
}
]
} }
}, },
{ {
@ -282,6 +334,29 @@
"named": true, "named": true,
"fields": {} "fields": {}
}, },
{
"type": "literal",
"named": true,
"fields": {},
"children": {
"multiple": false,
"required": false,
"types": [
{
"type": "keyword_false",
"named": true
},
{
"type": "keyword_null",
"named": true
},
{
"type": "keyword_true",
"named": true
}
]
}
},
{ {
"type": "marginalia", "type": "marginalia",
"named": true, "named": true,
@ -409,6 +484,10 @@
"type": "\"", "type": "\"",
"named": false "named": false
}, },
{
"type": "'",
"named": false
},
{ {
"type": "(", "type": "(",
"named": false "named": false
@ -457,6 +536,10 @@
"type": "keyword_bytea", "type": "keyword_bytea",
"named": true "named": true
}, },
{
"type": "keyword_constraint",
"named": true
},
{ {
"type": "keyword_create", "type": "keyword_create",
"named": true "named": true
@ -473,10 +556,18 @@
"type": "keyword_decimal", "type": "keyword_decimal",
"named": true "named": true
}, },
{
"type": "keyword_default",
"named": true
},
{ {
"type": "keyword_exists", "type": "keyword_exists",
"named": true "named": true
}, },
{
"type": "keyword_false",
"named": true
},
{ {
"type": "keyword_if", "type": "keyword_if",
"named": true "named": true
@ -501,6 +592,10 @@
"type": "keyword_not", "type": "keyword_not",
"named": true "named": true
}, },
{
"type": "keyword_null",
"named": true
},
{ {
"type": "keyword_numeric", "type": "keyword_numeric",
"named": true "named": true
@ -529,6 +624,10 @@
"type": "keyword_text", "type": "keyword_text",
"named": true "named": true
}, },
{
"type": "keyword_true",
"named": true
},
{ {
"type": "keyword_unlogged", "type": "keyword_unlogged",
"named": true "named": true
@ -540,9 +639,5 @@
{ {
"type": "keyword_xml", "type": "keyword_xml",
"named": true "named": true
},
{
"type": "literal",
"named": true
} }
] ]

File diff suppressed because it is too large Load diff

View file

@ -167,3 +167,113 @@ create table foo (
) )
) )
) )
================================================================================
Create a table with column constraints
================================================================================
create table foo (
c1 text not null,
c2 text null,
c2 text not null default 'hello'
);
--------------------------------------------------------------------------------
(source_file
(statement
(create_table
(keyword_create)
(keyword_table)
(table_reference
name: (identifier)
)
(column_definitions
(column_definition
name: (identifier)
datatype: (keyword_text)
(column_constraint
(keyword_not)
(keyword_null)
)
)
(column_definition
name: (identifier)
datatype: (keyword_text)
(column_constraint
(keyword_null)
)
)
(column_definition
name: (identifier)
datatype: (keyword_text)
(column_constraint
(keyword_not)
(keyword_null)
)
(column_constraint
(keyword_default)
(literal)
)
)
)
)
)
)
================================================================================
Create a table with named column constraints
================================================================================
create table foo (
c1 text constraint strong_c1 not null,
c2 text constraint weak_c2 null,
c3 text constraint "c3 with power" not null constraint "c2 set default hello" default 'hello'
);
--------------------------------------------------------------------------------
(source_file
(statement
(create_table
(keyword_create)
(keyword_table)
(table_reference
name: (identifier)
)
(column_definitions
(column_definition
name: (identifier)
datatype: (keyword_text)
(column_constraint
(keyword_constraint)
name: (identifier)
(keyword_not)
(keyword_null)
)
)
(column_definition
name: (identifier)
datatype: (keyword_text)
(column_constraint
(keyword_constraint)
name: (identifier)
(keyword_null)
)
)
(column_definition
name: (identifier)
datatype: (keyword_text)
(column_constraint
(keyword_constraint)
name: (identifier)
(keyword_not)
(keyword_null)
)
(column_constraint
(keyword_constraint)
name: (identifier)
(keyword_default)
(literal)
)
)
)
)
)
)

Binary file not shown.