1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-21 04:52:26 -05:00

in the mirrorrrr tsh tshh

This commit is contained in:
Divy Srivastava 2024-12-11 22:55:37 +05:30
parent 87574d241e
commit 3279935647
3 changed files with 169 additions and 167 deletions

View file

@ -40,8 +40,15 @@ pub struct DatabaseSync {
impl GarbageCollected for DatabaseSync {}
// Represents a single connection to a SQLite database.
#[op2]
impl DatabaseSync {
// Constructs a new `DatabaseSync` instance.
//
// A SQLite database can be stored in a file or in memory. To
// use a file-backed database, the `location` should be a path.
// To use an in-memory database, the `location` should be special
// name ":memory:".
#[constructor]
#[cppgc]
fn new(
@ -67,8 +74,17 @@ impl DatabaseSync {
})
}
// Opens the database specified by `location` of this instance.
//
// This method should only be used when the database is not opened
// via the constructor. An exception is thrown if the database is
// already opened.
#[fast]
fn open(&self) -> Result<(), SqliteError> {
if self.conn.borrow().is_some() {
return Err(SqliteError::AlreadyOpen);
}
let db = rusqlite::Connection::open(&self.location)?;
if self.options.enable_foreign_key_constraints {
db.execute("PRAGMA foreign_keys = ON", [])?;
@ -79,8 +95,32 @@ impl DatabaseSync {
Ok(())
}
// Closes the database connection. An exception is thrown if the
// database is not open.
#[fast]
fn close(&self) {}
fn close(&self) -> Result<(), SqliteError> {
if self.conn.borrow().is_none() {
return Err(SqliteError::AlreadyClosed);
}
*self.conn.borrow_mut() = None;
Ok(())
}
// This method allows one or more SQL statements to be executed
// without returning any results.
//
// This method is a wrapper around sqlite3_exec().
#[fast]
fn exec(&self, #[string] sql: &str) -> Result<(), SqliteError> {
let db = self.conn.borrow();
let db = db.as_ref().ok_or(SqliteError::InUse)?;
let mut stmt = db.prepare_cached(sql)?;
stmt.raw_execute()?;
Ok(())
}
#[cppgc]
fn prepare(&self, #[string] sql: &str) -> Result<StatementSync, SqliteError> {
@ -101,7 +141,7 @@ impl DatabaseSync {
};
if r != libsqlite3_sys::SQLITE_OK {
panic!("Failed to prepare statement");
return Err(SqliteError::PrepareFailed);
}
Ok(StatementSync {
@ -109,15 +149,4 @@ impl DatabaseSync {
db: self.conn.clone(),
})
}
#[fast]
fn exec(&self, #[string] sql: &str) -> Result<(), SqliteError> {
let db = self.conn.borrow();
let db = db.as_ref().ok_or(SqliteError::InUse)?;
let mut stmt = db.prepare_cached(sql)?;
stmt.raw_execute()?;
Ok(())
}
}

View file

@ -12,10 +12,18 @@ pub enum SqliteError {
InUse,
#[error("Failed to step statement")]
FailedStep,
#[error("Failed to bind parameter. {0}")]
FailedBind(&'static str),
#[error("Unknown column type")]
UnknownColumnType,
#[error("Failed to get SQL")]
GetSqlFailed,
#[error("Database is already closed")]
AlreadyClosed,
#[error("Database is already open")]
AlreadyOpen,
#[error("Failed to prepare statement")]
PrepareFailed,
#[error(transparent)]
Other(deno_core::error::AnyError),
}

View file

@ -24,29 +24,16 @@ pub struct StatementSync {
impl GarbageCollected for StatementSync {}
#[op2]
impl StatementSync {
#[constructor]
#[cppgc]
fn new(_: bool) -> StatementSync {
unimplemented!()
}
fn get<'a>(
&self,
fn read_entry<'a>(
raw: *mut libsqlite3_sys::sqlite3_stmt,
scope: &mut v8::HandleScope<'a>,
#[varargs] params: Option<&v8::FunctionCallbackArguments>,
) -> Result<v8::Local<'a, v8::Object>, SqliteError> {
let raw = self.inner;
) -> Result<Option<v8::Local<'a, v8::Object>>, SqliteError> {
let result = v8::Object::new(scope);
unsafe {
libsqlite3_sys::sqlite3_reset(raw);
let r = libsqlite3_sys::sqlite3_step(raw);
if r == libsqlite3_sys::SQLITE_DONE {
return Ok(v8::Object::new(scope));
return Ok(None);
}
if r != libsqlite3_sys::SQLITE_ROW {
return Err(SqliteError::FailedStep);
@ -104,7 +91,75 @@ impl StatementSync {
.into();
result.set(scope, name, value);
}
}
Ok(Some(result))
}
fn bind_params(
scope: &mut v8::HandleScope,
raw: *mut libsqlite3_sys::sqlite3_stmt,
params: Option<&v8::FunctionCallbackArguments>,
) -> Result<(), SqliteError> {
if let Some(params) = params {
let len = params.length();
for i in 0..len {
let value = params.get(i);
if value.is_number() {
let value = value.number_value(scope).unwrap();
unsafe {
libsqlite3_sys::sqlite3_bind_double(raw, i as i32 + 1, value);
}
} else if value.is_string() {
let value = value.to_rust_string_lossy(scope);
unsafe {
libsqlite3_sys::sqlite3_bind_text(
raw,
i as i32 + 1,
value.as_ptr() as *const i8,
value.len() as i32,
libsqlite3_sys::SQLITE_TRANSIENT(),
);
}
} else if value.is_null() {
unsafe {
libsqlite3_sys::sqlite3_bind_null(raw, i as i32 + 1);
}
} else {
return Err(SqliteError::FailedBind("Unsupported type"));
}
}
}
Ok(())
}
#[op2]
impl StatementSync {
#[constructor]
#[cppgc]
fn new(_: bool) -> StatementSync {
unimplemented!()
}
fn get<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
#[varargs] params: Option<&v8::FunctionCallbackArguments>,
) -> Result<v8::Local<'a, v8::Object>, SqliteError> {
let raw = self.inner;
unsafe {
libsqlite3_sys::sqlite3_reset(raw);
}
bind_params(scope, raw, params)?;
let result = read_entry(raw, scope)
.map(|r| r.unwrap_or_else(|| v8::Object::new(scope)))?;
unsafe {
libsqlite3_sys::sqlite3_reset(raw);
}
@ -127,6 +182,7 @@ impl StatementSync {
unsafe {
libsqlite3_sys::sqlite3_reset(raw);
bind_params(scope, raw, params)?;
loop {
let r = libsqlite3_sys::sqlite3_step(raw);
if r == libsqlite3_sys::SQLITE_DONE {
@ -157,71 +213,9 @@ impl StatementSync {
let mut arr = vec![];
unsafe {
libsqlite3_sys::sqlite3_reset(raw);
loop {
let result = v8::Object::new(scope);
let r = libsqlite3_sys::sqlite3_step(raw);
if r == libsqlite3_sys::SQLITE_DONE {
break;
}
if r != libsqlite3_sys::SQLITE_ROW {
return Err(SqliteError::FailedStep);
}
let columns = libsqlite3_sys::sqlite3_column_count(raw);
for i in 0..columns {
let name = libsqlite3_sys::sqlite3_column_name(raw, i);
let name =
std::ffi::CStr::from_ptr(name).to_string_lossy().to_string();
let value = match libsqlite3_sys::sqlite3_column_type(raw, i) {
libsqlite3_sys::SQLITE_INTEGER => {
let value = libsqlite3_sys::sqlite3_column_int64(raw, i);
v8::Integer::new(scope, value as _).into()
}
libsqlite3_sys::SQLITE_FLOAT => {
let value = libsqlite3_sys::sqlite3_column_double(raw, i);
v8::Number::new(scope, value).into()
}
libsqlite3_sys::SQLITE_TEXT => {
let value = libsqlite3_sys::sqlite3_column_text(raw, i);
let value = std::ffi::CStr::from_ptr(value as _)
.to_string_lossy()
.to_string();
v8::String::new_from_utf8(
scope,
value.as_bytes(),
v8::NewStringType::Normal,
)
.unwrap()
.into()
}
libsqlite3_sys::SQLITE_BLOB => {
let value = libsqlite3_sys::sqlite3_column_blob(raw, i);
let size = libsqlite3_sys::sqlite3_column_bytes(raw, i);
let value =
std::slice::from_raw_parts(value as *const u8, size as usize);
let value =
v8::ArrayBuffer::new_backing_store_from_vec(value.to_vec())
.make_shared();
v8::ArrayBuffer::with_backing_store(scope, &value).into()
}
libsqlite3_sys::SQLITE_NULL => v8::null(scope).into(),
_ => {
return Err(SqliteError::UnknownColumnType);
}
};
let name = v8::String::new_from_utf8(
scope,
name.as_bytes(),
v8::NewStringType::Normal,
)
.unwrap()
.into();
result.set(scope, name, value);
}
bind_params(scope, raw, params)?;
while let Some(result) = read_entry(raw, scope)? {
arr.push(result.into());
}
@ -231,33 +225,4 @@ impl StatementSync {
let arr = v8::Array::new_with_elements(scope, &arr);
Ok(arr)
}
#[string]
fn source_sql(&self) -> Result<String, SqliteError> {
let raw = unsafe { libsqlite3_sys::sqlite3_sql(self.inner) };
if raw.is_null() {
return Err(SqliteError::GetSqlFailed);
}
let cstr = unsafe { std::ffi::CStr::from_ptr(raw) };
let sql = cstr.to_string_lossy().to_string();
Ok(sql)
}
#[string]
fn expanded_SQL(&self) -> Result<String, SqliteError> {
let raw = unsafe { libsqlite3_sys::sqlite3_expanded_sql(self.inner) };
if raw.is_null() {
return Err(SqliteError::GetSqlFailed);
}
let cstr = unsafe { std::ffi::CStr::from_ptr(raw) };
let expanded_sql = cstr.to_string_lossy().to_string();
unsafe { libsqlite3_sys::sqlite3_free(raw as *mut std::ffi::c_void) };
Ok(expanded_sql)
}
}