//----------------------------------------------------------------------------//
// dbstep_t1.cpp - This example shows a simple selection from
// test database. Database driver type is defined in dbstep_test.h
//----------------------------------------------------------------------------//

#include <iostream>
#include <iomanip>

#define PREPARED_TEST

#include "dbstep_test.h"

// function that prints field names in query result
void test1_print_fields(DBSTEP::QueryResult* r)
{
        const DBSTEP::FieldListType *field_list_ptr = r->fetchFieldList();

        if (field_list_ptr)
	{        
	  int field_count = 0;
          for (DBSTEP::FieldListType::const_iterator f_it = field_list_ptr->begin();
                    f_it != field_list_ptr->end(); ++f_it)
          std::cout << "\nField (" << field_count++ << "): " << (*f_it);
          std::cout << "\n";
        }
}

void test1_print_result(DBSTEP::QueryResult* r)
{
        DBSTEP::RowMapType *row_map_ptr;

        // fetched rows from QueryResult are returned in a STL map
        // containing field name and field value
        while ((row_map_ptr = r->fetchRow()))
        {
            if (row_map_ptr->size() == 0)
                break;

            std::cout << "\nNew record:";
            int id = (*row_map_ptr) ["id"];
            int livel = (*row_map_ptr) ["livel"];
            std::string name = (*row_map_ptr) ["name"];
	    
	    std::cout << " id: " << std::setw(4) << id
	              << " name: " << std::setw(30) << name 
	              << " livel: " << std::setw(4) << livel;

        }
}


int main (int argc, char** argv)
{
    // here we get driver code 
    int drv=getDriver(argc, argv);
    
    // init parameter map
    DBSTEP::StringMapType param_map;
    try
    {
        if (drv == DBSTEP_ODBC)
	{ 
	  param_map ["dbname"] = "dbstep_test";
          param_map ["host"] = "localhost";
          param_map ["user"] = "";
          param_map ["password"] = "";
        }
	else
        if (drv == DBSTEP_FBIRD) 
	  param_map ["dbname"] = "dbstep_test.gdb";
        else
	{
	  param_map ["dbname"] = "dbstep_test";
          param_map ["host"] = "localhost";
          param_map ["user"] = "dbstep_user";
          param_map ["password"] = "dbstep_test";
        }
	
        param_map ["autocommit"] = "0";

	// new database object
        DBSTEP::Db db(drv);

        // opens connection
        db.openConnection(param_map);

        // query object
        DBSTEP::Query q(&db);

        int i = 1;
        q = "SELECT * from TestTable WHERE id=", i;

        // version 0.3.0 allows query preparation (on drivers that do not
	// support it the following method call does nothing) 
        q.prepare();
        
	// we need to bind parameters after preparing the query
	q.bind();
	
        // executes the query returning a QueryResult object (if query is a SELECT,
	// otherwise returns NULL)
        DBSTEP::QueryResult* r = q.exec();

        // here we test field names returned by query
        test1_print_fields(r);
        test1_print_result(r);
        delete r;

        // query result returned by Query::exec method must be deleted my caller

        // now we change the parameter and re-execute the previously prepared query;
	// if driver does not support that, prepared queries are emulated
        i=2;
	
	// it is necessary to rebind the parameters
	q.bind();
        DBSTEP::QueryResult* r2 = q.exec();
        if (r2->isEmpty() == true) std::cout << "\nError in isEmpty (1) !!";
 
        test1_print_fields(r2);
        test1_print_result(r2);
        delete r2;

        i=1000;
        q.bind();
	DBSTEP::QueryResult* r3 = q.exec();
        if (r3->isEmpty() == false) std::cout << "\nError in isEmpty (2) !!";
        delete r3;

        std::string p_name="pipo3";
        DBSTEP::Query q2(&db);
        q2 = "SELECT * from TestTable WHERE name = ", p_name;
	q2.prepare();
	q2.bind();
        
	DBSTEP::QueryResult* r4 = q2.exec();
        test1_print_result(r4);
        delete r4;
	
	p_name="pippo2"; 
	q2.bind();

	DBSTEP::QueryResult* r4b = q2.exec();
        test1_print_result(r4b);
        delete r4b;

	p_name="pippo"; 
	q2.bind();

	DBSTEP::QueryResult* r4c = q2.exec();
        test1_print_result(r4c);
        delete r4c;

        
	DBSTEP::Query q2b(&db);
        q2b = "SELECT * from TestTable WHERE name = ", p_name;
        p_name = "pippo2";
	DBSTEP::QueryResult* r4d = q2b.execImmediate();
        test1_print_result(r4d);
        delete r4d;
	
		
        // here we build a query with constant value of variable j ...
	
        int j=1;
	DBSTEP::Query q3(&db);
        q3= "SELECT * from TestTable WHERE id = ", DBSTEP::constValue(j);
        // q3= "SELECT * from TestTable WHERE id = ", j;
	q3.prepare();
        q3.bind();
        DBSTEP::QueryResult* r5= q3.exec();
        test1_print_result(r5);
        delete r5;
	
	// ... if we modify j value query remains the same
        j=2;
	q3.bind();
        DBSTEP::QueryResult* r6= q3.exec();
        test1_print_result(r6);
        delete r6;

        db.closeConnection();
    }
    catch (errException e)
    {
        std::cout << "\nERROR: " << DBSTEP::Params::instance()->getErrManager()->first()->getName() <<  std::endl;
    }
    
    // cleans up
    DBSTEP::Params::instance()->dispose();

#ifdef __BORLANDC__
    getch();
#endif

    return 0;
}



syntax highlighted by Code2HTML, v. 0.9.1