Skip to content

Commit

Permalink
parser: support for the RELEASE stmt
Browse files Browse the repository at this point in the history
  • Loading branch information
xNaCly committed Nov 23, 2024
1 parent c1a4b0c commit c02e3d3
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 36 deletions.
72 changes: 38 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,36 +40,36 @@ dynamic correctness. See below for a list of currently implemented features.

### Supported sql statements

| done | `sqlite`-syntax name | sql example | non-standard sql |
| ---- | --------------------------- | ------------------------------- | ---------------- |
|| `explain-stmt` | `EXPLAIN QUERY PLAN;` | |
| | `alter-table-stmt` | | |
|| `analyze-stmt` | `ANALYZE my_table;` | |
| | `attach-stmt` | | |
|| `begin-stmt` | `BEGIN DEFERRED TRANSACTION;` | |
|| `commit-stmt` | `END TRANSACTION;` | |
| | `create-index-stmt` | | |
| | `create-table-stmt` | | |
| | `create-trigger-stmt` | | |
| | `create-view-stmt` | | |
| | `create-virtual-table-stmt` | | |
| | `delete-stmt` | | |
| | `delete-stmt-limited` | | |
|| `detach-stmt` | `DETACH DATABASE my_database` | |
|| `drop-index-stmt` | `DROP INDEX my_index;` | |
|| `drop-table-stmt` | `DROP TABLE my_table;` | |
|| `drop-trigger-stmt` | `DROP TRIGGER my_trigger;` | |
|| `drop-view-stmt` | `DROP VIEW my_view;` | |
| | `insert-stmt` | | |
| | `pragma-stmt` | | sqlite specific |
| | `reindex-stmt` | | |
| | `release-stmt` | | |
|| `rollback-stmt` | `ROLLBACK TO latest_savepoint;` | |
| | `savepoint-stmt` | | |
| | `select-stmt` | | |
| | `update-stmt` | | |
| | `update-stmt-limited` | | |
|| `vacuum-stmt` | `VACUUM INTO 'repacked.db'` | |
| done | `sqlite`-syntax name | sql example | non-standard sql |
| ---- | --------------------------- | ------------------------------------ | ---------------- |
|| `explain-stmt` | `EXPLAIN QUERY PLAN;` | |
| | `alter-table-stmt` | | |
|| `analyze-stmt` | `ANALYZE my_table;` | |
| | `attach-stmt` | | |
|| `begin-stmt` | `BEGIN DEFERRED TRANSACTION;` | |
|| `commit-stmt` | `END TRANSACTION;` | |
| | `create-index-stmt` | | |
| | `create-table-stmt` | | |
| | `create-trigger-stmt` | | |
| | `create-view-stmt` | | |
| | `create-virtual-table-stmt` | | |
| | `delete-stmt` | | |
| | `delete-stmt-limited` | | |
|| `detach-stmt` | `DETACH DATABASE my_database` | |
|| `drop-index-stmt` | `DROP INDEX my_index;` | |
|| `drop-table-stmt` | `DROP TABLE my_table;` | |
|| `drop-trigger-stmt` | `DROP TRIGGER my_trigger;` | |
|| `drop-view-stmt` | `DROP VIEW my_view;` | |
| | `insert-stmt` | | |
| | `pragma-stmt` | | sqlite specific |
| | `reindex-stmt` | | |
| | `release-stmt` | `RELEASE SAVEPOINT latest_savepoint` | |
|| `rollback-stmt` | `ROLLBACK TO latest_savepoint;` | |
| | `savepoint-stmt` | `SAVEPOINT latest_savepoint` | |
| | `select-stmt` | | |
| | `update-stmt` | | |
| | `update-stmt-limited` | | |
|| `vacuum-stmt` | `VACUUM INTO 'repacked.db'` | |

## Installation

