#include "ocilib.hpp"
#ifdef _MSC_VER
#if defined(OCI_CHARSET_WIDE)
#pragma comment(lib, "ocilibw.lib")
#elif defined(OCI_CHARSET_ANSI)
#pragma comment(lib, "ociliba.lib")
#endif
#endif
#include <iostream>
#include <fstream>
#include <iomanip>
#include <sstream>
const int ArgDatabase = 1;
const int ArgUser = 2;
const int ArgPassword = 3;
const int ArgHome = 4;
const int ArgCount = 5;
const int SizeString = 260;
const int SizeBuffer = 2048;
const int ElemCount = 5;
const int DirPathBufferSize = 64000;
const int DirPathLoadSize = 100;
const int DirPathLoadCount = 10;
const int DirPathSizeColumn1 = 20;
const int DirPathSizeColumn2 = 30;
const int DirPathSizeColumn3 = 8;
const int DirPathColumnCount = 3;
#ifndef OCI_SHARED_LIB
#if defined(_WINDOWS)
#if defined(OCI_CHARSET_WIDE)
#define OCI_SHARED_LIB                   "ocilibw.dll"
#else
#define OCI_SHARED_LIB                   "ociliba.dll"
#endif
#elif defined(__APPLE__)
#define OCI_SHARED_LIB                   "libocilib.dylib"
#elif defined(__hppa)
#define OCI_SHARED_LIB                   "libocilib.sl"
#else
#define OCI_SHARED_LIB                   "libocilib.so"
#endif
#endif
#define otext(s) OTEXT(s)
#define oendl  std::endl
#if defined(OCI_CHARSET_WIDE)
#if defined(_MSC_VER)
#define omain           wmain
#define oarg            otext
#define oarglen         wcslen
#else
#define omain           main
#define oarg            char
#define oarglen         strlen
#endif
#else
#define omain             main
#define oarg              char
#define oarglen           strlen
#endif
#if defined(OCI_CHARSET_WIDE)
#define ocout             std::wcout
#define oostringstream    std::wostringstream
#else
#define ocout             std::cout
#define oostringstream    std::ostringstream
#endif
#define ARRAY_COUNT(t) (sizeof(t)/sizeof(t[0]))
struct Test
{
    void(*proc)(void); 
    int    execute;     
};
struct Product
{
    int code;
    double price;
};
struct TestArray
{
    int val_int;
    float val_flt;
    double val_dbl;
};
void print_version(void);
void create_tables(void);
void drop_tables(void);
void test_format(void);
void test_immediate(void);
void test_immediate_format(void);
void test_fetch(void);
void test_fetch_translate(void);
void test_foreach(void);
void test_foreach_translate(void);
void test_bind1(void);
void test_bind2(void);
void test_piecewise_insert(void);
void test_piecewise_fetch(void);
void test_lob(void);
void test_nested_table(void);
void test_ref_cursor(void);
void test_plsql(void);
void test_dates(void);
void test_timestamp(void);
void test_describe(void);
void test_returning(void);
void test_returning_array(void);
void test_object_insert(void);
void test_object_fetch(void);
void test_scrollable_cursor(void);
void test_collection(void);
void test_ref(void);
void test_directpath(void);
Product CreateProductFromQuery(
const Resultset &rs);
bool FillProductFromQuery(
const Resultset &rs, Product &p);
 bool PrintProductFromQuery(
const Resultset &rs);
 bool PrintProductFromObject(const Product &p);
