Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ r2d2 = ["diesel/r2d2"]
default = ["chrono-time", "r2d2"]

[replace]
"diesel:1.4.2" = { git = "https://github.com/GiGainfosystems/diesel", rev = "83ef2f8346" }
"diesel_derives:1.4.0" = { git = "https://github.com/GiGainfosystems/diesel", rev = "83ef2f8346" }
"diesel:1.4.2" = { git = "https://github.com/GiGainfosystems/diesel", rev = "ea521dd32" }
"diesel_derives:1.4.0" = { git = "https://github.com/GiGainfosystems/diesel", rev = "ea521dd32" }
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nightly-2019-07-02
nightly-2019-10-03
44 changes: 39 additions & 5 deletions src/oracle/backend.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use byteorder::NativeEndian;
use diesel::backend::UsesAnsiSavepointSyntax;
use diesel::backend::*;
use diesel::query_builder::bind_collector::RawBytesBindCollector;
Expand All @@ -15,8 +14,18 @@ pub struct Oracle;
impl Backend for Oracle {
type QueryBuilder = OciQueryBuilder;
type BindCollector = RawBytesBindCollector<Oracle>;
type RawValue = OracleValue;
type ByteOrder = NativeEndian;
}

impl<'a> HasRawValue<'a> for Oracle {
type RawValue = OracleValue<'a>;
}

impl<'a> BinaryRawValue<'a> for Oracle {
type ByteOrder = byteorder::NativeEndian;

fn as_bytes(value: Self::RawValue) -> &'a [u8] {
value.bytes
}
}