Expand Down Expand Up @@ -142,6 +142,7 @@ Options:
- no-content: Source file is empty
- no-statements: Source file is not empty but holds no statements
- unimplemented: Source file contains constructs sqleibniz does not yet understand
- unknown-keyword: Source file contains an unknown keyword
- bad-sqleibniz-instruction: Source file contains invalid sqleibniz instruction
- unterminated-string: Source file contains an unterminated string
- unknown-character: The source file contains an unknown character
Expand All @@ -151,7 +152,7 @@ Options:
- semicolon: The source file is missing a semicolon
-h, --help
Print help (see a summary with '-h')
Print help (see a summary with '-h'
```

### Configuration
Expand All @@ -162,9 +163,10 @@ Consult [src/rules.rs](./src/rules.rs) for configuration documentation and
[leibniz.toml](./leibniz.toml) for said example:

```toml
# this is an example file, consult: https://toml.io/en/ and src/rules.rs for
# documentation
# this is an example file, consult: https://toml.io/en/ for syntax help and
# src/rules.rs::Config for all available options
[disabled]
# see sqleibniz --help for all available rules
rules = [
# by default, sqleibniz specific errors are disabled:
"NoContent", # source file is empty
Expand All @@ -173,13 +175,15 @@ Consult [src/rules.rs](./src/rules.rs) for configuration documentation and
"BadSqleibnizInstruction", # source file contains a bad sqleibniz instruction

# ignoring sqlite specific diagnostics:
# "UnknownKeyword", # an unknown keyword was encountered
# "UnterminatedString", # a not closed string was found
# "UnknownCharacter", # an unknown character was found
# "InvalidNumericLiteral", # an invalid numeric literal was found
# "InvalidBlob", # an invalid blob literal was found (either bad hex data or incorrect syntax)
# "Syntax", # a structure with incorrect syntax was found
# "Semicolon", # a semicolon is missing
]

```

### sqleibniz instructions
Expand Down Expand Up @@ -248,7 +252,7 @@ multiple lines.

## Contribution

Contributions are always welcome <3
Contributions are always welcome <3, but remember to test all features you contribute.

### Local Dev env

Expand Down
4 changes: 4 additions & 0 deletions example/stmt.sql
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,7 @@ DROP VIEW IF EXISTS schema_name.view_name;

-- https://www.sqlite.org/lang_savepoint.html
SAVEPOINT savepoint_name;

-- https://www.sqlite.org/syntax/release-stmt.html
RELEASE savepoint_name;
RELEASE SAVEPOINT savepoint_name;
6 changes: 4 additions & 2 deletions leibniz.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# this is an example file, consult: https://toml.io/en/ and src/rules.rs for
# documentation
# this is an example file, consult: https://toml.io/en/ for syntax help and
# src/rules.rs::Config for all available options
[disabled]
# see sqleibniz --help for all available rules
rules = [
# by default, sqleibniz specific errors are disabled:
"NoContent", # source file is empty
Expand All @@ -9,6 +10,7 @@
"BadSqleibnizInstruction", # source file contains a bad sqleibniz instruction

# ignoring sqlite specific diagnostics:
# "UnknownKeyword", # an unknown keyword was encountered
# "UnterminatedString", # a not closed string was found
# "UnknownCharacter", # an unknown character was found
# "InvalidNumericLiteral", # an invalid numeric literal was found
Expand Down
36 changes: 36 additions & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ impl<'a> Parser<'a> {
trace!(self.tracer, "sql_stmt", self.cur());
let r = match self.cur()?.ttype {
// TODO: add new statement starts here
Type::Keyword(Keyword::RELEASE) => self.release_stmt(),
Type::Keyword(Keyword::SAVEPOINT) => self.savepoint_stmt(),
Type::Keyword(Keyword::DROP) => self.drop_stmt(),
Type::Keyword(Keyword::ANALYZE) => self.analyse_stmt(),
Expand Down Expand Up @@ -357,6 +358,41 @@ impl<'a> Parser<'a> {
// TODO: add new statement function here *_stmt()
// fn $1_stmt(&mut self) -> Option<Box<dyn nodes::Node>> {}

/// https://www.sqlite.org/syntax/release-stmt.html
fn release_stmt(&mut self) -> Option<Box<dyn nodes::Node>> {
let mut r = nodes::Release {
t: self.cur()?.clone(),
savepoint_name: String::new(),
};
self.advance();

if self.is(Type::Keyword(Keyword::SAVEPOINT)) {
self.advance();
}

if let Type::Ident(savepoint) = &self.cur()?.ttype {
r.savepoint_name = savepoint.clone();
self.advance();
} else {
let mut err = self.err(
"Unexpected Token",
&format!(
"Expected Ident(<savepoint-name>), got {:?}",
self.cur()?.ttype
),
self.cur()?,
Rule::Syntax,
);
err.doc_url = Some("https://www.sqlite.org/syntax/release-stmt.html");
self.errors.push(err);
self.advance();
return None;
}

self.expect_end("https://www.sqlite.org/syntax/release-stmt.html");
some_box!(r)
}

/// https://www.sqlite.org/syntax/savepoint-stmt.html
fn savepoint_stmt(&mut self) -> Option<Box<dyn nodes::Node>> {
let mut s = nodes::Savepoint {
Expand Down
7 changes: 7 additions & 0 deletions src/parser/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,15 @@ node!(
ttype: Keyword,
argument: String
);

node!(
Savepoint,
"Savepoint stmt, see: https://www.sqlite.org/lang_savepoint.html",
savepoint_name: String
);

node!(
Release,
"Release stmt, see: https://www.sqlite.org/lang_savepoint.html",
savepoint_name: String
);
17 changes: 17 additions & 0 deletions src/parser/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,13 @@ EXPLAIN VACUUM;

savepoint_savepoint_name:r"SAVEPOINT savepoint_name;"=vec![Type::Keyword(Keyword::SAVEPOINT)]
}

test_group_pass_assert! {
release_stmt,

release_savepoint_savepoint_name:r"RELEASE SAVEPOINT savepoint_name;"=vec![Type::Keyword(Keyword::RELEASE)],
release_savepoint_name:r"RELEASE savepoint_name;"=vec![Type::Keyword(Keyword::RELEASE)]
}
}

#[cfg(test)]
Expand Down Expand Up @@ -251,4 +258,14 @@ mod should_fail {

savepoint_no_savepoint_name:r"SAVEPOINT;"
}

test_group_fail! {
release_stmt,

release_savepoint_savepoint_name_no_semicolon:r"RELEASE SAVEPOINT savepoint_name",
release_savepoint_name_no_semicolon:r"RELEASE savepoint_name",

release_savepoint_no_savepoint_name:r"RELEASE SAVEPOINT;",
release_savepoint_no_name:r"RELEASE;"
}
}

0 comments on commit c02e3d3

Please sign in to comment.