Test tab_test[] =
{
    { test_fetch, TRUE },
    { test_fetch_translate, TRUE },
    { test_foreach, TRUE },
    { test_foreach_translate, TRUE },
    { test_bind1, TRUE },
    { test_bind2, TRUE },
    { test_piecewise_insert, TRUE },
    { test_piecewise_fetch, TRUE },
    { test_lob, TRUE },
    { test_nested_table, TRUE },
    { test_ref_cursor, TRUE },
    { test_plsql, TRUE },
    { test_dates, TRUE },
    { test_timestamp, TRUE },
    { test_describe, TRUE },
    { test_returning, TRUE },
    { test_returning_array, TRUE },
    { test_object_insert, TRUE },
    { test_object_fetch, TRUE },
    { test_scrollable_cursor, TRUE },
    { test_collection, TRUE },
    { test_ref, TRUE },
    { test_directpath, TRUE }
};
{
    if (arg)
    {
        size_t i = 0, size = oarglen(arg);
        res.resize(size);
        while (i < size) { res[i] = static_cast<char>(arg[i]); i++; }
    }
    return res;
}
int omain(int argc, oarg* argv[])
{
    size_t i;
    
    if (argc < (ArgCount - 1))
    {
        return EXIT_FAILURE;
    }
    
    dbs = GetArg(argv[ArgDatabase]);
    usr = GetArg(argv[ArgUser]);
    pwd = GetArg(argv[ArgPassword]);
    if (argc == ArgCount)
    {
        home = GetArg(argv[ArgHome]);
    }
    try
    {
        ocout << otext("Connecting to ") << usr << otext("/") << pwd << otext("@") << dbs << oendl << oendl;
        print_version();
        create_tables();
        
        for (i = 0; i < ARRAY_COUNT(tab_test); i++)
        {
            if (tab_test[i].execute)
                tab_test[i].proc();
        }
        drop_tables();
    }
    catch (std::exception &ex)
    {
        ocout << ex.what() << oendl;
    }
    if (con)
    {
        drop_tables();
    }
    ocout << otext("\nPress any key to exit...");
    getchar();
    return EXIT_SUCCESS;
}
bool FillProductFromQuery(
const Resultset &rs, Product &p)
 {
    p.price = rs.
Get<
double>(3);
    return true;
}
Product CreateProductFromQuery(
const Resultset &rs)
{
    Product p;
    return p;
}
bool PrintProductFromQuery(
const Resultset &rs)
 {
    ocout << otext(
"> code   : ") << rs.
Get<
int>(1);
    ocout << otext(
", action : ") << rs.
Get<
ostring>(2);
    ocout << otext(
", price  : ") << rs.
Get<
double>(3);
    ocout << otext(
", date   : ") << rs.
Get<
Date>(4);
    ocout << oendl;
    return true;
}
bool PrintProductFromObject(const Product &p)
{
    ocout << otext("> code   : ") << p.code;
    ocout << otext(", action : ") << p.action;
    ocout << otext(", price  : ") << p.price;
    ocout << otext(", date   : ") << p.date;
    ocout << oendl;
    return true;
}
void print_version(void)
{
    ocout << otext("\n>>>>> OCILIB BUILD INFORMATION \n\n");
        ocout << otext("OCI import mode         : LINKAGE\n");
    else
        ocout << otext("OCI import mode         : RUNTIME\n");
        ocout << otext("Charset type            : ANSI\n");
    else
        ocout << otext("Charset type            : WIDE\n");
    ocout << otext("\n>>>>> VERSIONS INFORMATION \n\n");
    ocout << otext("OCILIB major    version : ") << OCILIB_MAJOR_VERSION << oendl;
    ocout << otext("OCILIB minor    version : ") << OCILIB_MINOR_VERSION << oendl;
    ocout << otext("OCILIB revision version : ") << OCILIB_REVISION_VERSION << oendl;
    ocout << otext(
"Connection      version : ") << 
static_cast<unsigned int>(con.
GetVersion()) << oendl;
    ocout << otext("\n>>>>> SERVER VERSION BANNER \n\n");
}
{
    try
    {
        st.Execute(sql);
    }
    {
        {
            ocout << otext("Oracle Error => ");
            break;
            ocout << otext("Oracle Error => ");
            break;
            ocout << otext("OCILIB Error => ");
            break;
        default:
            ocout << otext("Unknown Error => ");
            break;
        }
        ocout << ex.
what() << oendl;
    }
}
void create_tables(void)
{
    ocout << otext("\n>>>>> CREATE TABLES FOR DEMO \n\n");
    
    execute_ddl(otext("create type type_t as OBJECT (id int, name varchar2(50))"));
    execute_ddl(otext("create type test_t as object ")
        otext("( ")
        otext("    val_int  number, ")
        otext("    val_flt  float, ")
        otext("    val_dbl  float, ")
        otext("    val_str  varchar2(30), ")
        otext("    val_date date, ")
        otext("    val_lob  clob, ")
        otext("    val_file bfile, ")
        otext("    val_obj  type_t, ")
        otext("    val_raw  raw(10) ")
        otext(")"));
    execute_ddl(otext("create type t_tab1_emp as VARRAY(100) of varchar2(50)"));
    execute_ddl(otext("create type t_tab2_emp as table of varchar2(50)"));
    
    execute_ddl(otext("create table test_fetch(code int, article ")
        otext("varchar2(30), price float, creation date)"));
    execute_ddl(otext("create table test_long_raw(code int, content long raw)"));
    execute_ddl(otext("create table test_long_str(code int, content long)"));
    execute_ddl(otext("create table test_lob(code int, content clob)"));
    execute_ddl(otext("create table test_object(val test_t)"));
    execute_ddl(otext("create table test_table_obj of type_t"));
    execute_ddl(otext("create table test_array ")
        otext("( ")
        otext("    val_int  number, ")
        otext("    val_dbl  float, ")
        otext("    val_flt  float, ")
        otext("    val_str  varchar2(30), ")
        otext("    val_date date, ")
        otext("    val_lob  clob, ")
        otext("    val_file bfile ")
        otext(")")
        );
    execute_ddl(otext("create table test_coll_varray ")
        otext("( ")
        otext("    departement number, ")
        otext("    employees   t_tab1_emp ")
        otext(")")
        );
    execute_ddl(otext("create table test_coll_nested ")
        otext("( ")
        otext("    departement number, ")
        otext("    employees   t_tab2_emp ")
        otext(") nested table employees store as test_table_emp")
        );
    execute_ddl(otext("create table test_directpath(val_int number(8,4), ")
        otext(" val_str varchar2(30), val_date date)"));
    
    execute_ddl(otext("insert into test_fetch ")
        otext("(code, article, price, creation) ")
        otext("values (1, 'shoes', 3.14, to_date('1978-12-23', 'YYYY-MM-DD'))"));
    execute_ddl(otext("insert into test_fetch ")
        otext("(code, article, price, creation) ")
        otext("values (2, 'shirt', 5.99, to_date('1999-09-12', 'YYYY-MM-DD'))"));
    execute_ddl(otext("insert into test_lob(code,content)  ")
        otext("values (1, EMPTY_CLOB())"));
    execute_ddl(otext("insert into test_long_str(code,content) ")
        otext("values (1, 'Rugby rocks !')"));
    execute_ddl(otext("insert into test_coll_varray(departement,employees) ")
        otext("values (1, t_tab1_emp('Peter', 'John', 'Paula', 'Gina'))"));
    execute_ddl(otext("insert into test_coll_varray(departement,employees) ")
        otext("values (2, t_tab1_emp('Ben', 'Alice', 'Joel', 'Maria'))"));
    execute_ddl(otext("insert into test_coll_nested(departement,employees) ")
        otext("values (1, t_tab2_emp('Vince', 'Richard', 'Rita', 'Sophia'))"));
    execute_ddl(otext("insert into test_coll_nested(departement,employees) ")
        otext("values (2, t_tab2_emp('Paul', 'Sarah', 'Robert', 'Zoe'))"));
    execute_ddl(otext("insert into test_table_obj values(type_t(1, 'shoes'))"));
    execute_ddl(otext("insert into test_table_obj values(type_t(2, 'pen'))"));
}
void drop_tables(void)
{
    ocout << otext("\n>>>>> DROPPING TABLES AND TYPES \n\n");
    execute_ddl(otext("drop table test_fetch"));
    execute_ddl(otext("drop table test_long_str"));
    execute_ddl(otext("drop table test_long_raw"));
    execute_ddl(otext("drop table test_lob"));
    execute_ddl(otext("drop table test_array"));
    execute_ddl(otext("drop table test_object"));
    execute_ddl(otext("drop table test_coll_varray"));
    execute_ddl(otext("drop table test_coll_nested"));
    execute_ddl(otext("drop table test_table_obj"));
    execute_ddl(otext("drop table test_directpath"));
    execute_ddl(otext("drop type  test_t"));
    execute_ddl(otext("drop type  type_t"));
    execute_ddl(otext("drop type  t_tab1_emp"));
    execute_ddl(otext("drop type  t_tab2_emp"));
}
void test_fetch(void)
{
    ocout << otext("\n>>>>> SIMPLE TEST FETCH WITH META DATA\n\n");
    st.Execute(otext("select * from test_fetch"));
    {
        ocout << otext(
"> Field : #") << i << otext(
" - Name : ") << rs.
GetColumn(i).
GetName() << oendl;
    }
    ocout << oendl;
    while (rs++)
    {
        PrintProductFromQuery(rs);
    }
    ocout << oendl << rs.
GetCount() << otext(
" row(s) fetched") << oendl;
}
void test_fetch_translate(void)
{
    ocout << otext("\n>>>>> SIMPLE TEST FETCH  WITH ROW TRANSLATION TO USER TYPE \n\n");
    st.Execute(otext("select * from test_fetch"));
    ocout << oendl;
    while (rs++)
    {
        Product p;
        if (rs.
Get(p, FillProductFromQuery))
         {
            PrintProductFromObject(p);
        }
    }
    ocout << oendl << rs.
GetCount() << otext(
" row(s) fetched") << oendl;
}
void test_foreach(void)
{
    ocout << otext("\n>>>>> FOREACH FETCH\n\n");
    st.Execute(otext("select * from test_fetch"), PrintProductFromQuery);
}
void test_foreach_translate(void)
{
    ocout << otext("\n>>>>> FOREACH FETCH WITH TRANSLATION\n\n");
    st.Execute(otext("select * from test_fetch"), PrintProductFromObject, CreateProductFromQuery);
}
void test_bind1(void)
{
    unsigned int code = 1, count = 0;
    ocout << otext("\n>>>>> TEST BINDING \n\n");
    st.Prepare(otext("select * from test_fetch where code = :code"));
    count = st.ExecutePrepared(PrintProductFromObject, CreateProductFromQuery);
    ocout << oendl << count << otext(" row(s) fetched") << oendl;
}
void test_bind2(void)
{
    ocout << otext("\n>>>>> SINGLE BINDING \n\n");
    st.Prepare(otext("insert into test_array ")
        otext("( ")
        otext("   val_int,  val_dbl, val_flt, val_str, val_date, ")
        otext("   val_lob, val_file ")
        otext(") ")
        otext("values ")
        otext("( ")
        otext("   :val_int, :val_dbl, :val_flt, :val_str, :val_date, ")
        otext("   :val_lob, :val_file ")
        otext(") "));
    
    TestArray t;
    t.val_int = 1;
    t.val_dbl = 3.14;
    t.val_flt = 3.14f;
    t.val_str = otext("Name00");
    t.val_lob.Write(otext("lob value00"));
    t.val_file.SetInfos(otext("mydir"), otext("file00.txt"));
    
    st.Bind(otext(
":val_str"), t.val_str, static_cast<unsigned int>(t.val_str.size()), 
BindInfo::In);
    
    
    st.ExecutePrepared();
    ocout << oendl << st.GetAffectedRows() << otext(" row(s) inserted") << oendl;
}
void test_piecewise_insert(void)
{
    ocout << otext("\n>>>>> TEST PIECEWISE INSERTING\n\n");
    std::ifstream file(OCI_SHARED_LIB, std::ios::in | std::ios::binary | std::ios::ate);
    if (file.is_open())
    {
        size_t size = static_cast<size_t>(file.tellg());
        file.seekg(0, std::ios::beg);
        ocout << oendl << size << otext(" bytes to write") << oendl;
        st.Prepare(otext("insert into test_long_raw(code, content) values (1, :data)"));
        st.SetLongMaxSize(static_cast<unsigned int>(size));
        st.Bind(otext(
":data"), lg, static_cast<unsigned int>(size), 
BindInfo::In);
        st.ExecutePrepared();
        unsigned char *strBuffer = new unsigned char[size];
        file.read(reinterpret_cast<char *>(strBuffer), size);
        lg.Write(
Raw(strBuffer, strBuffer + size));
        delete[] strBuffer;
        ocout << oendl << lg.GetLength() << otext(" bytes written") << oendl;
        file.close();
    }
}
void test_piecewise_fetch(void)
{
    ocout << otext("\n>>>>> TEST PIECEWISE FETCHING\n\n");
    st.Execute(otext("select content from test_long_raw where code = 1"));
    while (rs1++)
    {
        ocout << oendl << lg.
GetLength() << otext(
" bytes read") << oendl;
    }
    ocout << oendl << rs1.
GetCount() << otext(
" row(s) fetched") << oendl;
    ocout << otext("\n>>>>> TEST LONG MAPPED TO STRING\n\n");
    st.Execute(otext("select content from test_long_str where code = 1"));
    while (rs2++)
    {
        ocout << str << oendl;
        ocout << str.size() << otext(" bytes read") << oendl;
    }
    ocout << oendl << rs2.
GetCount() << otext(
" row(s) fetched") << oendl;
}
void test_lob(void)
{
    ocout << otext("\n>>>>> TEST LOB MANIPULATION\n\n");
    st.Execute(otext("select code, content from test_lob where code=1 for update"));
    while (rs++)
    {
        clob.
Write(otext(
"today, "));
        clob.
Append(otext(
"i'm going to the cinema ! "));
        ocout << otext(
"> code : ") << rs.
Get<
int>(1) << otext(
", content : ") << clob.
Read(SizeString) << oendl;
    }
    ocout << oendl << rs.
GetCount() << otext(
" row(s) fetched") << oendl;
}
void test_nested_table(void)
{
    ocout << otext("\n>>>>> TEST NESTED TABLE \n\n");
    st.Execute(otext("select article, cursor(select sysdate from dual) from test_fetch"));
    while (rs++)
    {
        while (rs2++)
        {
            ocout << otext(
"Article : ") << rs.
Get<
ostring>(1) << otext(
", Date : ") << rs2.Get<
ostring>(1) << oendl;
        }
    }
}
void test_ref_cursor(void)
{
    ocout << otext("\n>>>>> TEST REF CURSOR  \n\n");
    st.Prepare(otext("begin open :c for select * from test_fetch; end;"));
    st.ExecutePrepared();
    while (rs++)
    {
        PrintProductFromQuery(rs);
    }
    ocout << oendl << rs.
GetCount() << otext(
" row(s) fetched") << oendl;
}
void test_plsql(void)
{
    ocout << otext("\n>>>>> TEST PL/SQL OUTPUT BIND\n\n");
    int res = 0;
    st.Prepare(otext("begin :res := trunc(sysdate+1)-trunc(sysdate-1); end;"));
    st.ExecutePrepared();
    ocout << otext("PL/SQL : trunc(sysdate+1)-trunc(sysdate-1)") << oendl;
    ocout << otext("Result : ") << res << oendl;
#ifndef OCI_CHARSET_ANSI
    
        return;
#endif
    ocout << otext("\n>>>>> TEST PL/SQL SERVER OUTPUT\n\n");
    
    st.Execute(otext("begin ")
        otext("   dbms_output.put_line('First  line'); ")
        otext("   dbms_output.put_line('Second line'); ")
        otext("   dbms_output.put_line('Third  line'); ")
        otext("end;")
        );
    {
        ocout << line << oendl;
    }
}
void test_dates(void)
{
    ocout << otext("\n>>>>> TEST DATETIME MANIPULATION\n\n");
    Date date(otext(
"1978-04-13"));
     ocout << date << oendl;
    ocout << date.SysDate() << oendl;
    date.AddDays(5);
    date.AddMonths(2);
    ocout << otext("Date + 5 days and 2 months is ") << date << oendl;
    ocout << otext("Last day of the month : ") << date.LastDay() << oendl;
    ocout << otext("Number of days until the end of the months : ") << date.LastDay().DaysBetween(date) << oendl;
}
void test_timestamp(void)
{
#ifndef OCI_CHARSET_ANSI
    
    if ((version >= Oracle9iR1) || (version < Oracle10gR1))
        return;
#endif
    if (version >= Oracle9iR1)
    {
        ocout << otext("\n>>>>> TEST TIMESTAMP\n\n");
        ocout << otext("Current timestamp: ") << tm << oendl;
        
        if (version >= Oracle10gR1)
        {
            ocout << otext("\n>>>>> TEST INTERVAL \n\n");
            itv.SetDaySecond(1, 1, 1, 1, 0);
            tm += itv;
            ocout << otext("Current timestamp + Interval: ") << tm << oendl;
        }
    }
}
void test_describe(void)
{
    ocout << otext("\n>>>>> TEST DESCRIBING TABLE \n\n");
    ocout << otext("Column Name         Type                ") << oendl;
    ocout << otext("----------------------------------------") << oendl;
    ocout << std::setiosflags(std::ios::left);
    for (int i = 1, n = table.GetColumnCount(); i <= n; i++)
    {
        Column col = table.GetColumn(i);
         ocout << std::setw(20) << col.
GetName().c_str()
            << oendl;
    }
    
    ocout << otext("\n>>>>> TEST DESCRIBING TYPE \n\n");
    ocout << otext("Column Name         Type                ") << oendl;
    ocout << otext("----------------------------------------") << oendl;
    ocout << std::setiosflags(std::ios::left);
    for (int i = 1, n = type.GetColumnCount(); i <= n; i++)
    {
        Column col = type.GetColumn(i);
         ocout << std::setw(20) << col.
GetName().c_str()
            << oendl;
    }
}
void test_returning(void)
{
    ocout << otext("\n>>>>> TEST RETURNING CLAUSE \n\n");
    st.Prepare(otext("update test_lob set code = code + 1 returning code, content into :i, :l"));
    st.Register<int>(otext(":i"));
    st.Register<
Clob>(otext(
":l"));
    st.ExecutePrepared();
    while (rs++)
    {
        clob.
Append(otext(
"(modified)"));
        ocout << otext(
"> code : ") << rs.
Get<
int>(1) << otext(
" - ") << clob.
Read(static_cast<unsigned int>(clob.
GetLength())) << oendl;
    }
    ocout << oendl << rs.
GetCount() << otext(
" row(s) fetched") << oendl;
}
void test_returning_array(void)
{
    ocout << otext("\n>>>>> TEST ARRAY BINDING WITH RETURNING CLAUSE \n\n");
    std::vector<int>     tab_int;
    std::vector<double>  tab_dbl;
    std::vector<float>   tab_flt;
    std::vector<ostring> tab_str;
    std::vector<Date>    tab_date;
    std::vector<Clob>    tab_lob;
    std::vector<File>    tab_file;
    for (int i = 0; i < ElemCount; i++)
    {
        tab_int.push_back(i + 1);
        tab_dbl.push_back(3.14*static_cast<double>(i + 1));
        tab_flt.push_back(3.14f*static_cast<float>(i + 1));
        str += otext("Name");
        str += static_cast<ostring::value_type>((i + 1) + '0');
        tab_str.push_back(str);
        clob.
Write(otext(
"Lob value ") + str);
        tab_lob.push_back(clob);
        fileName += otext("File");
        fileName += static_cast<ostring::value_type>((i + 1) + '0');
        File file(con, otext(
"Mydir"), fileName);
         tab_file.push_back(file);
    }
    st.Prepare(otext("insert into test_array ")
        otext("( ")
        otext("   val_int,  val_dbl, val_flt, val_str, val_date, ")
        otext("   val_lob, val_file ")
        otext(") ")
        otext("values ")
        otext("( ")
        otext("   :val_int, :val_dbl, :val_flt, :val_str, :val_date, ")
        otext("   :val_lob, :val_file ")
        otext(") ")
        otext("returning")
        otext("  val_int,  val_dbl, val_flt, val_str, val_date, ")
        otext("   val_lob, val_file ")
        otext("into  ")
        otext("  :out_int, :out_dbl, :out_flt,  :out_str, :out_date, ")
        otext("   :out_lob, :out_file "));
    st.SetBindArraySize(ElemCount);
    
    
    st.Register<int    >(otext(":out_int"));
    st.Register<double >(otext(":out_dbl"));
    st.Register<float  >(otext(":out_flt"));
    st.Register<
Date   >(otext(
":out_date"));
    st.Register<
Clob   >(otext(
":out_lob"));
    st.Register<
File   >(otext(
":out_file"));
    st.Register<
ostring>(otext(
":out_str"), 30);
    st.ExecutePrepared();
    ocout << oendl << st.GetAffectedRows() << otext(" row(s) inserted") << oendl;
    int rowIndex = 0;
    while (!rs.IsNull())
    {
        while (rs++)
        {
            ocout << otext("Row #") << ++rowIndex << otext("---------------") << oendl;
            ocout << otext(
".... val_int    : ") << rs.
Get<
int>(otext(
":OUT_INT")) << oendl;
            ocout << otext(
".... val_dbl    : ") << rs.
Get<
double>(otext(
":OUT_DBL")) << oendl;
            ocout << otext(
".... val_flt    : ") << rs.
Get<
float>(otext(
":OUT_FLT")) << oendl;
            ocout << otext(
".... val_str    : ") << rs.
Get<
ostring>(otext(
":OUT_STR")) << oendl;
            ocout << otext(
".... val_date   : ") << rs.
Get<
Date>(otext(
":OUT_DATE")) << oendl;
            ocout << otext(
".... val_lob    : ") << clob.
Read(SizeBuffer) << oendl;
            ocout << otext(
".... val_file   : ") << file.
GetDirectory() << otext(
"/") << file.
GetName() << oendl;
        }
        rs = st.GetNextResultset();
    }
}
void test_object_insert(void)
{
    unsigned char *constData = reinterpret_cast<unsigned char*>(const_cast< char *>("0123456789"));
    Raw rawData(constData, constData + 10);
     ocout << otext("\n>>>>> TEST OBJECT BINDING \n\n");
    clob.Write(otext("Lob Value"));
    File file(con, otext(
"mydir"), otext(
"myfile"));
     obj2.Set<int>(otext("ID"), 1);
    obj2.Set<
ostring>(otext(
"NAME"), otext(
"USB KEY 2go"));
    obj1.Set<int>(otext("VAL_INT"), 1);
    obj1.Set<double>(otext("VAL_DBL"), 3.14);
    obj1.Set<float>(otext("VAL_FLT"), static_cast<float>(3.14));
    obj1.Set<
ostring>(otext(
"VAL_STR"), otext(
"USB KEY 2go"));
    obj1.Set<
Raw>(otext(
"VAL_RAW"), rawData);
    obj1.Set<
Date>(otext(
"VAL_DATE"), date);
    obj1.Set<
Object>(otext(
"VAL_OBJ"), obj2);
    obj1.
Set<
Clob>(otext(
"VAL_LOB"), clob);
    obj1.Set<
File>(otext(
"VAL_FILE"), file);
    st.Prepare(otext("insert into test_object values(:obj)"));
    st.ExecutePrepared();
    ocout << otext("Rows inserted :  ") << st.GetAffectedRows() << oendl;
}
void test_object_fetch(void)
{
    ocout << otext("\n>>>>> TEST OBJECT FETCHING \n\n");
    st.Execute(otext("select val from test_object for update"));
    while (rs++)
    {
        ocout << otext(
".... val_int      : ") << obj.
Get<
int>(otext(
"VAL_INT")) << oendl;
        ocout << otext(
".... val_dbl      : ") << obj.
Get<
double>(otext(
"VAL_DBL")) << oendl;
        ocout << otext(
".... val_flt      : ") << obj.
Get<
float>(otext(
"VAL_FLT")) << oendl;
        ocout << otext(
".... val_str      : ") << obj.
Get<
ostring>(otext(
"VAL_STR")) << oendl;
        ocout << otext(
".... val_date     : ") << obj.
Get<
Date>(otext(
"VAL_DATE")) << oendl;
        ocout << otext(
".... val_lob      : ") << clob.
Read(SizeBuffer) << oendl;
        ocout << otext(
".... val_file     : ") << file.
GetDirectory() << otext(
"/") << file.
GetName() << oendl;
        raw.push_back(0);
        ocout << otext(".... val_raw      : ") << reinterpret_cast<char *>(raw.data()) << oendl;
        ocout << otext(
".... val_obj.code : ") << obj2.
Get<
int>(otext(
"ID")) << oendl;
        ocout << otext(
".... val_obj.name : ") << obj2.Get<
ostring>(otext(
"NAME")) << oendl;
    }
    ocout << otext("\n>>>>> TEST OBJECT FETCHING  AS STRING \n\n");
    st.Execute(otext("select val from test_object"));
    rs = st.GetResultset();
    while (rs++)
    {
    }
}
void test_scrollable_cursor(void)
{
    {
        ocout << otext("\n>>>>> TEST SCROLLABLE CURSORS \n\n");
        st.Execute(otext("select table_name from user_tables where ")
            otext("table_name like 'TEST_%' order by table_name"));
        ocout << otext(
"Total rows : ") << rs.
GetCount() << oendl;
        ocout << otext("... Go to row 1\n");
        ocout << otext(
"table ") << rs.
Get<
ostring>(1) << oendl;
        ocout << otext(
"... Enumerate from row 2 to row ") << rs.
GetCount() << otext(
" ") << oendl;
        while (rs++)
        {
            ocout << otext(
"table ") << rs.
Get<
ostring>(1) << oendl;
        }
        ocout << otext(
"... Enumerate from row ") << rs.
GetCount() - 1 << otext(
" back to row 1") << oendl;
        {
            ocout << otext(
"table ") << rs.
Get<
ostring>(1) << oendl;
        }
        ocout << otext("... Go to the 3th row") << oendl;
        ocout << otext(
"table ") << rs.
Get<
ostring>(1) << oendl;
        ocout << otext("... Fetch the next 2 rows") << oendl;
        {
            ocout << otext(
"table ") << rs.
Get<
ostring>(1) << oendl;
        }
    }
}
void test_collection(void)
{
    ocout << otext("\n>>>>> TEST VARRAY BINDING WITH ITERATOR \n\n");
    int i = 1;
    st.Prepare(otext("begin")
        otext("    select employees into :tab_emp ")
        otext("    from test_coll_varray ")
        otext("    where departement = :id; ")
        otext("end;"));
    st.ExecutePrepared();
    ocout << otext("Department ID #") << i << oendl;
    for (; it1 != it2; ++it1)
    {
        ocout << otext(
"... Employee : ") << 
static_cast<ostring>(*it1) << oendl;
    }
    ocout << otext("\n>>>>> TEST VARRAY PRINTING \n\n");
    ocout << coll << oendl;
    ocout << otext("\n>>>>> TEST VARRAY FETCHING WITH ITERATOR \n\n");
    st.Execute(otext("SELECT * from test_coll_varray"));
    while (rs++)
    {
        ocout << otext(
"Department ID #") << rs.
Get<
int>(1) << oendl;
        for (; it3 != it4; ++it3)
        {
            ocout << otext(
"... Employee : ") << 
static_cast<ostring>(*it3) << oendl;
        }
    }
    ocout << otext("\n>>>>> TEST NESTED TABLE FETCHING WITH INDEX ACCESS \n\n");
    st.Execute(otext("SELECT * from test_coll_nested"));
    rs = st.GetResultset();
    while (rs++)
    {
        ocout << otext(
"Department ID #") << rs.
Get<
int>(1) << oendl;
        for (unsigned int index = 1, n = coll.GetSize(); index <= n; index++)
        {
            ocout << otext(
"... Employee : ") << 
static_cast<ostring>(coll[index]) << oendl;
        }
    }
}
void test_ref(void)
{
    ocout << otext("\n>>>>> TEST REF FETCHING \n\n");
    st.Execute(otext("select ref(e) from test_table_obj e"));
    while (rs++)
    {
        ocout << obj.
Get<
int>(otext(
"ID")) << otext(
" - ") << obj.Get<
ostring>(otext(
"NAME")) << oendl;
    }
    ocout << otext("\n>>>>> TEST REF PL/SQL BINDING \n\n");
    st.Prepare(otext("begin ")
        otext("  select ref(e) into :r from test_table_obj e where e.id = 1; ")
        otext("end; "));
    st.ExecutePrepared();
    ocout << obj.
Get<
int>(otext(
"ID")) << otext(
" - ") << obj.
Get<
ostring>(otext(
"NAME")) << oendl;
}
void test_directpath(void)
{
    
    
    {
        
        ocout << otext("\n>>>>> TEST DIRECT PATH (10 loads of 100 rows) \n\n");
        int i = 0, j = 0, n = DirPathLoadSize;
        
        dp.SetBufferSize(DirPathBufferSize);
        dp.SetNoLog(true);
        dp.SetParallel(true);
        
        dp.SetColumn(1, otext("VAL_INT"), DirPathSizeColumn1);
        dp.SetColumn(2, otext("VAL_STR"), DirPathSizeColumn2);
        dp.SetColumn(3, otext("VAL_DATE"), DirPathSizeColumn3, otext("YYYYMMDD"));
        
        dp.Prepare();
        n = dp.GetMaxRows();
        for (i = 0; i < DirPathLoadCount; i++)
        {
            dp.Reset();
            for (j = 1; j <= n; j++)
            {
                oostringstream val1, val2, val3;
                
                val1 << std::setfill(otext('0')) << std::setw(4) << j + (i * DirPathLoadCount);
                val2 << otext("value ") << std::setfill(otext('0')) << std::setw(5) << j + (i * DirPathLoadCount);
                val3 << std::setfill(otext('0')) << std::setw(2) << (j % 23) + 1 + 2000 << std::setw(2) << (j % 11) + 1 << (j % 23) + 1;
                dp.SetEntry(j, 1, val1.str());
                dp.SetEntry(j, 2, val2.str());
                dp.SetEntry(j, 3, val3.str());
            }
            
            dp.Convert();
            dp.Load();
        }
        
        dp.Finish();
        ocout << std::setw(4) << dp.GetRowCount() << otext(" row(s) loaded") << oendl;
    }
}