From 260164a711a0e36dbf3962a7d2e94c5542fa6df6 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 28 Nov 2022 12:26:13 -0800 Subject: [PATCH] Added basic syntax checker to sqlez --- crates/sqlez/src/statement.rs | 73 +++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/crates/sqlez/src/statement.rs b/crates/sqlez/src/statement.rs index 86035f5d0a..f3970827f8 100644 --- a/crates/sqlez/src/statement.rs +++ b/crates/sqlez/src/statement.rs @@ -489,3 +489,76 @@ mod test { ); } } + +mod syntax_check { + use std::{ + ffi::{CStr, CString}, + ptr, + }; + + use libsqlite3_sys::{ + sqlite3_close, sqlite3_errmsg, sqlite3_error_offset, sqlite3_extended_errcode, + sqlite3_extended_result_codes, sqlite3_finalize, sqlite3_open_v2, sqlite3_prepare_v2, + sqlite3_stmt, SQLITE_OPEN_CREATE, SQLITE_OPEN_NOMUTEX, SQLITE_OPEN_READWRITE, + }; + + fn syntax_errors(sql: &str) -> Option<(String, i32)> { + let mut sqlite3 = 0 as *mut _; + let mut raw_statement = 0 as *mut sqlite3_stmt; + + let flags = SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_READWRITE; + unsafe { + let memory_str = CString::new(":memory:").unwrap(); + sqlite3_open_v2(memory_str.as_ptr(), &mut sqlite3, flags, 0 as *const _); + + let sql = CString::new(sql).unwrap(); + + // Turn on extended error codes + sqlite3_extended_result_codes(sqlite3, 1); + + sqlite3_prepare_v2( + sqlite3, + sql.as_c_str().as_ptr(), + -1, + &mut raw_statement, + &mut ptr::null(), + ); + + let res = sqlite3_extended_errcode(sqlite3); + let offset = sqlite3_error_offset(sqlite3); + + if res == 1 && offset != -1 { + let message = sqlite3_errmsg(sqlite3); + let err_msg = + String::from_utf8_lossy(CStr::from_ptr(message as *const _).to_bytes()) + .into_owned(); + + sqlite3_finalize(*&mut raw_statement); + sqlite3_close(sqlite3); + + return Some((err_msg, offset)); + } else { + sqlite3_finalize(*&mut raw_statement); + sqlite3_close(sqlite3); + + None + } + } + } + + #[cfg(test)] + mod test { + use super::syntax_errors; + + #[test] + fn test_check_syntax() { + assert!(syntax_errors("SELECT FROM").is_some()); + + assert!(syntax_errors("SELECT col FROM table_t;").is_none()); + + assert!(syntax_errors("CREATE TABLE t(col TEXT,) STRICT;").is_some()); + + assert!(syntax_errors("CREATE TABLE t(col TEXT) STRICT;").is_none()); + } + } +}