impl TypeMetadata for Oracle {
Expand All @@ -31,9 +40,34 @@ impl UsesAnsiSavepointSyntax for Oracle {}
impl SupportsReturningClause for Oracle {}

pub trait HasSqlTypeExt<ST>: HasSqlType<ST, MetadataLookup = ()> {
fn oci_row_metadata(out: &mut Vec<Self::TypeMetadata>) {
fn oci_row_metadata(out: &mut Vec<Self::TypeMetadata>);
}

impl<ST> HasSqlTypeExt<ST> for Oracle
where
Oracle: HasSqlType<ST>,
{
default fn oci_row_metadata(out: &mut Vec<Self::TypeMetadata>) {
out.push(Self::metadata(&()))
}
}

impl<ST> HasSqlTypeExt<ST> for Oracle where Oracle: HasSqlType<ST> {}
macro_rules! tuple_impls {
($(
$Tuple:tt {
$(($idx:tt) -> $T:ident, $ST:ident, $TT:ident,)+
}
)+) => {
$(
impl<$($T),+> HasSqlTypeExt<($($T,)+)> for Oracle
where $(Oracle: HasSqlTypeExt<$T>,)*
{
fn oci_row_metadata(out: &mut Vec<Self::TypeMetadata>) {
$(<Oracle as HasSqlTypeExt<$T>>::oci_row_metadata(out);)+
}
}
)*
};
}

__diesel_for_each_tuple!(tuple_impls);
27 changes: 0 additions & 27 deletions src/oracle/clause_impl.rs

This file was deleted.

39 changes: 14 additions & 25 deletions src/oracle/connection/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use diesel::result::Error::DeserializationError;
use diesel::result::QueryResult;
use diesel::sql_types::HasSqlType;
use oci_sys as ffi;
use std::collections::HashMap;
use std::marker::PhantomData;

use super::row::{NamedOciRow, OciRow};
Expand Down Expand Up @@ -40,6 +39,18 @@ impl Field {
pub fn is_null(&self) -> bool {
*self.null_indicator == -1
}

pub fn buffer(&self) -> &[u8] {
&self.buffer
}

pub fn name(&self) -> &str {
&self.name
}

pub fn datatype(&self) -> OciDataType {
self.typ
}
}

impl Drop for Field {
Expand Down Expand Up @@ -103,14 +114,7 @@ where
}

self.current_row += 1;
let null_indicators = self.results.iter().map(|r| r.is_null()).collect();
let mut row = OciRow::new(
self.results
.iter_mut()
.map(|r: &mut Field| &r.buffer[..])
.collect::<Vec<&[u8]>>(),
null_indicators,
);
let mut row = OciRow::new(&self.results);
let value = T::Row::build_from_row(&mut row)
.map(T::build)
.map_err(DeserializationError);
Expand All @@ -121,20 +125,13 @@ where
pub struct NamedCursor<'a> {
stmt: &'a Statement,
results: Vec<Field>,
lut: HashMap<String, usize>,
}

impl<'a> NamedCursor<'a> {
pub fn new(stmt: &'a Statement, binds: Vec<Field>) -> NamedCursor<'a> {
let lut = binds
.iter()
.enumerate()
.map(|(i, b)| (b.name.clone(), i))
.collect();
NamedCursor {
stmt,
results: binds,
lut,
}
}

Expand Down Expand Up @@ -164,15 +161,7 @@ impl<'a> NamedCursor<'a> {
break;
}
}
let null_indicators = self.results.iter().map(|r| r.is_null()).collect();
let row = NamedOciRow::new(
self.results
.iter_mut()
.map(|r: &mut Field| &r.buffer[..])
.collect::<Vec<&[u8]>>(),
null_indicators,
&self.lut,
);
let row = NamedOciRow::new(&self.results);

ret.push(T::build(&row).map_err(DeserializationError)?);
}
Expand Down
85 changes: 45 additions & 40 deletions src/oracle/connection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use diesel::sql_types::HasSqlType;
use self::cursor::{Cursor, NamedCursor};
use self::stmt::Statement;
use self::transaction::OCITransactionManager;
use super::backend::Oracle;
use super::backend::{HasSqlTypeExt, Oracle};
use diesel::RunQueryDsl;

mod oracle_value;
pub use self::oracle_value::OracleValue;
Expand All @@ -34,29 +35,33 @@ pub struct OciConnection {
}

impl MigrationConnection for OciConnection {
#[cfg(ka)]
const CREATE_MIGRATIONS_FUNCTION: &'static str =
"create or replace procedure create_if_not_exists(input_sql varchar2) \
as \
begin \
execute immediate input_sql; \
exception \
when others then \
if sqlcode = -955 then \
NULL; \
else \
raise; \
end if; \
end; \n ";

const CREATE_MIGRATIONS_TABLE: &'static str = "
declare \
begin \
create_if_not_exists('CREATE TABLE \"__DIESEL_SCHEMA_MIGRATIONS\" (\
\"VERSION\" VARCHAR2(50) PRIMARY KEY NOT NULL,\
\"RUN_ON\" TIMESTAMP with time zone DEFAULT sysdate not null\
)'); \
end; \n";
fn setup(&self) -> QueryResult<usize> {
diesel::sql_query(
r#"create or replace procedure create_if_not_exists(input_sql varchar2)
as
begin
execute immediate input_sql;
exception
when others then
if sqlcode = -955 then
NULL;
else
raise;
end if;
end;"#,
)
.execute(self)?;
diesel::sql_query(
r#"declare
begin
create_if_not_exists('CREATE TABLE "__DIESEL_SCHEMA_MIGRATIONS" (
"VERSION" VARCHAR2(50) PRIMARY KEY NOT NULL,
"RUN_ON" TIMESTAMP with time zone DEFAULT sysdate not null\
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The \ probably needs to be deleted.

)');
end; "#,
)
.execute(self)
}
}

// This relies on the invariant that RawConnection or Statement are never
Expand All @@ -67,8 +72,8 @@ unsafe impl Send for OciConnection {}

impl SimpleConnection for OciConnection {
fn batch_execute(&self, query: &str) -> QueryResult<()> {
let mut stmt = try!(Statement::prepare(&self.raw, query));
try!(stmt.run(self.auto_commit(), &[]));
let mut stmt = Statement::prepare(&self.raw, query)?;
stmt.run(self.auto_commit(), &[])?;
stmt.bind_index = 0;
Ok(())
}
Expand All @@ -82,7 +87,7 @@ impl Connection for OciConnection {
/// should be a valid connection string for a given backend. See the
/// documentation for the specific backend for specifics.
fn establish(database_url: &str) -> ConnectionResult<Self> {
let r = try!(raw::RawConnection::establish(database_url));
let r = raw::RawConnection::establish(database_url)?;
let ret = OciConnection {
raw: Rc::new(r),
transaction_manager: OCITransactionManager::new(),
Expand All @@ -103,10 +108,10 @@ impl Connection for OciConnection {

#[doc(hidden)]
fn execute(&self, query: &str) -> QueryResult<usize> {
let mut stmt = try!(Statement::prepare(&self.raw, query));
try!(stmt.run(self.auto_commit(), &[]));
let mut stmt = Statement::prepare(&self.raw, query)?;
stmt.run(self.auto_commit(), &[])?;
stmt.bind_index = 0;
Ok(try!(stmt.get_affected_rows()))
Ok(stmt.get_affected_rows()?)
}

#[doc(hidden)]
Expand All @@ -115,10 +120,10 @@ impl Connection for OciConnection {
T: QueryFragment<Self::Backend> + QueryId,
{
// TODO: FIXME: this always returns 0 whereas the code looks proper
let mut stmt = try!(self.prepare_query(source));
try!(stmt.run(self.auto_commit(), &[]));
let mut stmt = self.prepare_query(source)?;
stmt.run(self.auto_commit(), &[])?;
stmt.bind_index = 0;
Ok(try!(stmt.get_affected_rows()))
Ok(stmt.get_affected_rows()?)
}

fn transaction_manager(&self) -> &Self::TransactionManager {
Expand All @@ -134,9 +139,7 @@ impl Connection for OciConnection {
{
let mut stmt = self.prepare_query(&source.as_query())?;
let mut metadata = Vec::new();
// TODO: FIXME: Georg will check if this can get un-deprecated.
#[allow(deprecated)]
Oracle::row_metadata(&mut metadata, &());
Oracle::oci_row_metadata(&mut metadata);
let cursor: Cursor<T::SqlType, U> = stmt.run_with_cursor(self.auto_commit(), metadata)?;
cursor.collect()
}
Expand All @@ -159,14 +162,14 @@ impl OciConnection {
&self,
source: &T,
) -> QueryResult<MaybeCached<Statement>> {
let mut statement = try!(self.cached_prepared_statement(source));
let mut statement = self.cached_prepared_statement(source)?;

let mut bind_collector = RawBytesBindCollector::<Oracle>::new();
try!(source.collect_binds(&mut bind_collector, &()));
source.collect_binds(&mut bind_collector, &())?;
let metadata = bind_collector.metadata;
let binds = bind_collector.binds;
for (tpe, value) in metadata.into_iter().zip(binds) {
try!(statement.bind(tpe, value));
statement.bind(tpe, value)?;
}

Ok(statement)
Expand Down Expand Up @@ -200,5 +203,7 @@ use diesel::r2d2::R2D2Connection;

#[cfg(feature = "r2d2")]
impl R2D2Connection for OciConnection {
const CHECK_QUERY_STRING: &'static str = "SELECT 1 FROM DUAL";
fn ping(&self) -> QueryResult<()> {
self.execute("SELECT 1 FROM DUAL").map(|_| ())
}
}
17 changes: 12 additions & 5 deletions src/oracle/connection/oracle_value.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
use oracle::types::OciDataType;

#[derive(Debug)]
pub struct OracleValue {
pub(crate) bytes: [u8],
pub struct OracleValue<'a> {
pub(crate) bytes: &'a [u8],
tpe: OciDataType,
}

impl OracleValue {
pub fn new(bytes: &[u8]) -> &Self {
unsafe { &*(bytes as *const [u8] as *const Self) }
impl<'a> OracleValue<'a> {
pub fn new(bytes: &'a [u8], tpe: OciDataType) -> Self {
Self { bytes, tpe }
}

pub fn datatype(&self) -> OciDataType {
self.tpe
}
}
Loading