Skip to content

Commit

Permalink
Merge pull request #88 from mloskot/issue-81
Browse files Browse the repository at this point in the history
Fix OUT direction of IN/OUT procedure parameter
  • Loading branch information
mloskot committed Mar 2, 2013
2 parents 62cb617 + 6f092e5 commit e29813d
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 35 deletions.
89 changes: 57 additions & 32 deletions src/backends/oracle/test/test-oracle.cpp
Expand Up @@ -343,50 +343,73 @@ struct returns_null_procedure_creator : public procedure_creator_base

void test7()
{
session sql(backEnd, connectString);
{
basic_table_creator tableCreator(sql);
session sql(backEnd, connectString);
{
basic_table_creator tableCreator(sql);

int id(1);
string_holder in("my string");
sql << "insert into soci_test(id, name) values(:id, :name)", use(id), use(in);
int id(1);
string_holder in("my string");
sql << "insert into soci_test(id, name) values(:id, :name)", use(id), use(in);

string_holder out;
sql << "select name from soci_test", into(out);
assert(out.get() == "my string");
string_holder out;
sql << "select name from soci_test", into(out);
assert(out.get() == "my string");

row r;
sql << "select * from soci_test", into(r);
string_holder dynamicOut = r.get<string_holder>(1);
assert(dynamicOut.get() == "my string");
row r;
sql << "select * from soci_test", into(r);
string_holder dynamicOut = r.get<string_holder>(1);
assert(dynamicOut.get() == "my string");
}
}
std::cout << "test 7 passed" << std::endl;
}

// FIXME: see https://github.com/SOCI/soci/issues/81
// temporarily disabled to allow testing of Oracle on travis-ci
#if 0
// test procedure with user-defined type as in-out parameter
void test7inout()
{
{
in_out_procedure_creator procedureCreator(sql);
session sql(backEnd, connectString);

string_holder sh("test");
procedure proc = (sql.prepare << "soci_test(:s)", use(sh));
proc.execute(1);
assert(sh.get() == "testtest");
// test procedure with user-defined type as in-out parameter
{
in_out_procedure_creator procedureCreator(sql);

std::string sh("test");
procedure proc = (sql.prepare << "soci_test(:s)", use(sh));
proc.execute(1);
assert(sh == "testtest");
}

// test procedure with user-defined type as in-out parameter
{
in_out_procedure_creator procedureCreator(sql);

string_holder sh("test");
procedure proc = (sql.prepare << "soci_test(:s)", use(sh));
proc.execute(1);
assert(sh.get() == "testtest");
}
}
#endif
// test procedure which returns null
std::cout << "test 7 inout passed" << std::endl;
}

void test7outnull()
{
{
returns_null_procedure_creator procedureCreator(sql);
session sql(backEnd, connectString);

string_holder sh;
indicator ind = i_ok;
procedure proc = (sql.prepare << "soci_test(:s)", use(sh, ind));
proc.execute(1);
assert(ind == i_null);
}
// test procedure which returns null
{
returns_null_procedure_creator procedureCreator(sql);

// FIXME above std::cout << "test 7 passed (IN/OUT " << std::endl;
std::cout << "test 7 passed (IN/OUT proc skipped)" << std::endl;
string_holder sh;
indicator ind = i_ok;
procedure proc = (sql.prepare << "soci_test(:s)", use(sh, ind));
proc.execute(1);
assert(ind == i_null);
}
}
std::cout << "test 7 outnull passed" << std::endl;
}

// test bulk insert features
Expand Down Expand Up @@ -1196,6 +1219,8 @@ int main(int argc, char** argv)
test5();
test6();
test7();
test7inout();
test7outnull();
test8();
test9();
test10();
Expand Down
6 changes: 6 additions & 0 deletions src/core/type-conversion.h
Expand Up @@ -120,6 +120,12 @@ class conversion_use_type

void convert_from_base()
{
// NOTE:
// readOnly_ flag indicates that use_type object has been generated
// based on non-const object passed by user as input argument.
// For const objects, this is effectively no-op conversion.
// See standard_use_type::post_use() for more details.

if (readOnly_ == false)
{
type_conversion<T>::from_base(
Expand Down
14 changes: 11 additions & 3 deletions src/core/use-type.cpp
Expand Up @@ -30,18 +30,26 @@ void standard_use_type::bind(statement_impl & st, int & position)
}
}

void standard_use_type::pre_use()
void standard_use_type::pre_use()
{
// Handle IN direction of parameters of SQL statements and procedures
convert_to_base();
backEnd_->pre_use(ind_);
}

void standard_use_type::post_use(bool gotData)
{
// Handle OUT direction of IN/OUT parameters of stored procedures
backEnd_->post_use(gotData, ind_);
convert_from_base();

// There is no need to call convert_from_base() here, the converted value
// wouldn't be used anyhow.
// IMPORTANT:
// This treatment of input ("use") parameter as output data sink may be
// confusing, but it is necessary to store OUT data back in the same
// object as IN, of IN/OUT parameter.
// As there is no symmetry for IN/OUT in SQL and there are no OUT/IN
// we do not perform convert_to_base() for output ("into") parameter.
// See conversion_use_type<T>::convert_from_base() for more details.
}

void standard_use_type::clean_up()
Expand Down

0 comments on commit e29813d

Please sign in to comment.