dbgen 0.4.1

Generate random test cases for databases
Documentation
WHITESPACE = _{ " "|"\t"|"\r"|"\n"|"\x0b"|"\x0c" }
COMMENT = _{
    "--" ~ (!NEWLINE ~ ANY)* ~ NEWLINE |
    "/*" ~ (!"*/" ~ ANY)* ~ "*/"
}

back_quoted     = @{ "`" ~ (!"`" ~ ANY | "``")* ~ "`" }
single_quoted   = @{ "'" ~ (!"'" ~ ANY | "''")* ~ "'" }
double_quoted   = @{ "\"" ~ (!"\"" ~ ANY | "\"\"")* ~ "\"" }

ident = @{
    back_quoted |
    double_quoted |
    "[" ~ (!"]" ~ ANY)* ~ "]" |
    (ASCII_ALPHA|"_") ~ (ASCII_ALPHANUMERIC|"_")*
}
number = @{
    ^"0x" ~ ASCII_HEX_DIGIT+ |
    (ASCII_DIGIT+ ~ ("." ~ ASCII_DIGIT*)? | "." ~ ASCII_DIGIT+) ~ (^"e" ~ ("+"|"-")? ~ ASCII_DIGIT+)?
}

b = _{ !(ASCII_ALPHANUMERIC|"_") }
kw_create   = @{ ^"create" ~ b }
kw_table    = @{ ^"table" ~ b }
kw_or       = @{ ^"or" ~ b }
kw_and      = @{ ^"and" ~ b }
kw_not      = @{ ^"not" ~ b }
kw_is       = @{ ^"is" ~ b }
kw_rownum   = @{ ^"rownum" ~ b }
kw_null     = @{ ^"null" ~ b }
kw_true     = @{ ^"true" ~ b }
kw_false    = @{ ^"false" ~ b }
kw_case     = @{ ^"case" ~ b }
kw_when     = @{ ^"when" ~ b }
kw_then     = @{ ^"then" ~ b }
kw_else     = @{ ^"else" ~ b }
kw_end      = @{ ^"end" ~ b }
kw_timestamp = @{ ^"timestamp" ~ b }
kw_interval = @{ ^"interval" ~ b }
kw_week     = @{ ^"week" ~ b }
kw_day      = @{ ^"day" ~ b }
kw_hour     = @{ ^"hour" ~ b }
kw_minute   = @{ ^"minute" ~ b }
kw_second   = @{ ^"second" ~ b }
kw_millisecond = @{ ^"millisecond" ~ b }
kw_microsecond = @{ ^"microsecond" ~ b }
kw_with     = @{ ^"with" ~ b }
kw_time     = @{ ^"time" ~ b }
kw_zone     = @{ ^"zone" ~ b }

op_le       = @{ "<=" }
op_lt       = @{ "<" }
op_ge       = @{ ">=" }
op_gt       = @{ ">" }
op_eq       = @{ "=" }
op_ne       = @{ "<>" }
op_add      = @{ "+" }
op_sub      = @{ "-" }
op_concat   = @{ "||" }
op_mul      = @{ "*" }
op_float_div = @{ "/" }

balanced = _{
    "(" ~ balanced* ~ ")" |
    "[" ~ balanced* ~ "]" |
    "{" ~ balanced* ~ "}" |
    back_quoted |
    single_quoted |
    double_quoted |
    !("("|"["|"{"|"`"|"'"|"\""|")"|"]"|"}") ~ ANY
}

qname = {
    ident ~ ("." ~ ident){0,2}
}

column_definition = {
    (!"{{" ~ balanced)+
}
table_options = {
    ")" ~ ANY*
}
create_table_content = _{
    "(" ~ (column_definition | "{{" ~ expr ~ "}}")* ~ table_options
}

create_table = _{
    SOI ~ kw_create ~ kw_table ~ qname ~ create_table_content
}

expr = {
    ("@" ~ ident ~ ":=")* ~ expr_or
}
expr_or = {
    expr_and ~ (kw_or ~ expr_and)*
}
expr_and = {
    expr_not ~ (kw_and ~ expr_not)*
}
expr_not = {
    kw_not* ~ expr_cmp
}
is_not = { kw_is ~ kw_not }
expr_cmp = {
    expr_add ~ ((is_not | kw_is | op_le | op_ge | op_ne | op_lt | op_gt | op_eq) ~ expr_add)?
}
expr_add = {
    expr_mul ~ ((op_add | op_sub | op_concat) ~ expr_mul)*
}
expr_mul = {
    expr_primary ~ ((op_mul | op_float_div) ~ expr_primary)*
}

expr_primary = {
    kw_rownum | kw_null | kw_true | kw_false |
    expr_group |
    single_quoted |     // string
    number |
    expr_unary |
    expr_case_value_when |
    expr_timestamp |
    expr_interval |
    expr_get_variable |
    expr_function
}

expr_group = {
    "(" ~ expr ~ ")"
}
expr_unary = {
    (op_add | op_sub)+ ~ expr_primary
}

expr_case_value_when = {
    kw_case ~ case_value_when_value ~
    (kw_when ~ case_value_when_pattern ~ kw_then ~ case_value_when_result)+ ~
    (kw_else ~ case_value_when_else)? ~
    kw_end
}
case_value_when_value = { expr }
case_value_when_pattern = { expr }
case_value_when_result = { expr }
case_value_when_else = { expr }

expr_timestamp = {
    kw_timestamp ~ (kw_with ~ kw_time ~ kw_zone)? ~ expr_primary
}
expr_interval = {
    kw_interval ~ expr ~ (kw_week | kw_day | kw_hour | kw_minute | kw_second | kw_millisecond | kw_microsecond)
}

expr_get_variable = {
    "@" ~ ident ~ !":="
}

expr_function = {
    qname ~ "(" ~ (expr ~ ("," ~ expr)*)? ~ ")"
}