1 /*  $Id: dbapi_unit_test_stmt.cpp 556250 2018-01-29 14:12:00Z ucko $
2  * ===========================================================================
3  *
4  *                            PUBLIC DOMAIN NOTICE
5  *               National Center for Biotechnology Information
6  *
7  *  This software/database is a "United States Government Work" under the
8  *  terms of the United States Copyright Act.  It was written as part of
9  *  the author's official duties as a United States Government employee and
10  *  thus cannot be copyrighted.  This software/database is freely available
11  *  to the public for use. The National Library of Medicine and the U.S.
12  *  Government have not placed any restriction on its use or reproduction.
13  *
14  *  Although all reasonable efforts have been taken to ensure the accuracy
15  *  and reliability of the software and data, the NLM and the U.S.
16  *  Government do not and cannot warrant the performance or results that
17  *  may be obtained by using this software or data. The NLM and the U.S.
18  *  Government disclaim all warranties, express or implied, including
19  *  warranties of performance, merchantability or fitness for any particular
20  *  purpose.
21  *
22  *  Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author: Sergey Sikorskiy
27  *
28  * File Description: DBAPI unit-test
29  *
30  * ===========================================================================
31  */
32 
33 #include "dbapi_unit_test_pch.hpp"
34 
35 
36 BEGIN_NCBI_SCOPE
37 
38 ///////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_SelectStmt)39 BOOST_AUTO_TEST_CASE(Test_SelectStmt)
40 {
41     try {
42         // Scenario:
43         // 1) Select recordset with just one record
44         // 2) Retrive only one record.
45         // 3) Select another recordset with just one record
46         try {
47             unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
48             IResultSet* rs;
49 
50             // 1) Select recordset with just one record
51             rs = auto_stmt->ExecuteQuery( "select qq = 57 + 33" );
52             BOOST_REQUIRE( rs != NULL );
53 
54             // 2) Retrive a record.
55             BOOST_CHECK( rs->Next() );
56             BOOST_CHECK( !rs->Next() );
57 
58             // 3) Select another recordset with just one record
59             rs = auto_stmt->ExecuteQuery( "select qq = 57.55 + 0.0033" );
60             BOOST_REQUIRE( rs != NULL );
61             BOOST_CHECK( rs->Next() );
62             BOOST_CHECK( !rs->Next() );
63         } catch (boost::execution_aborted) {
64         }
65 
66         // Same as before but uses two differenr connections ...
67         if (false) try {
68             unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
69             IResultSet* rs;
70 
71             // 1) Select recordset with just one record
72             rs = auto_stmt->ExecuteQuery( "select qq = 57 + 33" );
73             BOOST_REQUIRE( rs != NULL );
74 
75             // 2) Retrive only one record.
76             BOOST_CHECK( rs->Next() );
77             BOOST_CHECK( !rs->Next() );
78 
79             // 3) Select another recordset with just one record
80             unique_ptr<IStatement> auto_stmt2( GetConnection().CreateStatement() );
81             rs = auto_stmt2->ExecuteQuery( "select qq = 57.55 + 0.0033" );
82             BOOST_REQUIRE( rs != NULL );
83             BOOST_CHECK( rs->Next() );
84             BOOST_CHECK( !rs->Next() );
85         } catch (boost::execution_aborted) {
86         }
87 
88         // Check column name ...
89         try {
90             unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
91 
92             IResultSet* rs(
93                 auto_stmt->ExecuteQuery( "select @@version as oops" )
94                 );
95             BOOST_REQUIRE( rs != NULL );
96             BOOST_CHECK( rs->Next() );
97             unique_ptr<const IResultSetMetaData> col_metadata(rs->GetMetaData());
98             BOOST_CHECK_EQUAL( string("oops"), col_metadata->GetName(1) );
99         } catch (boost::execution_aborted) {
100         }
101 
102         // Check resultset ...
103         try {
104             int num = 0;
105             string sql = "select user_id(), convert(varchar(64), user_name()), "
106                 "convert(nvarchar(64), user_name())";
107 
108             unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
109 
110             // 1) Select recordset with just one record
111             IResultSet* rs( auto_stmt->ExecuteQuery( sql ) );
112             BOOST_REQUIRE( rs != NULL );
113 
114             while (rs->Next()) {
115                 BOOST_CHECK(rs->GetVariant(1).GetInt4() > 0);
116                 BOOST_CHECK(rs->GetVariant(2).GetString().size() > 0);
117                 BOOST_CHECK(rs->GetVariant(3).GetString().size() > 0);
118                 ++num;
119             }
120 
121             BOOST_CHECK_EQUAL(num, 1);
122         } catch (boost::execution_aborted) {
123         }
124 
125         // Check sequent call of ExecuteQuery ...
126         if (true) {
127             IResultSet* rs = NULL;
128             unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
129 
130             // Run first time ...
131             rs = auto_stmt->ExecuteQuery( "select @@version as oops" );
132             BOOST_CHECK( rs != NULL );
133             if (rs != NULL) {
134                 BOOST_CHECK( rs->Next() );
135             }
136 
137             // Run second time ...
138             rs = auto_stmt->ExecuteQuery( "select @@version as oops" );
139             BOOST_CHECK( rs != NULL );
140             if (rs != NULL) {
141                 BOOST_CHECK( rs->Next() );
142             }
143 
144             // Run third time ...
145             rs = auto_stmt->ExecuteQuery( "select @@version as oops" );
146             BOOST_CHECK( rs != NULL );
147             if (rs != NULL) {
148                 BOOST_CHECK( rs->Next() );
149             }
150         } else {
151             GetArgs().PutMsgDisabled("Check sequent call of ExecuteQuery");
152         }
153 
154         // Select NULL values and empty strings ...
155         {
156             unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
157             unique_ptr<IResultSet> rs;
158 
159             rs.reset(
160                 auto_stmt->ExecuteQuery( "SELECT '', NULL, NULL, NULL" )
161                 );
162             BOOST_CHECK( rs.get() != NULL );
163             BOOST_CHECK( rs->Next() );
164 
165             rs.reset(
166                 auto_stmt->ExecuteQuery( "SELECT NULL, '', NULL, NULL" )
167                 );
168             BOOST_CHECK( rs.get() != NULL );
169             BOOST_CHECK( rs->Next() );
170 
171             rs.reset(
172                 auto_stmt->ExecuteQuery( "SELECT NULL, NULL, '', NULL" )
173                 );
174             BOOST_CHECK( rs.get() != NULL );
175             BOOST_CHECK( rs->Next() );
176 
177             rs.reset(
178                 auto_stmt->ExecuteQuery( "SELECT NULL, NULL, NULL, ''" )
179                 );
180             BOOST_CHECK( rs.get() != NULL );
181             BOOST_CHECK( rs->Next() );
182 
183             rs.reset(
184                 auto_stmt->ExecuteQuery( "SELECT '', '', NULL, NULL" )
185                 );
186             BOOST_CHECK( rs.get() != NULL );
187             BOOST_CHECK( rs->Next() );
188 
189             rs.reset(
190                 auto_stmt->ExecuteQuery( "SELECT NULL, '', '', NULL" )
191                 );
192             BOOST_CHECK( rs.get() != NULL );
193             BOOST_CHECK( rs->Next() );
194 
195             rs.reset(
196                 auto_stmt->ExecuteQuery( "SELECT NULL, NULL, '', ''" )
197                 );
198             BOOST_CHECK( rs.get() != NULL );
199             BOOST_CHECK( rs->Next() );
200         }
201 
202 
203     }
204     catch(const CException& ex) {
205         DBAPI_BOOST_FAIL(ex);
206     }
207 }
208 
209 
210 ///////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_SelectStmt2)211 BOOST_AUTO_TEST_CASE(Test_SelectStmt2)
212 {
213     string sql;
214     string table_name("#select_stmt2");
215 
216     try {
217         unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
218 
219         // Running parametrized statement ...
220         {
221             int result_num = 0;
222 
223             auto_stmt->SetParam( CVariant( "master" ), "@dbname" );
224 
225             auto_stmt->SendSql("exec sp_helpdb @dbname");
226 
227             while(auto_stmt->HasMoreResults()) {
228                 if( auto_stmt->HasRows() ) {
229                     ++result_num;
230                 }
231             }
232 
233             auto_stmt->ClearParamList();
234         }
235 
236         // Create table ...
237         {
238             sql =
239                 "CREATE TABLE " + table_name + " ( \n"
240                 "id INT NOT NULL PRIMARY KEY, \n"
241                 "name VARCHAR(255) NOT NULL \n"
242                 ")"
243                 ;
244 
245             auto_stmt->ExecuteUpdate(sql);
246         }
247 
248         // Insert data ...
249         {
250             sql  = "insert into ";
251             sql += table_name + "( id, name ) values ( 1, 'one' )";
252 
253             auto_stmt->ExecuteUpdate(sql);
254         }
255 
256         // Query data ...
257         {
258             sql  = "select id, name from ";
259             sql += table_name;
260 
261             auto_stmt->SendSql(sql);
262             while( auto_stmt->HasMoreResults() ) {
263                 if( auto_stmt->HasRows() ) {
264                     unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
265                     while( rs->Next() ) {
266                         ;
267                     }
268                 }
269             }
270         }
271     }
272     catch(const CException& ex) {
273         DBAPI_BOOST_FAIL(ex);
274     }
275 }
276 
277 ///////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_SelectStmtXML)278 BOOST_AUTO_TEST_CASE(Test_SelectStmtXML)
279 {
280     try {
281         // SQL + XML
282         {
283             string sql;
284             unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
285             IResultSet* rs;
286 
287             sql = "select 1 as Tag, null as Parent, 1 as [x!1!id] for xml explicit";
288             rs = auto_stmt->ExecuteQuery( sql );
289             BOOST_REQUIRE( rs != NULL );
290 
291             if ( !rs->Next() ) {
292                 BOOST_FAIL( msg_record_expected );
293             }
294 
295             // Same but call Execute instead of ExecuteQuery.
296             auto_stmt->SendSql( sql );
297         }
298     }
299     catch(const CException& ex) {
300         DBAPI_BOOST_FAIL(ex);
301     }
302 }
303 
304 ///////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_Recordset)305 BOOST_AUTO_TEST_CASE(Test_Recordset)
306 {
307     try {
308         unique_ptr<IStatement> auto_stmt(GetConnection().GetStatement());
309         IResultSet* rs;
310 
311         // First test ...
312         {
313             // bit
314             try {
315                 rs = auto_stmt->ExecuteQuery("select convert(bit, 1)");
316                 BOOST_REQUIRE(rs != NULL);
317 
318                 BOOST_CHECK(rs->Next());
319                 BOOST_CHECK(!rs->Next());
320 
321                 DumpResults(auto_stmt.get());
322             } catch (boost::execution_aborted) {
323             }
324 
325             // tinyint
326             try {
327                 rs = auto_stmt->ExecuteQuery("select convert(tinyint, 1)");
328                 BOOST_REQUIRE(rs != NULL);
329 
330                 BOOST_CHECK(rs->Next());
331                 BOOST_CHECK(!rs->Next());
332 
333                 DumpResults(auto_stmt.get());
334             } catch (boost::execution_aborted) {
335             }
336 
337             // smallint
338             try {
339                 rs = auto_stmt->ExecuteQuery("select convert(smallint, 1)");
340                 BOOST_REQUIRE(rs != NULL);
341 
342                 BOOST_CHECK(rs->Next());
343                 BOOST_CHECK(!rs->Next());
344 
345                 DumpResults(auto_stmt.get());
346             } catch (boost::execution_aborted) {
347             }
348 
349             // int
350             try {
351                 rs = auto_stmt->ExecuteQuery("select convert(int, 1)");
352                 BOOST_REQUIRE(rs != NULL);
353 
354                 BOOST_CHECK(rs->Next());
355                 BOOST_CHECK(!rs->Next());
356 
357                 DumpResults(auto_stmt.get());
358             } catch (boost::execution_aborted) {
359             }
360 
361             // numeric
362             {
363                 //
364                 try {
365                     rs = auto_stmt->ExecuteQuery("select convert(numeric(38, 0), 1)");
366                     BOOST_REQUIRE(rs != NULL);
367 
368                     BOOST_CHECK(rs->Next());
369                     BOOST_CHECK(!rs->Next());
370 
371                     DumpResults(auto_stmt.get());
372                 } catch (boost::execution_aborted) {
373                 }
374 
375                 //
376                 try {
377                     rs = auto_stmt->ExecuteQuery("select convert(numeric(18, 2), 2843113322)");
378                     BOOST_REQUIRE(rs != NULL);
379 
380                     BOOST_CHECK(rs->Next());
381                     BOOST_CHECK(!rs->Next());
382 
383                     DumpResults(auto_stmt.get());
384                 } catch (boost::execution_aborted) {
385                 }
386             }
387 
388             // decimal
389             try {
390                 rs = auto_stmt->ExecuteQuery("select convert(decimal(38, 0), 1)");
391                 BOOST_REQUIRE(rs != NULL);
392 
393                 BOOST_CHECK(rs->Next());
394                 BOOST_CHECK(!rs->Next());
395 
396                 DumpResults(auto_stmt.get());
397             } catch (boost::execution_aborted) {
398             }
399 
400             // float
401             try {
402                 rs = auto_stmt->ExecuteQuery("select convert(float(4), 1)");
403                 BOOST_REQUIRE(rs != NULL);
404 
405                 BOOST_CHECK(rs->Next());
406                 BOOST_CHECK(!rs->Next());
407 
408                 DumpResults(auto_stmt.get());
409             } catch (boost::execution_aborted) {
410             }
411 
412             // double
413             try {
414                 rs = auto_stmt->ExecuteQuery("select convert(double precision, 1)");
415                 BOOST_REQUIRE(rs != NULL);
416 
417                 BOOST_CHECK(rs->Next());
418                 BOOST_CHECK(!rs->Next());
419 
420                 DumpResults(auto_stmt.get());
421             } catch (boost::execution_aborted) {
422             }
423 
424             // real
425             try {
426                 rs = auto_stmt->ExecuteQuery("select convert(real, 1)");
427                 BOOST_REQUIRE(rs != NULL);
428 
429                 BOOST_CHECK(rs->Next());
430                 BOOST_CHECK(!rs->Next());
431 
432                 DumpResults(auto_stmt.get());
433             } catch (boost::execution_aborted) {
434             }
435 
436             // smallmoney
437             // Unsupported type ...
438         //     try {
439         //         rs = auto_stmt->ExecuteQuery("select convert(smallmoney, 1)");
440         //         BOOST_REQUIRE(rs != NULL);
441         //
442         //         BOOST_CHECK(rs->Next());
443         //         BOOST_CHECK(!rs->Next());
444         //
445         //         DumpResults(auto_stmt.get());
446         //     } catch (boost::execution_aborted) {
447         //     }
448 
449             // money
450             // Unsupported type ...
451         //     try {
452         //         rs = auto_stmt->ExecuteQuery("select convert(money, 1)");
453         //         BOOST_REQUIRE(rs != NULL);
454         //
455         //         BOOST_CHECK(rs->Next());
456         //         BOOST_CHECK(!rs->Next());
457         //
458         //         DumpResults(auto_stmt.get());
459         //     } catch (boost::execution_aborted) {
460         //     }
461 
462             // smalldatetime
463             try {
464                 rs = auto_stmt->ExecuteQuery("select convert(smalldatetime, 'January 1, 1900')");
465                 BOOST_REQUIRE(rs != NULL);
466 
467                 BOOST_CHECK(rs->Next());
468                 BOOST_CHECK(!rs->Next());
469 
470                 DumpResults(auto_stmt.get());
471             } catch (boost::execution_aborted) {
472             }
473 
474             // datetime
475             try {
476                 rs = auto_stmt->ExecuteQuery("select convert(datetime, 'January 1, 1753')");
477                 BOOST_REQUIRE(rs != NULL);
478 
479                 BOOST_CHECK(rs->Next());
480                 BOOST_CHECK(!rs->Next());
481 
482                 DumpResults(auto_stmt.get());
483             } catch (boost::execution_aborted) {
484             }
485 
486             // char
487             try {
488                 rs = auto_stmt->ExecuteQuery("select convert(char(32), '12345')");
489                 BOOST_REQUIRE(rs != NULL);
490 
491                 BOOST_CHECK(rs->Next());
492                 BOOST_CHECK(!rs->Next());
493 
494                 DumpResults(auto_stmt.get());
495             } catch (boost::execution_aborted) {
496             }
497 
498             // varchar
499             try {
500                 rs = auto_stmt->ExecuteQuery("select convert(varchar(32), '12345')");
501                 BOOST_REQUIRE(rs != NULL);
502 
503                 BOOST_CHECK(rs->Next());
504                 BOOST_CHECK(!rs->Next());
505 
506                 DumpResults(auto_stmt.get());
507             } catch (boost::execution_aborted) {
508             }
509 
510             // nchar
511             try {
512                 rs = auto_stmt->ExecuteQuery("select convert(nchar(32), '12345')");
513                 BOOST_REQUIRE(rs != NULL);
514 
515                 BOOST_CHECK(rs->Next());
516                 BOOST_CHECK(!rs->Next());
517 
518                 DumpResults(auto_stmt.get());
519             } catch (boost::execution_aborted) {
520             }
521 
522             // nvarchar
523             try {
524                 rs = auto_stmt->ExecuteQuery("select convert(nvarchar(32), '12345')");
525                 BOOST_REQUIRE(rs != NULL);
526 
527                 BOOST_CHECK(rs->Next());
528                 BOOST_CHECK(!rs->Next());
529 
530                 DumpResults(auto_stmt.get());
531             } catch (boost::execution_aborted) {
532             }
533 
534             // binary
535             try {
536                 rs = auto_stmt->ExecuteQuery("select convert(binary(32), '12345')");
537                 BOOST_REQUIRE(rs != NULL);
538 
539                 BOOST_CHECK(rs->Next());
540                 BOOST_CHECK(!rs->Next());
541 
542                 DumpResults(auto_stmt.get());
543             } catch (boost::execution_aborted) {
544             }
545 
546             // varbinary
547             try {
548                 rs = auto_stmt->ExecuteQuery("select convert(varbinary(32), '12345')");
549                 BOOST_REQUIRE(rs != NULL);
550 
551                 BOOST_CHECK(rs->Next());
552                 BOOST_CHECK(!rs->Next());
553 
554                 DumpResults(auto_stmt.get());
555             } catch (boost::execution_aborted) {
556             }
557 
558             // text
559             try {
560                 rs = auto_stmt->ExecuteQuery("select convert(text, '12345')");
561                 BOOST_REQUIRE(rs != NULL);
562 
563                 BOOST_CHECK(rs->Next());
564                 BOOST_CHECK(!rs->Next());
565 
566                 DumpResults(auto_stmt.get());
567             } catch (boost::execution_aborted) {
568             }
569 
570             // image
571             try {
572                 rs = auto_stmt->ExecuteQuery("select convert(image, '12345')");
573                 BOOST_REQUIRE(rs != NULL);
574 
575                 BOOST_CHECK(rs->Next());
576                 BOOST_CHECK(!rs->Next());
577 
578                 DumpResults(auto_stmt.get());
579             } catch (boost::execution_aborted) {
580             }
581         }
582 
583         // Second test ...
584         {
585             // bit
586             try {
587                 rs = auto_stmt->ExecuteQuery("select convert(bit, 1)");
588                 BOOST_REQUIRE(rs != NULL);
589 
590                 BOOST_CHECK(rs->Next());
591                 const CVariant& variant = rs->GetVariant(1);
592 
593                 CDB_Bit* data = dynamic_cast<CDB_Bit*>(variant.GetData());
594                 BOOST_REQUIRE(data != NULL);
595 
596                 BOOST_CHECK_EQUAL(data->Value(), 1);
597 
598                 DumpResults(auto_stmt.get());
599             } catch (boost::execution_aborted) {
600             }
601 
602             // tinyint
603             try {
604                 rs = auto_stmt->ExecuteQuery("select convert(tinyint, 1)");
605                 BOOST_REQUIRE(rs != NULL);
606 
607                 BOOST_CHECK(rs->Next());
608                 const CVariant& variant = rs->GetVariant(1);
609 
610                 CDB_TinyInt* data = dynamic_cast<CDB_TinyInt*>(variant.GetData());
611                 BOOST_REQUIRE(data != NULL);
612 
613                 BOOST_CHECK_EQUAL(data->Value(), 1);
614 
615                 DumpResults(auto_stmt.get());
616             } catch (boost::execution_aborted) {
617             }
618 
619             // smallint
620             try {
621                 rs = auto_stmt->ExecuteQuery("select convert(smallint, 1)");
622                 BOOST_REQUIRE(rs != NULL);
623 
624                 BOOST_CHECK(rs->Next());
625                 const CVariant& variant = rs->GetVariant(1);
626 
627                 CDB_SmallInt* data = dynamic_cast<CDB_SmallInt*>(variant.GetData());
628                 BOOST_REQUIRE(data != NULL);
629 
630                 BOOST_CHECK_EQUAL(data->Value(), 1);
631 
632                 DumpResults(auto_stmt.get());
633             } catch (boost::execution_aborted) {
634             }
635 
636             // int
637             try {
638                 rs = auto_stmt->ExecuteQuery("select convert(int, 1)");
639                 BOOST_REQUIRE(rs != NULL);
640 
641                 BOOST_CHECK(rs->Next());
642                 const CVariant& variant = rs->GetVariant(1);
643 
644                 CDB_Int* data = dynamic_cast<CDB_Int*>(variant.GetData());
645                 BOOST_REQUIRE(data != NULL);
646 
647                 BOOST_CHECK_EQUAL(data->Value(), 1);
648 
649                 DumpResults(auto_stmt.get());
650             } catch (boost::execution_aborted) {
651             }
652 
653             // numeric
654             {
655                 //
656                 try {
657                     rs = auto_stmt->ExecuteQuery("select convert(numeric(38, 0), 1)");
658                     BOOST_REQUIRE(rs != NULL);
659 
660                     BOOST_CHECK(rs->Next());
661                     const CVariant& variant = rs->GetVariant(1);
662 
663                     switch(variant.GetData()->GetType()) {
664                         case eDB_Numeric:
665                             {
666                                 CDB_Numeric* data = static_cast<CDB_Numeric*>(variant.GetData());
667                                 BOOST_CHECK_EQUAL(data->Value(), string("1"));
668                             }
669                             break;
670                         case eDB_Double:
671                             {
672                                 GetArgs().PutMsgExpected("CDB_Numeric", "CDB_Double");
673 
674                                 CDB_Double* data = static_cast<CDB_Double*>(variant.GetData());
675                                 BOOST_CHECK_EQUAL(data->Value(), 1);
676                             }
677                             break;
678                         default:
679                             BOOST_FAIL("Invalid data type.");
680                     }
681 
682                     DumpResults(auto_stmt.get());
683                 } catch (boost::execution_aborted) {
684                 }
685 
686                 //
687                 try {
688                     rs = auto_stmt->ExecuteQuery("select convert(numeric(18, 2), 2843113322)");
689                     BOOST_REQUIRE(rs != NULL);
690 
691                     BOOST_CHECK(rs->Next());
692                     const CVariant& variant = rs->GetVariant(1);
693 
694                     switch(variant.GetData()->GetType()) {
695                         case eDB_Numeric:
696                             {
697                                 CDB_Numeric* data = static_cast<CDB_Numeric*>(variant.GetData());
698 
699                                 if (GetArgs().IsODBCBased()) {
700                                     BOOST_CHECK_EQUAL(data->Value(), string("2843113322"));
701                                 } else {
702                                     BOOST_CHECK_EQUAL(data->Value(), string("2843113322.00"));
703                                 }
704                             }
705                             break;
706                         case eDB_Double:
707                             {
708                                 GetArgs().PutMsgExpected("CDB_Numeric", "CDB_Double");
709 
710                                 CDB_Double* data = static_cast<CDB_Double*>(variant.GetData());
711                                 BOOST_CHECK_EQUAL(data->Value(), 2843113322U);
712                             }
713                             break;
714                         default:
715                             BOOST_FAIL("Invalid data type.");
716                     }
717 
718                     DumpResults(auto_stmt.get());
719                 } catch (boost::execution_aborted) {
720                 }
721             }
722 
723             // decimal
724             try {
725                 rs = auto_stmt->ExecuteQuery("select convert(decimal(38, 0), 1)");
726                 BOOST_REQUIRE(rs != NULL);
727 
728                 BOOST_CHECK(rs->Next());
729                 const CVariant& variant = rs->GetVariant(1);
730 
731                 switch(variant.GetData()->GetType()) {
732                     case eDB_Numeric:
733                         {
734                             CDB_Numeric* data = static_cast<CDB_Numeric*>(variant.GetData());
735                             BOOST_CHECK_EQUAL(data->Value(), string("1"));
736                         }
737                         break;
738                     case eDB_Double:
739                         {
740                             GetArgs().PutMsgExpected("CDB_Numeric", "CDB_Double");
741 
742                             CDB_Double* data = static_cast<CDB_Double*>(variant.GetData());
743                             BOOST_CHECK_EQUAL(data->Value(), 1);
744                         }
745                         break;
746                     default:
747                         BOOST_FAIL("Invalid data type.");
748                 }
749 
750                 // CDB_Numeric* data = dynamic_cast<CDB_Numeric*>(variant.GetData());
751                 // BOOST_REQUIRE(data != NULL);
752 
753                 // BOOST_CHECK_EQUAL(data->Value(), string("1"));
754 
755                 DumpResults(auto_stmt.get());
756             } catch (boost::execution_aborted) {
757             }
758 
759             // float
760             try {
761                 rs = auto_stmt->ExecuteQuery("select convert(float(4), 1)");
762                 BOOST_REQUIRE(rs != NULL);
763 
764                 BOOST_CHECK(rs->Next());
765                 const CVariant& variant = rs->GetVariant(1);
766 
767                 //
768                 CDB_Float* float_data = NULL;
769                 float_data = dynamic_cast<CDB_Float*>(variant.GetData());
770 
771                 if (float_data) {
772                     // GetArgs().PutMsgExpected("CDB_Double", "CDB_Float");
773                     BOOST_CHECK_EQUAL(float_data->Value(), 1);
774                 }
775 
776                 //
777                 CDB_Double* double_data = NULL;
778                 double_data = dynamic_cast<CDB_Double*>(variant.GetData());
779 
780                 if (double_data) {
781                     GetArgs().PutMsgExpected("CDB_Float", "CDB_Double");
782                     BOOST_CHECK_EQUAL(double_data->Value(), 1);
783                 }
784 
785                 DumpResults(auto_stmt.get());
786             } catch (boost::execution_aborted) {
787             }
788 
789             // double
790             {
791                 //
792                 try {
793                     rs = auto_stmt->ExecuteQuery("select convert(double precision, 1)");
794                     BOOST_REQUIRE(rs != NULL);
795 
796                     BOOST_CHECK(rs->Next());
797                     const CVariant& variant = rs->GetVariant(1);
798 
799                     CDB_Double* data = dynamic_cast<CDB_Double*>(variant.GetData());
800                     BOOST_REQUIRE(data != NULL);
801 
802                     BOOST_CHECK_EQUAL(data->Value(), 1);
803 
804                     DumpResults(auto_stmt.get());
805                 } catch (boost::execution_aborted) {
806                 }
807 
808                 //
809                 try {
810                     rs = auto_stmt->ExecuteQuery("select convert(double precision, 2843113322)");
811                     BOOST_REQUIRE(rs != NULL);
812 
813                     BOOST_CHECK(rs->Next());
814                     const CVariant& variant = rs->GetVariant(1);
815 
816                     CDB_Double* data = dynamic_cast<CDB_Double*>(variant.GetData());
817                     BOOST_REQUIRE(data != NULL);
818 
819                     BOOST_CHECK_EQUAL(data->Value(), 2843113322U);
820 
821                     DumpResults(auto_stmt.get());
822                 } catch (boost::execution_aborted) {
823                 }
824             }
825 
826             // real
827             try {
828                 rs = auto_stmt->ExecuteQuery("select convert(real, 1)");
829                 BOOST_REQUIRE(rs != NULL);
830 
831                 BOOST_CHECK(rs->Next());
832                 const CVariant& variant = rs->GetVariant(1);
833 
834                 CDB_Float* data = dynamic_cast<CDB_Float*>(variant.GetData());
835                 BOOST_REQUIRE(data != NULL);
836 
837                 BOOST_CHECK_EQUAL(data->Value(), 1);
838 
839                 DumpResults(auto_stmt.get());
840             } catch (boost::execution_aborted) {
841             }
842 
843             // smallmoney
844             // Unsupported type ...
845         //     try {
846         //         rs = auto_stmt->ExecuteQuery("select convert(smallmoney, 1)");
847         //         BOOST_REQUIRE(rs != NULL);
848         //
849         //         BOOST_CHECK(rs->Next());
850         //         BOOST_CHECK(!rs->Next());
851         //
852         //         DumpResults(auto_stmt.get());
853         //     } catch (boost::execution_aborted) {
854         //     }
855 
856             // money
857             // Unsupported type ...
858         //     try {
859         //         rs = auto_stmt->ExecuteQuery("select convert(money, 1)");
860         //         BOOST_REQUIRE(rs != NULL);
861         //
862         //         BOOST_CHECK(rs->Next());
863         //         BOOST_CHECK(!rs->Next());
864         //
865         //         DumpResults(auto_stmt.get());
866         //     } catch (boost::execution_aborted) {
867         //     }
868 
869             // smalldatetime
870             try {
871                 rs = auto_stmt->ExecuteQuery("select convert(smalldatetime, 'January 1, 1900')");
872                 BOOST_REQUIRE(rs != NULL);
873 
874                 BOOST_CHECK(rs->Next());
875                 const CVariant& variant = rs->GetVariant(1);
876 
877                 CDB_SmallDateTime* data = dynamic_cast<CDB_SmallDateTime*>(variant.GetData());
878                 BOOST_REQUIRE(data != NULL);
879 
880                 // BOOST_CHECK_EQUAL(data->Value(), 1);
881 
882                 DumpResults(auto_stmt.get());
883             } catch (boost::execution_aborted) {
884             }
885 
886             // datetime
887             try {
888                 rs = auto_stmt->ExecuteQuery("select convert(datetime, 'January 1, 1753')");
889                 BOOST_REQUIRE(rs != NULL);
890 
891                 BOOST_CHECK(rs->Next());
892                 const CVariant& variant = rs->GetVariant(1);
893 
894                 CDB_DateTime* dt_data = NULL;
895                 dt_data = dynamic_cast<CDB_DateTime*>(variant.GetData());
896 
897                 if (!dt_data){
898                     GetArgs().PutMsgExpected("CDB_DateTime", "CDB_SmallDateTime");
899 
900                     CDB_SmallDateTime* data = dynamic_cast<CDB_SmallDateTime*>(variant.GetData());
901                     BOOST_REQUIRE(data != NULL);
902                 }
903 
904                 // BOOST_CHECK_EQUAL(data->Value(), 1);
905 
906                 DumpResults(auto_stmt.get());
907             } catch (boost::execution_aborted) {
908             }
909 
910             // char
911             try {
912                 rs = auto_stmt->ExecuteQuery("select convert(char(10), '12345')");
913                 BOOST_REQUIRE(rs != NULL);
914 
915                 BOOST_CHECK(rs->Next());
916                 const CVariant& variant = rs->GetVariant(1);
917 
918                 //
919                 CDB_Char* char_data = NULL;
920                 char_data = dynamic_cast<CDB_Char*>(variant.GetData());
921 
922                 if(char_data) {
923                     BOOST_CHECK_EQUAL(char_data->AsString(),
924                                       string("12345     "));
925                 }
926 
927                 //
928                 CDB_VarChar* varchar_data = NULL;
929                 varchar_data = dynamic_cast<CDB_VarChar*>(variant.GetData());
930 
931                 if(varchar_data) {
932                     GetArgs().PutMsgExpected("CDB_Char", "CDB_VarChar");
933 
934                     BOOST_CHECK_EQUAL(varchar_data->AsString(),
935                                       string("12345     "));
936                 }
937 
938                 //
939                 CDB_LongChar* longchar_data = NULL;
940                 longchar_data = dynamic_cast<CDB_LongChar*>(variant.GetData());
941 
942                 if(longchar_data) {
943                     GetArgs().PutMsgExpected("CDB_Char", "CDB_LongChar");
944 
945                     BOOST_CHECK_EQUAL(longchar_data->Size(), size_t(10));
946                     BOOST_CHECK_EQUAL(longchar_data->AsString(),
947                             string("12345     ")
948                             );
949                 }
950 
951 
952                 DumpResults(auto_stmt.get());
953             } catch (boost::execution_aborted) {
954             }
955 
956             // varchar
957             try {
958                 rs = auto_stmt->ExecuteQuery("select convert(varchar(10), '12345')");
959                 BOOST_REQUIRE(rs != NULL);
960 
961                 BOOST_CHECK(rs->Next());
962                 const CVariant& variant = rs->GetVariant(1);
963 
964                 //
965                 CDB_Char* char_data = NULL;
966                 char_data = dynamic_cast<CDB_Char*>(variant.GetData());
967 
968                 if(char_data) {
969                     GetArgs().PutMsgExpected("CDB_VarChar", "CDB_Char");
970 
971                     BOOST_CHECK_EQUAL(char_data->AsString(),
972                                       string("12345     "));
973                 }
974 
975                 //
976                 CDB_VarChar* varchar_data = NULL;
977                 varchar_data = dynamic_cast<CDB_VarChar*>(variant.GetData());
978 
979                 if (varchar_data) {
980                     BOOST_CHECK_EQUAL(varchar_data->AsString(),
981                                       string("12345"));
982                 }
983 
984                 //
985                 CDB_LongChar* longchar_data = NULL;
986                 longchar_data = dynamic_cast<CDB_LongChar*>(variant.GetData());
987 
988                 if(longchar_data) {
989                     GetArgs().PutMsgExpected("CDB_VarChar", "CDB_LongChar");
990 
991                     BOOST_CHECK_EQUAL(longchar_data->Size(), size_t(32));
992                     BOOST_CHECK_EQUAL(longchar_data->AsString(),
993                             string("12345     ")
994                             );
995                 }
996 
997                 DumpResults(auto_stmt.get());
998             } catch (boost::execution_aborted) {
999             }
1000 
1001             // nchar
1002             try {
1003                 rs = auto_stmt->ExecuteQuery("select convert(nchar(10), '12345')");
1004                 BOOST_REQUIRE(rs != NULL);
1005 
1006                 BOOST_CHECK(rs->Next());
1007                 const CVariant& variant = rs->GetVariant(1);
1008 
1009                 CDB_Char* char_data = NULL;
1010                 char_data = dynamic_cast<CDB_Char*>(variant.GetData());
1011 
1012                 if(char_data) {
1013                     BOOST_CHECK_EQUAL(char_data->AsString(),
1014                                       string("12345     "));
1015                 }
1016 
1017                 CDB_VarChar* varchar_data = NULL;
1018                 varchar_data = dynamic_cast<CDB_VarChar*>(variant.GetData());
1019 
1020                 if(varchar_data) {
1021                     GetArgs().PutMsgExpected("CDB_Char", "CDB_VarChar");
1022 
1023                     BOOST_CHECK_EQUAL(varchar_data->AsString(),
1024                                       string("12345     "));
1025                 }
1026 
1027                 CDB_LongChar* longchar_data = NULL;
1028                 longchar_data = dynamic_cast<CDB_LongChar*>(variant.GetData());
1029 
1030                 if(longchar_data) {
1031                     GetArgs().PutMsgExpected("CDB_Char", "CDB_LongChar");
1032 
1033                     BOOST_CHECK_EQUAL(longchar_data->Size(), size_t(10));
1034                     BOOST_CHECK_EQUAL(longchar_data->AsString(),
1035                             string("12345     ")
1036                             );
1037                 }
1038 
1039                 DumpResults(auto_stmt.get());
1040             } catch (boost::execution_aborted) {
1041             }
1042 
1043             // nvarchar
1044             try {
1045                 rs = auto_stmt->ExecuteQuery("select convert(nvarchar(10), '12345')");
1046                 BOOST_REQUIRE(rs != NULL);
1047 
1048                 BOOST_CHECK(rs->Next());
1049                 const CVariant& variant = rs->GetVariant(1);
1050 
1051                 //
1052                 CDB_Char* char_data = NULL;
1053                 char_data = dynamic_cast<CDB_Char*>(variant.GetData());
1054 
1055                 if(char_data) {
1056                     GetArgs().PutMsgExpected("CDB_VarChar", "CDB_Char");
1057 
1058                     BOOST_CHECK_EQUAL(char_data->AsString(),
1059                                       string("12345     "));
1060                 }
1061 
1062                 //
1063                 CDB_VarChar* varchar_data = NULL;
1064                 varchar_data = dynamic_cast<CDB_VarChar*>(variant.GetData());
1065 
1066                 if (varchar_data) {
1067                     BOOST_CHECK_EQUAL(varchar_data->AsString(),
1068                                       string("12345"));
1069                 }
1070 
1071                 //
1072                 CDB_LongChar* longchar_data = NULL;
1073                 longchar_data = dynamic_cast<CDB_LongChar*>(variant.GetData());
1074 
1075                 if(longchar_data) {
1076                     GetArgs().PutMsgExpected("CDB_VarChar", "CDB_LongChar");
1077 
1078                     BOOST_CHECK_EQUAL(longchar_data->Size(), size_t(32));
1079                     BOOST_CHECK_EQUAL(longchar_data->AsString(),
1080                             string("12345     ")
1081                             );
1082                 }
1083 
1084                 DumpResults(auto_stmt.get());
1085             } catch (boost::execution_aborted) {
1086             }
1087 
1088             // binary
1089             try {
1090                 rs = auto_stmt->ExecuteQuery("select convert(binary(10), '12345')");
1091                 BOOST_REQUIRE(rs != NULL);
1092 
1093                 BOOST_CHECK(rs->Next());
1094                 const CVariant& variant = rs->GetVariant(1);
1095 
1096                 //
1097                 CDB_Binary* char_data = NULL;
1098                 char_data = dynamic_cast<CDB_Binary*>(variant.GetData());
1099 
1100                 if(char_data) {
1101                     BOOST_CHECK_EQUAL(char_data->Size(), size_t(10));
1102                     // BOOST_CHECK_EQUAL(string(static_cast<const char*>(char_data->Value()),
1103                     //             char_data->Size()),
1104                     //         string("12345")
1105                     //         );
1106                     BOOST_CHECK_EQUAL(
1107                         memcmp(
1108                             char_data->Value(),
1109                             "12345\0\0\0\0\0",
1110                             char_data->Size()
1111                             ),
1112                         0
1113                         );
1114                 }
1115 
1116                 //
1117                 CDB_VarBinary* varchar_data = NULL;
1118                 varchar_data = dynamic_cast<CDB_VarBinary*>(variant.GetData());
1119 
1120                 if(varchar_data) {
1121                     GetArgs().PutMsgExpected("CDB_Binary", "CDB_VarBinary");
1122 
1123                     BOOST_CHECK_EQUAL(varchar_data->Size(), size_t(10));
1124                     // BOOST_CHECK_EQUAL(string(static_cast<const char*>(varchar_data->Value()),
1125                     //             varchar_data->Size()),
1126                     //         string("12345")
1127                     //         );
1128                     BOOST_CHECK_EQUAL(
1129                         memcmp(
1130                             varchar_data->Value(),
1131                             "12345\0\0\0\0\0",
1132                             varchar_data->Size()
1133                             ),
1134                         0
1135                         );
1136                 }
1137 
1138                 //
1139                 CDB_LongBinary* longchar_data = NULL;
1140                 longchar_data = dynamic_cast<CDB_LongBinary*>(variant.GetData());
1141 
1142                 if(longchar_data) {
1143                     GetArgs().PutMsgExpected("CDB_Binary", "CDB_LongBinary");
1144 
1145                     BOOST_CHECK_EQUAL(longchar_data->Size(), size_t(32));
1146                     BOOST_CHECK_EQUAL(string(static_cast<const char*>(longchar_data->Value()),
1147                                 longchar_data->Size()),
1148                             string("12345     ")
1149                             );
1150                 }
1151 
1152                 DumpResults(auto_stmt.get());
1153             } catch (boost::execution_aborted) {
1154             }
1155 
1156             // long binary
1157             try {
1158                 rs = auto_stmt->ExecuteQuery("select convert(binary(1000), '12345')");
1159                 BOOST_REQUIRE(rs != NULL);
1160 
1161                 BOOST_CHECK(rs->Next());
1162                 const CVariant& variant = rs->GetVariant(1);
1163 
1164                 //
1165                 CDB_Binary* char_data = NULL;
1166                 char_data = dynamic_cast<CDB_Binary*>(variant.GetData());
1167 
1168                 if(char_data) {
1169                     GetArgs().PutMsgExpected("CDB_LongBinary", "CDB_Binary");
1170 
1171                     BOOST_CHECK_EQUAL(string(static_cast<const char*>(char_data->Value()),
1172                                 char_data->Size()),
1173                             string("12345")
1174                             );
1175                 }
1176 
1177                 //
1178                 CDB_VarBinary* varchar_data = NULL;
1179                 varchar_data = dynamic_cast<CDB_VarBinary*>(variant.GetData());
1180 
1181                 if(varchar_data) {
1182                     GetArgs().PutMsgExpected("CDB_LongBinary", "CDB_VarBinary");
1183 
1184                     BOOST_CHECK_EQUAL(varchar_data->Size(), size_t(1000));
1185                     // BOOST_CHECK_EQUAL(string(static_cast<const char*>(varchar_data->Value()),
1186                     //             varchar_data->Size()),
1187                     //         string("12345")
1188                     //         );
1189                     BOOST_CHECK_EQUAL(
1190                         memcmp(
1191                             varchar_data->Value(),
1192                             "12345\0\0\0\0\0",
1193                             10
1194                             ),
1195                         0
1196                         );
1197                 }
1198 
1199                 //
1200                 CDB_LongBinary* longchar_data = NULL;
1201                 longchar_data = dynamic_cast<CDB_LongBinary*>(variant.GetData());
1202 
1203                 if(longchar_data) {
1204                     BOOST_CHECK_EQUAL(longchar_data->Size(), size_t(1000));
1205                     // BOOST_CHECK_EQUAL(string(static_cast<const char*>(longchar_data->Value()),
1206                     //             longchar_data->Size()),
1207                     //         string("12345")
1208                     //         );
1209                     BOOST_CHECK_EQUAL(
1210                         memcmp(
1211                             longchar_data->Value(),
1212                             "12345\0\0\0\0\0",
1213                             10
1214                             ),
1215                         0
1216                         );
1217                 }
1218 
1219                 DumpResults(auto_stmt.get());
1220             } catch (boost::execution_aborted) {
1221             }
1222 
1223             // varbinary
1224             try {
1225                 rs = auto_stmt->ExecuteQuery("select convert(varbinary(10), '12345')");
1226                 BOOST_REQUIRE(rs != NULL);
1227 
1228                 BOOST_CHECK(rs->Next());
1229                 const CVariant& variant = rs->GetVariant(1);
1230 
1231                 //
1232                 CDB_Binary* char_data = NULL;
1233                 char_data = dynamic_cast<CDB_Binary*>(variant.GetData());
1234 
1235                 if(char_data) {
1236                     GetArgs().PutMsgExpected("CDB_VarBinary", "CDB_Binary");
1237 
1238                     BOOST_CHECK_EQUAL(string(static_cast<const char*>(char_data->Value()),
1239                                 char_data->Size()),
1240                             string("12345")
1241                             );
1242                 }
1243 
1244                 //
1245                 CDB_VarBinary* data = dynamic_cast<CDB_VarBinary*>(variant.GetData());
1246                 BOOST_REQUIRE(data != NULL);
1247 
1248                 BOOST_CHECK_EQUAL(data->Size(), size_t(5));
1249                 BOOST_CHECK_EQUAL(string(static_cast<const char*>(data->Value()),
1250                             data->Size()),
1251                         string("12345")
1252                         );
1253 
1254                 //
1255                 CDB_LongBinary* longchar_data = NULL;
1256                 longchar_data = dynamic_cast<CDB_LongBinary*>(variant.GetData());
1257 
1258                 if(longchar_data) {
1259                     GetArgs().PutMsgExpected("CDB_VarBinary", "CDB_LongBinary");
1260 
1261                     BOOST_CHECK_EQUAL(longchar_data->Size(), size_t(10));
1262                     BOOST_CHECK_EQUAL(string(static_cast<const char*>(longchar_data->Value()),
1263                                 longchar_data->Size()),
1264                             string("12345")
1265                             );
1266                 }
1267 
1268                 DumpResults(auto_stmt.get());
1269             } catch (boost::execution_aborted) {
1270             }
1271 
1272             // text
1273             try {
1274                 rs = auto_stmt->ExecuteQuery("select convert(text, '12345')");
1275                 BOOST_REQUIRE(rs != NULL);
1276 
1277                 BOOST_CHECK(rs->Next());
1278                 const CVariant& variant = rs->GetVariant(1);
1279 
1280                 CDB_Text* data = dynamic_cast<CDB_Text*>(variant.GetData());
1281                 BOOST_REQUIRE(data != NULL);
1282 
1283                 // BOOST_CHECK_EQUAL(data->Value(), 1);
1284 
1285                 DumpResults(auto_stmt.get());
1286             } catch (boost::execution_aborted) {
1287             }
1288 
1289             // image
1290             try {
1291                 rs = auto_stmt->ExecuteQuery("select convert(image, '12345')");
1292                 BOOST_REQUIRE(rs != NULL);
1293 
1294                 BOOST_CHECK(rs->Next());
1295                 const CVariant& variant = rs->GetVariant(1);
1296 
1297                 CDB_Image* data = dynamic_cast<CDB_Image*>(variant.GetData());
1298                 BOOST_REQUIRE(data != NULL);
1299 
1300                 // BOOST_CHECK_EQUAL(data->Value(), 1);
1301 
1302                 DumpResults(auto_stmt.get());
1303             } catch (boost::execution_aborted) {
1304             }
1305         }
1306 
1307     }
1308     catch(const CException& ex) {
1309         DBAPI_BOOST_FAIL(ex);
1310     }
1311 }
1312 
1313 ///////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_ResultsetMetaData)1314 BOOST_AUTO_TEST_CASE(Test_ResultsetMetaData)
1315 {
1316     try {
1317         unique_ptr<IStatement> auto_stmt(GetConnection().GetStatement());
1318         IResultSet* rs;
1319         const IResultSetMetaData* md = NULL;
1320 
1321         // First test ...
1322         // Check different data types ...
1323         // Check non-empty results ...
1324         {
1325             // bit
1326             try {
1327                 rs = auto_stmt->ExecuteQuery
1328                     ("select convert(bit, 1) as [x y]");
1329                 BOOST_REQUIRE(rs != NULL);
1330                 md = rs->GetMetaData();
1331                 BOOST_REQUIRE(md != NULL);
1332                 // 1-based, sensitive to case and internal whitespace
1333                 BOOST_CHECK( !md->HasColumn(0) );
1334                 BOOST_CHECK(md->HasColumn(1));
1335                 BOOST_CHECK( !md->HasColumn(2) );
1336 
1337                 BOOST_CHECK(md->HasColumn("x y"));
1338                 BOOST_CHECK(md->HasColumn(" x y "));
1339                 BOOST_CHECK( !md->HasColumn("X Y") );
1340                 BOOST_CHECK( !md->HasColumn("x  y") );
1341 
1342                 EDB_Type curr_type = md->GetType(1);
1343                 BOOST_CHECK_EQUAL(curr_type, eDB_Bit);
1344                 BOOST_CHECK_EQUAL(md->GetMaxSize(1), 1);
1345 
1346                 DumpResults(auto_stmt.get());
1347             } catch (boost::execution_aborted) {
1348             }
1349 
1350             // tinyint
1351             try {
1352                 rs = auto_stmt->ExecuteQuery("select convert(tinyint, 1)");
1353                 BOOST_REQUIRE(rs != NULL);
1354                 md = rs->GetMetaData();
1355                 BOOST_REQUIRE(md != NULL);
1356 
1357                 EDB_Type curr_type = md->GetType(1);
1358                 BOOST_CHECK_EQUAL(curr_type, eDB_TinyInt);
1359                 if (GetArgs().GetDriverName() == odbc_driver) {
1360                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 3);
1361                 } else {
1362                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 1);
1363                 }
1364                 DumpResults(auto_stmt.get());
1365             } catch (boost::execution_aborted) {
1366             }
1367 
1368             // smallint
1369             try {
1370                 rs = auto_stmt->ExecuteQuery("select convert(smallint, 1)");
1371                 BOOST_REQUIRE(rs != NULL);
1372                 md = rs->GetMetaData();
1373                 BOOST_REQUIRE(md != NULL);
1374 
1375                 EDB_Type curr_type = md->GetType(1);
1376                 BOOST_CHECK_EQUAL(curr_type, eDB_SmallInt);
1377 
1378                 if (GetArgs().GetDriverName() == odbc_driver) {
1379                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 5);
1380                 } else {
1381                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 2);
1382                 }
1383 
1384                 DumpResults(auto_stmt.get());
1385             } catch (boost::execution_aborted) {
1386             }
1387 
1388             // int
1389             try {
1390                 rs = auto_stmt->ExecuteQuery("select convert(int, 1)");
1391                 BOOST_REQUIRE(rs != NULL);
1392                 md = rs->GetMetaData();
1393                 BOOST_REQUIRE(md != NULL);
1394 
1395                 EDB_Type curr_type = md->GetType(1);
1396                 BOOST_CHECK_EQUAL(curr_type, eDB_Int);
1397 
1398                 if (GetArgs().GetDriverName() == odbc_driver) {
1399                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 10);
1400                 } else {
1401                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 4);
1402                 }
1403 
1404                 DumpResults(auto_stmt.get());
1405             } catch (boost::execution_aborted) {
1406             }
1407 
1408             // numeric
1409             {
1410                 //
1411                 try {
1412                     rs = auto_stmt->ExecuteQuery("select convert(numeric(38, 0), 1)");
1413                     BOOST_REQUIRE(rs != NULL);
1414                     md = rs->GetMetaData();
1415                     BOOST_REQUIRE(md != NULL);
1416 
1417                     EDB_Type curr_type = md->GetType(1);
1418                     BOOST_CHECK_EQUAL(curr_type, eDB_Numeric);
1419 
1420                     if (GetArgs().GetDriverName() == odbc_driver) {
1421                         BOOST_CHECK_EQUAL(md->GetMaxSize(1), 38);
1422                     } else {
1423                         BOOST_CHECK_EQUAL(md->GetMaxSize(1), 35);
1424                     }
1425 
1426                     DumpResults(auto_stmt.get());
1427                 } catch (boost::execution_aborted) {
1428                 }
1429 
1430                 //
1431                 try {
1432                     rs = auto_stmt->ExecuteQuery("select convert(numeric(18, 2), 2843113322)");
1433                     BOOST_REQUIRE(rs != NULL);
1434                     md = rs->GetMetaData();
1435                     BOOST_REQUIRE(md != NULL);
1436 
1437                     EDB_Type curr_type = md->GetType(1);
1438                     BOOST_CHECK_EQUAL(curr_type, eDB_Numeric);
1439 
1440                     if (GetArgs().GetDriverName() == odbc_driver) {
1441                         BOOST_CHECK_EQUAL(md->GetMaxSize(1), 18);
1442                     } else {
1443                         BOOST_CHECK_EQUAL(md->GetMaxSize(1), 35);
1444                     }
1445 
1446                     DumpResults(auto_stmt.get());
1447                 } catch (boost::execution_aborted) {
1448                 }
1449             }
1450 
1451             // decimal
1452             // There is no eDB_Decimal ...
1453             if (false) try {
1454                 rs = auto_stmt->ExecuteQuery("select convert(decimal(38, 0), 1)");
1455                 BOOST_REQUIRE(rs != NULL);
1456                 md = rs->GetMetaData();
1457                 BOOST_REQUIRE(md != NULL);
1458 
1459                 EDB_Type curr_type = md->GetType(1);
1460                 BOOST_CHECK_EQUAL(curr_type, eDB_Numeric);
1461 
1462                 DumpResults(auto_stmt.get());
1463             } catch (boost::execution_aborted) {
1464             }
1465 
1466             // float
1467             try {
1468                 rs = auto_stmt->ExecuteQuery("select convert(float(4), 1)");
1469                 BOOST_REQUIRE(rs != NULL);
1470                 md = rs->GetMetaData();
1471                 BOOST_REQUIRE(md != NULL);
1472 
1473                 EDB_Type curr_type = md->GetType(1);
1474                 BOOST_CHECK_EQUAL(curr_type, eDB_Float);
1475 
1476                 if (GetArgs().GetDriverName() == odbc_driver) {
1477                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 24);
1478                 } else {
1479                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 4);
1480                 }
1481 
1482                 DumpResults(auto_stmt.get());
1483             } catch (boost::execution_aborted) {
1484             }
1485 
1486             // double
1487             try {
1488                 rs = auto_stmt->ExecuteQuery("select convert(double precision, 1)");
1489                 BOOST_REQUIRE(rs != NULL);
1490                 md = rs->GetMetaData();
1491                 BOOST_REQUIRE(md != NULL);
1492 
1493                 EDB_Type curr_type = md->GetType(1);
1494                 BOOST_CHECK_EQUAL(curr_type, eDB_Double);
1495 
1496                 if (GetArgs().GetDriverName() == odbc_driver) {
1497                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 53);
1498                 } else {
1499                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 8);
1500                 }
1501 
1502                 DumpResults(auto_stmt.get());
1503             } catch (boost::execution_aborted) {
1504             }
1505 
1506             // real
1507             try {
1508                 rs = auto_stmt->ExecuteQuery("select convert(real, 1)");
1509                 BOOST_REQUIRE(rs != NULL);
1510                 md = rs->GetMetaData();
1511                 BOOST_REQUIRE(md != NULL);
1512 
1513                 EDB_Type curr_type = md->GetType(1);
1514                 BOOST_CHECK_EQUAL(curr_type, eDB_Float);
1515 
1516                 if (GetArgs().GetDriverName() == odbc_driver) {
1517                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 24);
1518                 } else {
1519                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 4);
1520                 }
1521 
1522                 DumpResults(auto_stmt.get());
1523             } catch (boost::execution_aborted) {
1524             }
1525 
1526             // smallmoney
1527             // Unsupported type ...
1528             if (false) try {
1529                 rs = auto_stmt->ExecuteQuery("select convert(smallmoney, 1)");
1530                 BOOST_REQUIRE(rs != NULL);
1531                 md = rs->GetMetaData();
1532                 BOOST_REQUIRE(md != NULL);
1533 
1534                 EDB_Type curr_type = md->GetType(1);
1535                 BOOST_CHECK_EQUAL(curr_type, eDB_Double);
1536                 BOOST_CHECK_EQUAL(md->GetMaxSize(1), 2);
1537 
1538                 DumpResults(auto_stmt.get());
1539             } catch (boost::execution_aborted) {
1540             }
1541 
1542             // money
1543             // Unsupported type ...
1544             if (false) try {
1545                 rs = auto_stmt->ExecuteQuery("select convert(money, 1)");
1546                 BOOST_REQUIRE(rs != NULL);
1547                 md = rs->GetMetaData();
1548                 BOOST_REQUIRE(md != NULL);
1549 
1550                 EDB_Type curr_type = md->GetType(1);
1551                 BOOST_CHECK_EQUAL(curr_type, eDB_Double);
1552                 BOOST_CHECK_EQUAL(md->GetMaxSize(1), 2);
1553 
1554                 DumpResults(auto_stmt.get());
1555             } catch (boost::execution_aborted) {
1556             }
1557 
1558             // smalldatetime
1559             try {
1560                 rs = auto_stmt->ExecuteQuery("select convert(smalldatetime, 'January 1, 1900')");
1561                 BOOST_REQUIRE(rs != NULL);
1562                 md = rs->GetMetaData();
1563                 BOOST_REQUIRE(md != NULL);
1564 
1565                 EDB_Type curr_type = md->GetType(1);
1566                 BOOST_CHECK_EQUAL(curr_type, eDB_SmallDateTime);
1567 
1568                 if (GetArgs().GetDriverName() == odbc_driver) {
1569                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 16);
1570                 } else {
1571                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 4);
1572                 }
1573 
1574                 DumpResults(auto_stmt.get());
1575             } catch (boost::execution_aborted) {
1576             }
1577 
1578             // datetime
1579             try {
1580                 rs = auto_stmt->ExecuteQuery("select convert(datetime, 'January 1, 1753')");
1581                 BOOST_REQUIRE(rs != NULL);
1582                 md = rs->GetMetaData();
1583                 BOOST_REQUIRE(md != NULL);
1584 
1585                 EDB_Type curr_type = md->GetType(1);
1586                 BOOST_CHECK_EQUAL(curr_type, eDB_DateTime);
1587 
1588                 if (GetArgs().GetDriverName() == odbc_driver) {
1589                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 23);
1590                 } else {
1591                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 8);
1592                 }
1593 
1594                 DumpResults(auto_stmt.get());
1595             } catch (boost::execution_aborted) {
1596             }
1597 
1598             // char
1599             try {
1600                 rs = auto_stmt->ExecuteQuery("select convert(char(32), '12345')");
1601                 BOOST_REQUIRE(rs != NULL);
1602                 md = rs->GetMetaData();
1603                 BOOST_REQUIRE(md != NULL);
1604 
1605                 EDB_Type curr_type = md->GetType(1);
1606                 if (GetArgs().GetDriverName() == odbc_driver) {
1607                     BOOST_CHECK_EQUAL(curr_type, eDB_Char);
1608                 } else {
1609                     BOOST_CHECK_EQUAL(curr_type, eDB_VarChar);
1610                 }
1611 
1612                 // BOOST_CHECK_EQUAL(md->GetMaxSize(1), 32);
1613 
1614                 DumpResults(auto_stmt.get());
1615             } catch (boost::execution_aborted) {
1616             }
1617 
1618             // long char
1619             try {
1620                 rs = auto_stmt->ExecuteQuery("select convert(char(8000), '12345')");
1621                 BOOST_REQUIRE(rs != NULL);
1622                 md = rs->GetMetaData();
1623                 BOOST_REQUIRE(md != NULL);
1624 
1625                 EDB_Type curr_type = md->GetType(1);
1626                 if (GetArgs().IsFreeTDS() ||
1627                     GetArgs().GetDriverName() == ctlib_driver
1628                     ) {
1629                     BOOST_CHECK_EQUAL(curr_type, eDB_VarChar);
1630                 } else if (GetArgs().GetDriverName() == odbc_driver) {
1631                     BOOST_CHECK_EQUAL(curr_type, eDB_LongChar);
1632                 } else {
1633                     BOOST_CHECK_EQUAL(curr_type, eDB_Char);
1634                 }
1635 
1636                 // BOOST_CHECK_EQUAL(md->GetMaxSize(1), 8000);
1637 
1638                 DumpResults(auto_stmt.get());
1639             } catch (boost::execution_aborted) {
1640             }
1641 
1642             // varchar
1643             try {
1644                 rs = auto_stmt->ExecuteQuery("select convert(varchar(32), '12345')");
1645                 BOOST_REQUIRE(rs != NULL);
1646                 md = rs->GetMetaData();
1647                 BOOST_REQUIRE(md != NULL);
1648 
1649                 EDB_Type curr_type = md->GetType(1);
1650                 BOOST_CHECK_EQUAL(curr_type, eDB_VarChar);
1651                 // BOOST_CHECK_EQUAL(md->GetMaxSize(1), 32);
1652 
1653                 DumpResults(auto_stmt.get());
1654             } catch (boost::execution_aborted) {
1655             }
1656 
1657             // nchar
1658             try {
1659                 rs = auto_stmt->ExecuteQuery("select convert(nchar(32), '12345')");
1660                 BOOST_REQUIRE(rs != NULL);
1661                 md = rs->GetMetaData();
1662                 BOOST_REQUIRE(md != NULL);
1663 
1664                 EDB_Type curr_type = md->GetType(1);
1665                 if (GetArgs().GetDriverName() == odbc_driver) {
1666                     BOOST_CHECK_EQUAL(curr_type, eDB_Char);
1667                 } else {
1668                     BOOST_CHECK_EQUAL(curr_type, eDB_VarChar);
1669                 }
1670                 // BOOST_CHECK_EQUAL(md->GetMaxSize(1), 32);
1671 
1672                 DumpResults(auto_stmt.get());
1673             } catch (boost::execution_aborted) {
1674             }
1675 
1676             // nvarchar
1677             try {
1678                 rs = auto_stmt->ExecuteQuery("select convert(nvarchar(32), '12345')");
1679                 BOOST_REQUIRE(rs != NULL);
1680                 md = rs->GetMetaData();
1681                 BOOST_REQUIRE(md != NULL);
1682 
1683                 EDB_Type curr_type = md->GetType(1);
1684                 BOOST_CHECK_EQUAL(curr_type, eDB_VarChar);
1685                 // BOOST_CHECK_EQUAL(md->GetMaxSize(1), 32);
1686 
1687                 DumpResults(auto_stmt.get());
1688             } catch (boost::execution_aborted) {
1689             }
1690 
1691             // binary
1692             try {
1693                 rs = auto_stmt->ExecuteQuery("select convert(binary(32), '12345')");
1694                 BOOST_REQUIRE(rs != NULL);
1695                 md = rs->GetMetaData();
1696                 BOOST_REQUIRE(md != NULL);
1697 
1698                 EDB_Type curr_type = md->GetType(1);
1699                 if (GetArgs().GetDriverName() == odbc_driver) {
1700                     BOOST_CHECK_EQUAL(curr_type, eDB_Binary);
1701                 } else {
1702                     BOOST_CHECK_EQUAL(curr_type, eDB_VarBinary);
1703                 }
1704                 BOOST_CHECK_EQUAL(md->GetMaxSize(1), 32);
1705 
1706                 DumpResults(auto_stmt.get());
1707             } catch (boost::execution_aborted) {
1708             }
1709 
1710             // long binary
1711             try {
1712                 rs = auto_stmt->ExecuteQuery("select convert(binary(8000), '12345')");
1713                 BOOST_REQUIRE(rs != NULL);
1714                 md = rs->GetMetaData();
1715                 BOOST_REQUIRE(md != NULL);
1716 
1717                 EDB_Type curr_type = md->GetType(1);
1718                 if ((GetArgs().IsFreeTDS() &&
1719                         GetArgs().GetServerType() == CDBConnParams::eMSSqlServer) ||
1720                     (GetArgs().GetDriverName() == ctlib_driver &&
1721                         NStr::CompareNocase(GetSybaseClientVersion(), 0, 4, "12.0") == 0)
1722                     ) {
1723                     BOOST_CHECK_EQUAL(curr_type, eDB_VarBinary);
1724                 } else if ((GetArgs().IsFreeTDS()  &&
1725                         GetArgs().GetServerType() == CDBConnParams::eSybaseSQLServer) ||
1726                     GetArgs().GetDriverName() == ctlib_driver ||
1727                     GetArgs().GetDriverName() == odbc_driver
1728                     ) {
1729                     BOOST_CHECK_EQUAL(curr_type, eDB_LongBinary);
1730                 } else {
1731                     BOOST_CHECK_EQUAL(curr_type, eDB_Binary);
1732                 }
1733 
1734                 if (GetArgs().GetDriverName() == ctlib_driver &&
1735                     NStr::CompareNocase(GetSybaseClientVersion(), 0, 4, "12.0") == 0
1736                     ) {
1737                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 255);
1738                 } else {
1739                     BOOST_CHECK_EQUAL(md->GetMaxSize(1), 8000);
1740                 }
1741 
1742                 DumpResults(auto_stmt.get());
1743             } catch (boost::execution_aborted) {
1744             }
1745 
1746             // varbinary
1747             try {
1748                 rs = auto_stmt->ExecuteQuery("select convert(varbinary(32), '12345')");
1749                 BOOST_REQUIRE(rs != NULL);
1750                 md = rs->GetMetaData();
1751                 BOOST_REQUIRE(md != NULL);
1752 
1753                 EDB_Type curr_type = md->GetType(1);
1754                 BOOST_CHECK_EQUAL(curr_type, eDB_VarBinary);
1755                 BOOST_CHECK_EQUAL(md->GetMaxSize(1), 32);
1756 
1757                 DumpResults(auto_stmt.get());
1758             } catch (boost::execution_aborted) {
1759             }
1760 
1761             // Explicitly set max LOB size ...
1762             {
1763                 I_DriverContext* drv_context = GetDS().GetDriverContext();
1764 
1765                 if ( drv_context == NULL ) {
1766                     BOOST_FAIL("FATAL: Unable to load context for dbdriver " +
1767                             GetArgs().GetDriverName());
1768                 }
1769 
1770                 drv_context->SetMaxBlobSize( 0x7fffffff );
1771             }
1772 
1773             // Set text size manually ...
1774             // SetMaxBlobSize() method doesn't work in case of ctlib
1775             // driver.
1776             {
1777                 auto_stmt->ExecuteQuery("set textsize 2147483647");
1778                 DumpResults(auto_stmt.get());
1779             }
1780 
1781             // text
1782             try {
1783                 rs = auto_stmt->ExecuteQuery("select convert(text, '12345')");
1784                 BOOST_REQUIRE(rs != NULL);
1785                 md = rs->GetMetaData();
1786                 BOOST_REQUIRE(md != NULL);
1787 
1788                 EDB_Type curr_type = md->GetType(1);
1789                 BOOST_CHECK_EQUAL(curr_type, eDB_Text);
1790                 BOOST_CHECK_EQUAL(md->GetMaxSize(1), 2147483647);
1791 
1792                 DumpResults(auto_stmt.get());
1793             } catch (boost::execution_aborted) {
1794             }
1795 
1796             // image
1797             try {
1798                 rs = auto_stmt->ExecuteQuery("select convert(image, '12345')");
1799                 BOOST_REQUIRE(rs != NULL);
1800                 md = rs->GetMetaData();
1801                 BOOST_REQUIRE(md != NULL);
1802 
1803                 EDB_Type curr_type = md->GetType(1);
1804                 BOOST_CHECK_EQUAL(curr_type, eDB_Image);
1805                 BOOST_CHECK_EQUAL(md->GetMaxSize(1), 2147483647);
1806 
1807                 DumpResults(auto_stmt.get());
1808             } catch (boost::execution_aborted) {
1809             }
1810         }
1811 
1812         // Second test ...
1813         {
1814         }
1815     }
1816     catch(const CException& ex) {
1817         DBAPI_BOOST_FAIL(ex);
1818     }
1819 }
1820 
1821 ///////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_StmtMetaData)1822 BOOST_AUTO_TEST_CASE(Test_StmtMetaData)
1823 {
1824     try {
1825         unique_ptr<ICallableStatement> auto_stmt;
1826         unsigned int col_num = 0;
1827 
1828         if (false) {
1829             unique_ptr<IStatement> auto_stmt01(GetConnection().GetStatement());
1830             auto_stmt01->ExecuteUpdate("USE DBAPI_Sample");
1831         }
1832 
1833         //////////////////////////////////////////////////////////////////////
1834         {
1835             auto_stmt.reset(
1836                     GetConnection().GetCallableStatement("sp_columns")
1837                     );
1838 
1839             const IResultSetMetaData& mi = auto_stmt->GetParamsMetaData();
1840 
1841             col_num = mi.GetTotalColumns();
1842             if (GetArgs().GetServerType() == CDBConnParams::eSybaseSQLServer) {
1843                 BOOST_CHECK_EQUAL(col_num, 5U);
1844             } else {
1845                 BOOST_CHECK_EQUAL(col_num, 6U);
1846             }
1847         }
1848 
1849         //////////////////////////////////////////////////////////////////////
1850         {
1851             auto_stmt.reset(
1852                     GetConnection().GetCallableStatement(".sp_columns")
1853                     );
1854 
1855             const IResultSetMetaData& mi = auto_stmt->GetParamsMetaData();
1856 
1857             col_num = mi.GetTotalColumns();
1858             if (GetArgs().GetServerType() == CDBConnParams::eSybaseSQLServer) {
1859                 BOOST_CHECK_EQUAL(col_num, 5U);
1860             } else {
1861                 BOOST_CHECK_EQUAL(col_num, 6U);
1862             }
1863         }
1864 
1865         //////////////////////////////////////////////////////////////////////
1866         {
1867             auto_stmt.reset(
1868                     GetConnection().GetCallableStatement("..sp_columns")
1869                     );
1870 
1871             const IResultSetMetaData& mi = auto_stmt->GetParamsMetaData();
1872 
1873             col_num = mi.GetTotalColumns();
1874             if (GetArgs().GetServerType() == CDBConnParams::eSybaseSQLServer) {
1875                 BOOST_CHECK_EQUAL(col_num, 5U);
1876             } else {
1877                 BOOST_CHECK_EQUAL(col_num, 6U);
1878             }
1879         }
1880 
1881         //////////////////////////////////////////////////////////////////////
1882         {
1883             auto_stmt.reset(
1884                     GetConnection().GetCallableStatement("sp_sproc_columns")
1885                     );
1886 
1887             const IResultSetMetaData& mi = auto_stmt->GetParamsMetaData();
1888 
1889             col_num = mi.GetTotalColumns();
1890             switch (GetArgs().GetServerType()) {
1891                 case CDBConnParams::eSybaseSQLServer:
1892                     BOOST_CHECK_EQUAL(col_num, 5U);
1893                     break;
1894                 case CDBConnParams::eMSSqlServer:
1895                     BOOST_CHECK_EQUAL(col_num, 7U);
1896                     break;
1897                 default:
1898                     break;
1899             }
1900         }
1901 
1902         //////////////////////////////////////////////////////////////////////
1903         {
1904             auto_stmt.reset(
1905                     GetConnection().GetCallableStatement("sp_server_info")
1906                     );
1907 
1908             const IResultSetMetaData& mi = auto_stmt->GetParamsMetaData();
1909 
1910             col_num = mi.GetTotalColumns();
1911             BOOST_CHECK_EQUAL(col_num, 2U);
1912         }
1913 
1914         //////////////////////////////////////////////////////////////////////
1915         {
1916             auto_stmt.reset(
1917                     GetConnection().GetCallableStatement("sp_tables")
1918                     );
1919 
1920             const IResultSetMetaData& mi = auto_stmt->GetParamsMetaData();
1921 
1922             col_num = mi.GetTotalColumns();
1923             if (GetArgs().GetServerType() == CDBConnParams::eMSSqlServer) {
1924                 BOOST_CHECK_EQUAL(col_num, 6U);
1925             } else {
1926                 BOOST_CHECK_EQUAL(col_num, 5U);
1927             }
1928         }
1929 
1930         //////////////////////////////////////////////////////////////////////
1931         {
1932             auto_stmt.reset(
1933                     GetConnection().GetCallableStatement("sp_stored_procedures")
1934                     );
1935 
1936             const IResultSetMetaData& mi = auto_stmt->GetParamsMetaData();
1937 
1938             col_num = mi.GetTotalColumns();
1939             if (GetArgs().GetServerType() == CDBConnParams::eMSSqlServer) {
1940                 BOOST_CHECK_EQUAL(col_num, 5U);
1941             } else {
1942                 BOOST_CHECK_EQUAL(col_num, 4U);
1943             }
1944         }
1945 
1946         //////////////////////////////////////////////////////////////////////
1947         {
1948             if (GetArgs().GetServerType() == CDBConnParams::eSybaseSQLServer) {
1949         auto_stmt.reset(
1950             GetConnection().GetCallableStatement("sybsystemprocs..sp_stored_procedures")
1951             );
1952             } else {
1953         auto_stmt.reset(
1954             GetConnection().GetCallableStatement("master..sp_stored_procedures")
1955             );
1956             }
1957 
1958             const IResultSetMetaData& mi = auto_stmt->GetParamsMetaData();
1959 
1960             col_num = mi.GetTotalColumns();
1961             if (GetArgs().GetServerType() == CDBConnParams::eMSSqlServer) {
1962                 BOOST_CHECK_EQUAL(col_num, 5U);
1963             } else {
1964                 BOOST_CHECK_EQUAL(col_num, 4U);
1965             }
1966         }
1967 
1968         //////////////////////////////////////////////////////////////////////
1969         {
1970             if (GetArgs().GetServerType() == CDBConnParams::eSybaseSQLServer) {
1971         auto_stmt.reset(
1972             GetConnection().GetCallableStatement("sybsystemprocs.dbo.sp_stored_procedures")
1973             );
1974             } else {
1975         auto_stmt.reset(
1976             GetConnection().GetCallableStatement("master.dbo.sp_stored_procedures")
1977             );
1978             }
1979 
1980             const IResultSetMetaData& mi = auto_stmt->GetParamsMetaData();
1981 
1982             col_num = mi.GetTotalColumns();
1983             if (GetArgs().GetServerType() == CDBConnParams::eMSSqlServer) {
1984                 BOOST_CHECK_EQUAL(col_num, 5U);
1985             } else {
1986                 BOOST_CHECK_EQUAL(col_num, 4U);
1987             }
1988         }
1989 
1990     }
1991     catch(const CException& ex) {
1992         DBAPI_BOOST_FAIL(ex);
1993     }
1994 }
1995 
1996 ////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_NULL)1997 BOOST_AUTO_TEST_CASE(Test_NULL)
1998 {
1999     const string table_name = GetTableName();
2000     // const string table_name("DBAPI_Sample..dbapi_unit_test");
2001 
2002     enum {rec_num = 10};
2003     string sql;
2004 
2005     try {
2006         // Initialize data (strings are NOT empty) ...
2007         {
2008             unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
2009 
2010             {
2011                 // Drop all records ...
2012                 sql  = " DELETE FROM " + table_name;
2013                 auto_stmt->ExecuteUpdate(sql);
2014 
2015                 sql  = " INSERT INTO " + table_name +
2016                     "(int_field, vc1000_field) "
2017                     "VALUES(@int_field, @vc1000_field) \n";
2018 
2019                 // CVariant variant(eDB_Text);
2020                 // variant.Append(" ", 1);
2021 
2022                 // Insert data ...
2023                 for (long ind = 0; ind < rec_num; ++ind) {
2024                     if (ind % 2 == 0) {
2025                         auto_stmt->SetParam( CVariant( Int4(ind) ), "@int_field" );
2026                         auto_stmt->SetParam(CVariant(eDB_VarChar), "@vc1000_field");
2027                     } else {
2028                         auto_stmt->SetParam( CVariant(eDB_Int), "@int_field" );
2029                         auto_stmt->SetParam( CVariant(NStr::NumericToString(ind)),
2030                                              "@vc1000_field"
2031                                              );
2032                     }
2033 
2034                     // Execute a statement with parameters ...
2035                     auto_stmt->ExecuteUpdate( sql );
2036                 }
2037 
2038                 // Check record number ...
2039                 BOOST_CHECK_EQUAL(size_t(rec_num),
2040                                   GetNumOfRecords(auto_stmt, table_name)
2041                                   );
2042             }
2043 
2044             {
2045                 // !!! Do not forget to clear a parameter list ....
2046                 // Workaround for the ctlib driver ...
2047                 auto_stmt->ClearParamList();
2048 
2049                 // Drop all records ...
2050                 sql  = " DELETE FROM #test_unicode_table";
2051                 auto_stmt->ExecuteUpdate(sql);
2052 
2053                 sql  = " INSERT INTO #test_unicode_table"
2054                     "(nvc255_field) VALUES(@nvc255_field)";
2055 
2056                 // Insert data ...
2057                 for (long ind = 0; ind < rec_num; ++ind) {
2058                     if (ind % 2 == 0) {
2059                         auto_stmt->SetParam(CVariant(eDB_VarChar), "@nvc255_field");
2060                     } else {
2061                         auto_stmt->SetParam( CVariant(NStr::NumericToString(ind)),
2062                                              "@nvc255_field");
2063                     }
2064 
2065                     // Execute a statement with parameters ...
2066                     auto_stmt->ExecuteUpdate( sql );
2067                 }
2068 
2069                 // Check record number ...
2070                 BOOST_CHECK_EQUAL(size_t(rec_num),
2071                                   GetNumOfRecords(auto_stmt, "#test_unicode_table"));
2072             }
2073         }
2074 
2075         // Check ...
2076         if (true) {
2077             unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
2078 
2079             {
2080                 sql = "SELECT int_field, vc1000_field FROM " + table_name +
2081                     " ORDER BY id";
2082 
2083                 auto_stmt->SendSql( sql );
2084                 BOOST_CHECK(auto_stmt->HasMoreResults());
2085                 BOOST_CHECK(auto_stmt->HasRows());
2086                 unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
2087                 BOOST_CHECK(rs.get() != NULL);
2088 
2089                 for (long ind = 0; ind < rec_num; ++ind) {
2090                     BOOST_CHECK(rs->Next());
2091 
2092                     const CVariant& int_field = rs->GetVariant(1);
2093                     const CVariant& vc1000_field = rs->GetVariant(2);
2094 
2095                     if (ind % 2 == 0) {
2096                         BOOST_CHECK( !int_field.IsNull() );
2097                         BOOST_CHECK_EQUAL( int_field.GetInt4(), ind );
2098 
2099                         BOOST_CHECK( vc1000_field.IsNull() );
2100                     } else {
2101                         BOOST_CHECK( int_field.IsNull() );
2102 
2103                         BOOST_CHECK( !vc1000_field.IsNull() );
2104                         BOOST_CHECK_EQUAL( vc1000_field.GetString(),
2105                                            NStr::NumericToString(ind) );
2106                     }
2107                 }
2108 
2109                 DumpResults(auto_stmt.get());
2110             }
2111 
2112             {
2113                 sql = "SELECT nvc255_field FROM #test_unicode_table ORDER BY id";
2114 
2115                 auto_stmt->SendSql( sql );
2116                 BOOST_CHECK(auto_stmt->HasMoreResults());
2117                 BOOST_CHECK(auto_stmt->HasRows());
2118                 unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
2119                 BOOST_CHECK(rs.get() != NULL);
2120 
2121                 for (long ind = 0; ind < rec_num; ++ind) {
2122                     BOOST_CHECK(rs->Next());
2123 
2124                     const CVariant& nvc255_field = rs->GetVariant(1);
2125 
2126                     if (ind % 2 == 0) {
2127                         BOOST_CHECK( nvc255_field.IsNull() );
2128                     } else {
2129                         BOOST_CHECK( !nvc255_field.IsNull() );
2130                         BOOST_CHECK_EQUAL( NStr::TruncateSpaces(
2131                                                 nvc255_field.GetString()
2132                                                 ),
2133                                            NStr::NumericToString(ind) );
2134                     }
2135                 }
2136 
2137                 DumpResults(auto_stmt.get());
2138             }
2139         }
2140 
2141         // Check NULL with stored procedures ...
2142         {
2143             {
2144                 unique_ptr<ICallableStatement> auto_stmt(
2145                     GetConnection().GetCallableStatement("sp_server_info")
2146                     );
2147 
2148                 // Set parameter to NULL ...
2149                 auto_stmt->SetParam( CVariant(eDB_Int), "@attribute_id" );
2150                 auto_stmt->Execute();
2151 
2152                 if (GetArgs().GetServerType() == CDBConnParams::eSybaseSQLServer) {
2153                     BOOST_CHECK_EQUAL( size_t(30), GetNumOfRecords(auto_stmt) );
2154                 } else {
2155                     BOOST_CHECK_EQUAL( size_t(29), GetNumOfRecords(auto_stmt) );
2156                 }
2157 
2158                 // Set parameter to 1 ...
2159                 auto_stmt->SetParam( CVariant( Int4(1) ), "@attribute_id" );
2160                 auto_stmt->Execute();
2161 
2162                 BOOST_CHECK_EQUAL( size_t(1), GetNumOfRecords(auto_stmt) );
2163             }
2164 
2165             {
2166             }
2167         }
2168 
2169 
2170         // Special case: empty strings and strings with spaces.
2171         {
2172             unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
2173 
2174             // Initialize data (strings are EMPTY) ...
2175             {
2176                 // Drop all records ...
2177                 sql  = " DELETE FROM " + table_name;
2178                 auto_stmt->ExecuteUpdate(sql);
2179 
2180                 sql  = " INSERT INTO " + table_name +
2181                     "(int_field, vc1000_field) "
2182                     "VALUES(@int_field, @vc1000_field) \n";
2183 
2184                 // CVariant variant(eDB_Text);
2185                 // variant.Append(" ", 1);
2186 
2187                 // Insert data ...
2188                 for (long ind = 0; ind < rec_num; ++ind) {
2189                     if (ind % 2 == 0) {
2190                         auto_stmt->SetParam( CVariant( Int4(ind) ), "@int_field" );
2191                         auto_stmt->SetParam(CVariant(eDB_VarChar), "@vc1000_field");
2192                     } else {
2193                         auto_stmt->SetParam( CVariant(eDB_Int), "@int_field" );
2194                         auto_stmt->SetParam( CVariant(string()), "@vc1000_field" );
2195                     }
2196 
2197                     // Execute a statement with parameters ...
2198                     auto_stmt->ExecuteUpdate( sql );
2199                 }
2200 
2201                 // Check record number ...
2202                 BOOST_CHECK_EQUAL(size_t(rec_num), GetNumOfRecords(auto_stmt,
2203                                                                 table_name));
2204             }
2205 
2206             // Check ...
2207             {
2208                 sql = "SELECT int_field, vc1000_field FROM " + table_name +
2209                     " ORDER BY id";
2210 
2211                 auto_stmt->SendSql( sql );
2212                 BOOST_CHECK(auto_stmt->HasMoreResults());
2213                 BOOST_CHECK(auto_stmt->HasRows());
2214                 unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
2215                 BOOST_CHECK(rs.get() != NULL);
2216 
2217                 for (long ind = 0; ind < rec_num; ++ind) {
2218                     BOOST_CHECK(rs->Next());
2219 
2220                     const CVariant& int_field = rs->GetVariant(1);
2221                     const CVariant& vc1000_field = rs->GetVariant(2);
2222 
2223                     if (ind % 2 == 0) {
2224                         BOOST_CHECK( !int_field.IsNull() );
2225                         BOOST_CHECK_EQUAL( int_field.GetInt4(), ind );
2226 
2227                         BOOST_CHECK( vc1000_field.IsNull() );
2228                     } else {
2229                         BOOST_CHECK( int_field.IsNull() );
2230 
2231 #ifdef NCBI_OS_SOLARIS
2232                         // Another version of Sybase client is used on Solaris,
2233                         // ctlib driver works there differently
2234                         if (GetArgs().GetDriverName() == ctlib_driver) {
2235                             const string sybase_version = GetSybaseClientVersion();
2236                             if (NStr::CompareNocase(sybase_version, 0, 4, "12.0") == 0) {
2237                                 BOOST_CHECK( vc1000_field.IsNull() );
2238                                 continue;
2239                             }
2240                         }
2241 #endif
2242 
2243                         BOOST_CHECK( !vc1000_field.IsNull() );
2244                         // Old protocol version has this strange feature
2245                         if (GetArgs().GetServerType() == CDBConnParams::eSybaseSQLServer
2246                            )
2247                         {
2248                             BOOST_CHECK_EQUAL( vc1000_field.GetString(), string(" ") );
2249                         }
2250                         else {
2251                             BOOST_CHECK_EQUAL( vc1000_field.GetString(), string() );
2252                         }
2253                     }
2254                 }
2255 
2256                 DumpResults(auto_stmt.get());
2257             }
2258 
2259             // Initialize data (strings are full of spaces) ...
2260             {
2261                 // Drop all records ...
2262                 sql  = " DELETE FROM " + GetTableName();
2263                 auto_stmt->ExecuteUpdate(sql);
2264 
2265                 sql  = " INSERT INTO " + GetTableName() +
2266                     "(int_field, vc1000_field) "
2267                     "VALUES(@int_field, @vc1000_field) \n";
2268 
2269                 // CVariant variant(eDB_Text);
2270                 // variant.Append(" ", 1);
2271 
2272                 // !!! Do not forget to clear a parameter list ....
2273                 // Workaround for the ctlib driver ...
2274                 auto_stmt->ClearParamList();
2275 
2276                 // Insert data ...
2277                 for (long ind = 0; ind < rec_num; ++ind) {
2278                     if (ind % 2 == 0) {
2279                         auto_stmt->SetParam( CVariant( Int4(ind) ), "@int_field" );
2280                         auto_stmt->SetParam(CVariant(eDB_VarChar), "@vc1000_field");
2281                     } else {
2282                         auto_stmt->SetParam( CVariant(eDB_Int), "@int_field" );
2283                         auto_stmt->SetParam( CVariant(string("    ")), "@vc1000_field" );
2284                     }
2285 
2286                     // Execute a statement with parameters ...
2287                     auto_stmt->ExecuteUpdate( sql );
2288                 }
2289 
2290                 // Check record number ...
2291                 BOOST_CHECK_EQUAL(size_t(rec_num), GetNumOfRecords(auto_stmt,
2292                                                                 GetTableName()));
2293             }
2294 
2295             // Check ...
2296             {
2297                 sql = "SELECT int_field, vc1000_field FROM " + GetTableName() +
2298                     " ORDER BY id";
2299 
2300                 auto_stmt->SendSql( sql );
2301                 BOOST_CHECK(auto_stmt->HasMoreResults());
2302                 BOOST_CHECK(auto_stmt->HasRows());
2303                 unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
2304                 BOOST_CHECK(rs.get() != NULL);
2305 
2306                 for (long ind = 0; ind < rec_num; ++ind) {
2307                     BOOST_CHECK(rs->Next());
2308 
2309                     const CVariant& int_field = rs->GetVariant(1);
2310                     const CVariant& vc1000_field = rs->GetVariant(2);
2311 
2312                     if (ind % 2 == 0) {
2313                         BOOST_CHECK( !int_field.IsNull() );
2314                         BOOST_CHECK_EQUAL( int_field.GetInt4(), ind );
2315 
2316                         BOOST_CHECK( vc1000_field.IsNull() );
2317                     } else {
2318                         BOOST_CHECK( int_field.IsNull() );
2319 
2320                         BOOST_CHECK( !vc1000_field.IsNull() );
2321                         // Old protocol version has this strange feature
2322                         if (GetArgs().GetServerType() == CDBConnParams::eSybaseSQLServer
2323                            )
2324                         {
2325                             BOOST_CHECK_EQUAL( vc1000_field.GetString(), string(" ") );
2326                         }
2327                         else {
2328                             BOOST_CHECK_EQUAL( vc1000_field.GetString(), string("    ") );
2329                         }
2330                     }
2331                 }
2332 
2333                 DumpResults(auto_stmt.get());
2334             }
2335         }
2336     }
2337     catch(const CException& ex) {
2338         DBAPI_BOOST_FAIL(ex);
2339     }
2340 }
2341 
2342 ////////////////////////////////////////////////////////////////////////////////
2343 static void
s_CheckGetRowCount(int row_count,ETransBehavior tb=eNoTrans,IStatement * stmt=NULL)2344 s_CheckGetRowCount(
2345     int row_count,
2346     ETransBehavior tb = eNoTrans,
2347     IStatement* stmt = NULL
2348     )
2349 {
2350     // Transaction ...
2351     CTestTransaction transaction(GetConnection(), tb);
2352     string sql;
2353     sql  = " INSERT INTO " + GetTableName() + "(int_field) VALUES( 1 ) \n";
2354 
2355     // Insert row_count records into the table ...
2356     for ( int i = 0; i < row_count; ++i ) {
2357         IStatement* curr_stmt = NULL;
2358         unique_ptr<IStatement> auto_stmt;
2359         if ( !stmt ) {
2360             auto_stmt.reset( GetConnection().GetStatement() );
2361             curr_stmt = auto_stmt.get();
2362         } else {
2363             curr_stmt = stmt;
2364         }
2365 
2366         curr_stmt->ExecuteUpdate(sql);
2367         int nRows = curr_stmt->GetRowCount();
2368         BOOST_CHECK_EQUAL( nRows, 1 );
2369     }
2370 
2371     // Check a SELECT statement
2372     {
2373         IStatement* curr_stmt = NULL;
2374         unique_ptr<IStatement> auto_stmt;
2375         if ( !stmt ) {
2376             auto_stmt.reset( GetConnection().GetStatement() );
2377             curr_stmt = auto_stmt.get();
2378         } else {
2379             curr_stmt = stmt;
2380         }
2381 
2382         sql  = " SELECT * FROM " + GetTableName();
2383         curr_stmt->ExecuteUpdate(sql);
2384 
2385         int nRows = curr_stmt->GetRowCount();
2386 
2387         BOOST_CHECK_EQUAL( row_count, nRows );
2388     }
2389 
2390     // Check an UPDATE statement
2391     {
2392         IStatement* curr_stmt = NULL;
2393         unique_ptr<IStatement> auto_stmt;
2394         if ( !stmt ) {
2395             auto_stmt.reset( GetConnection().GetStatement() );
2396             curr_stmt = auto_stmt.get();
2397         } else {
2398             curr_stmt = stmt;
2399         }
2400 
2401         sql  = " UPDATE " + GetTableName() + " SET int_field = 0 ";
2402         curr_stmt->ExecuteUpdate(sql);
2403 
2404         int nRows = curr_stmt->GetRowCount();
2405 
2406         BOOST_CHECK_EQUAL( row_count, nRows );
2407     }
2408 
2409     // Check a SELECT statement again
2410     {
2411         IStatement* curr_stmt = NULL;
2412         unique_ptr<IStatement> auto_stmt;
2413         if ( !stmt ) {
2414             auto_stmt.reset( GetConnection().GetStatement() );
2415             curr_stmt = auto_stmt.get();
2416         } else {
2417             curr_stmt = stmt;
2418         }
2419 
2420         sql  = " SELECT * FROM " + GetTableName() + " WHERE int_field = 0";
2421         curr_stmt->ExecuteUpdate(sql);
2422 
2423         int nRows = curr_stmt->GetRowCount();
2424 
2425         BOOST_CHECK_EQUAL( row_count, nRows );
2426     }
2427 
2428     // Check a DELETE statement
2429     {
2430         IStatement* curr_stmt = NULL;
2431         unique_ptr<IStatement> auto_stmt;
2432         if ( !stmt ) {
2433             auto_stmt.reset( GetConnection().GetStatement() );
2434             curr_stmt = auto_stmt.get();
2435         } else {
2436             curr_stmt = stmt;
2437         }
2438 
2439         sql  = " DELETE FROM " + GetTableName();
2440         curr_stmt->ExecuteUpdate(sql);
2441 
2442         int nRows = curr_stmt->GetRowCount();
2443 
2444         BOOST_CHECK_EQUAL( row_count, nRows );
2445     }
2446 
2447     // Check a SELECT statement again and again ...
2448     {
2449         IStatement* curr_stmt = NULL;
2450         unique_ptr<IStatement> auto_stmt;
2451         if ( !stmt ) {
2452             auto_stmt.reset( GetConnection().GetStatement() );
2453             curr_stmt = auto_stmt.get();
2454         } else {
2455             curr_stmt = stmt;
2456         }
2457 
2458         sql  = " SELECT * FROM " + GetTableName();
2459         curr_stmt->ExecuteUpdate(sql);
2460 
2461         int nRows = curr_stmt->GetRowCount();
2462 
2463         BOOST_CHECK_EQUAL( 0, nRows );
2464     }
2465 
2466 }
2467 
2468 ////////////////////////////////////////////////////////////////////////////////
2469 static void
s_CheckGetRowCount2(int row_count,ETransBehavior tb=eNoTrans,IStatement * stmt=NULL)2470 s_CheckGetRowCount2(
2471     int row_count,
2472     ETransBehavior tb = eNoTrans,
2473     IStatement* stmt = NULL
2474     )
2475 {
2476     // Transaction ...
2477     CTestTransaction transaction(GetConnection(), tb);
2478     // unique_ptr<IStatement> stmt( GetConnection().CreateStatement() );
2479     // _ASSERT(curr_stmt->get());
2480     string sql;
2481     sql  = " INSERT INTO " + GetTableName() + "(int_field) VALUES( @value ) \n";
2482 
2483     // Insert row_count records into the table ...
2484     for ( Int4 i = 0; i < row_count; ++i ) {
2485         IStatement* curr_stmt = NULL;
2486         unique_ptr<IStatement> auto_stmt;
2487         if ( !stmt ) {
2488             auto_stmt.reset( GetConnection().GetStatement() );
2489             curr_stmt = auto_stmt.get();
2490         } else {
2491             curr_stmt = stmt;
2492         }
2493 
2494         curr_stmt->SetParam(CVariant(i), "@value");
2495         curr_stmt->ExecuteUpdate(sql);
2496 
2497         int nRows = curr_stmt->GetRowCount();
2498         BOOST_CHECK_EQUAL( nRows, 1 );
2499 
2500         int nRows2 = curr_stmt->GetRowCount();
2501         BOOST_CHECK_EQUAL( nRows2, 1 );
2502     }
2503 
2504     // Workaround for the CTLIB driver ...
2505     {
2506         IStatement* curr_stmt = NULL;
2507         unique_ptr<IStatement> auto_stmt;
2508         if ( !stmt ) {
2509             auto_stmt.reset( GetConnection().GetStatement() );
2510             curr_stmt = auto_stmt.get();
2511         } else {
2512             curr_stmt = stmt;
2513         }
2514 
2515         curr_stmt->ClearParamList();
2516     }
2517 
2518     // Check a SELECT statement
2519     {
2520         IStatement* curr_stmt = NULL;
2521         unique_ptr<IStatement> auto_stmt;
2522         if ( !stmt ) {
2523             auto_stmt.reset( GetConnection().GetStatement() );
2524             curr_stmt = auto_stmt.get();
2525         } else {
2526             curr_stmt = stmt;
2527         }
2528 
2529         sql  = " SELECT int_field FROM " + GetTableName() +
2530             " ORDER BY int_field";
2531         curr_stmt->ExecuteUpdate(sql);
2532 
2533         int nRows = curr_stmt->GetRowCount();
2534         BOOST_CHECK_EQUAL( row_count, nRows );
2535 
2536         int nRows2 = curr_stmt->GetRowCount();
2537         BOOST_CHECK_EQUAL( row_count, nRows2 );
2538     }
2539 
2540     // Check an UPDATE statement
2541     {
2542         IStatement* curr_stmt = NULL;
2543         unique_ptr<IStatement> auto_stmt;
2544         if ( !stmt ) {
2545             auto_stmt.reset( GetConnection().GetStatement() );
2546             curr_stmt = auto_stmt.get();
2547         } else {
2548             curr_stmt = stmt;
2549         }
2550 
2551         sql  = " UPDATE " + GetTableName() + " SET int_field = 0 ";
2552         curr_stmt->ExecuteUpdate(sql);
2553 
2554         int nRows = curr_stmt->GetRowCount();
2555         BOOST_CHECK_EQUAL( row_count, nRows );
2556 
2557         int nRows2 = curr_stmt->GetRowCount();
2558         BOOST_CHECK_EQUAL( row_count, nRows2 );
2559     }
2560 
2561     // Check a SELECT statement again
2562     {
2563         IStatement* curr_stmt = NULL;
2564         unique_ptr<IStatement> auto_stmt;
2565         if ( !stmt ) {
2566             auto_stmt.reset( GetConnection().GetStatement() );
2567             curr_stmt = auto_stmt.get();
2568         } else {
2569             curr_stmt = stmt;
2570         }
2571 
2572         sql  = " SELECT int_field FROM " + GetTableName() +
2573             " WHERE int_field = 0";
2574         curr_stmt->ExecuteUpdate(sql);
2575 
2576         int nRows = curr_stmt->GetRowCount();
2577         BOOST_CHECK_EQUAL( row_count, nRows );
2578 
2579         int nRows2 = curr_stmt->GetRowCount();
2580         BOOST_CHECK_EQUAL( row_count, nRows2 );
2581     }
2582 
2583     // Check a DELETE statement
2584     {
2585         IStatement* curr_stmt = NULL;
2586         unique_ptr<IStatement> auto_stmt;
2587         if ( !stmt ) {
2588             auto_stmt.reset( GetConnection().GetStatement() );
2589             curr_stmt = auto_stmt.get();
2590         } else {
2591             curr_stmt = stmt;
2592         }
2593 
2594         sql  = " DELETE FROM " + GetTableName();
2595         curr_stmt->ExecuteUpdate(sql);
2596 
2597         int nRows = curr_stmt->GetRowCount();
2598         BOOST_CHECK_EQUAL( row_count, nRows );
2599 
2600         int nRows2 = curr_stmt->GetRowCount();
2601         BOOST_CHECK_EQUAL( row_count, nRows2 );
2602     }
2603 
2604     // Check a DELETE statement again
2605     {
2606         IStatement* curr_stmt = NULL;
2607         unique_ptr<IStatement> auto_stmt;
2608         if ( !stmt ) {
2609             auto_stmt.reset( GetConnection().GetStatement() );
2610             curr_stmt = auto_stmt.get();
2611         } else {
2612             curr_stmt = stmt;
2613         }
2614 
2615         sql  = " DELETE FROM " + GetTableName();
2616         curr_stmt->ExecuteUpdate(sql);
2617 
2618         int nRows = curr_stmt->GetRowCount();
2619         BOOST_CHECK_EQUAL( 0, nRows );
2620 
2621         int nRows2 = curr_stmt->GetRowCount();
2622         BOOST_CHECK_EQUAL( 0, nRows2 );
2623     }
2624 
2625     // Check a SELECT statement again and again ...
2626     {
2627         IStatement* curr_stmt = NULL;
2628         unique_ptr<IStatement> auto_stmt;
2629         if ( !stmt ) {
2630             auto_stmt.reset( GetConnection().GetStatement() );
2631             curr_stmt = auto_stmt.get();
2632         } else {
2633             curr_stmt = stmt;
2634         }
2635 
2636         sql  = " SELECT int_field FROM " + GetTableName() + " ORDER BY int_field";
2637         curr_stmt->ExecuteUpdate(sql);
2638 
2639         int nRows = curr_stmt->GetRowCount();
2640         BOOST_CHECK_EQUAL( 0, nRows );
2641 
2642         int nRows2 = curr_stmt->GetRowCount();
2643         BOOST_CHECK_EQUAL( 0, nRows2 );
2644     }
2645 
2646 }
2647 
2648 ////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_GetRowCount)2649 BOOST_AUTO_TEST_CASE(Test_GetRowCount)
2650 {
2651     try {
2652         {
2653             unique_ptr<IStatement> stmt( GetConnection().GetStatement() );
2654 
2655             stmt->ExecuteUpdate("DELETE FROM " + GetTableName());
2656         }
2657 
2658         enum {repeat_num = 5};
2659         for ( int i = 0; i < repeat_num; ++i ) {
2660             // Shared/Reusable statement
2661             {
2662                 unique_ptr<IStatement> stmt( GetConnection().GetStatement() );
2663 
2664                 s_CheckGetRowCount( i, eNoTrans, stmt.get() );
2665                 s_CheckGetRowCount( i, eTransCommit, stmt.get() );
2666                 s_CheckGetRowCount( i, eTransRollback, stmt.get() );
2667             }
2668             // Dedicated statement
2669             {
2670                 s_CheckGetRowCount( i, eNoTrans );
2671                 s_CheckGetRowCount( i, eTransCommit );
2672                 s_CheckGetRowCount( i, eTransRollback );
2673             }
2674         }
2675 
2676         for ( int i = 0; i < repeat_num; ++i ) {
2677             // Shared/Reusable statement
2678             {
2679                 unique_ptr<IStatement> stmt( GetConnection().GetStatement() );
2680 
2681                 s_CheckGetRowCount2( i, eNoTrans, stmt.get() );
2682                 s_CheckGetRowCount2( i, eTransCommit, stmt.get() );
2683                 s_CheckGetRowCount2( i, eTransRollback, stmt.get() );
2684             }
2685             // Dedicated statement
2686             {
2687                 s_CheckGetRowCount2( i, eNoTrans );
2688                 s_CheckGetRowCount2( i, eTransCommit );
2689                 s_CheckGetRowCount2( i, eTransRollback );
2690             }
2691         }
2692     }
2693     catch(const CException& ex) {
2694         DBAPI_BOOST_FAIL(ex);
2695     }
2696 }
2697 
2698 ///////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_HasMoreResults)2699 BOOST_AUTO_TEST_CASE(Test_HasMoreResults)
2700 {
2701     string sql;
2702     unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
2703 
2704     // First test ...
2705     // This test shouldn't throw.
2706     // Sergey Koshelkov complained that this code throws an exception with
2707     // info-level severity.
2708     // ftds (windows):  HasMoreResults() never returns;
2709     // odbs (windows):  HasMoreResults() throws exception:
2710     try {
2711         auto_stmt->SendSql( "exec sp_spaceused @updateusage='true'" );
2712 
2713         BOOST_CHECK( auto_stmt->HasMoreResults() );
2714         BOOST_CHECK( auto_stmt->HasRows() );
2715         unique_ptr<IResultSet> rs( auto_stmt->GetResultSet() );
2716         BOOST_CHECK( rs.get() != NULL );
2717 
2718         while (auto_stmt->HasMoreResults()) {
2719             if (auto_stmt->HasRows()) {
2720                 unique_ptr<IResultSet> rs( auto_stmt->GetResultSet() );
2721             }
2722         }
2723     }
2724     catch( const CDB_Exception& ex ) {
2725         DBAPI_BOOST_FAIL(ex);
2726     }
2727     catch(...) {
2728         BOOST_FAIL("Unknown error in Test_HasMoreResults");
2729     }
2730 
2731     // Second test ...
2732     {
2733         try {
2734             auto_stmt->SendSql( "exec sp_spaceused @updateusage='true'" );
2735 
2736             BOOST_CHECK( auto_stmt->HasMoreResults() );
2737             BOOST_CHECK( auto_stmt->HasRows() );
2738             unique_ptr<IResultSet> rs( auto_stmt->GetResultSet() );
2739             BOOST_CHECK( rs.get() != NULL );
2740 
2741             while (auto_stmt->HasMoreResults()) {
2742                 if (auto_stmt->HasRows()) {
2743                     unique_ptr<IResultSet> rs( auto_stmt->GetResultSet() );
2744                 }
2745             }
2746         }
2747         catch( const CDB_Exception& ex ) {
2748             DBAPI_BOOST_FAIL(ex);
2749         }
2750     }
2751 }
2752 
2753 ///////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_GetTotalColumns)2754 BOOST_AUTO_TEST_CASE(Test_GetTotalColumns)
2755 {
2756     string sql;
2757 
2758     try {
2759         unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
2760 
2761         // Create table ...
2762         {
2763             sql =
2764                 "CREATE TABLE #Overlaps ( \n"
2765                 "   pairId int NOT NULL , \n"
2766                 "   overlapNum smallint NOT NULL , \n"
2767                 "   start1 int NOT NULL , \n"
2768                 "   start2 int NOT NULL , \n"
2769                 "   stop1 int NOT NULL , \n"
2770                 "   stop2 int NOT NULL , \n"
2771                 "   orient char (2) NOT NULL , \n"
2772                 "   gaps int NOT NULL , \n"
2773                 "   mismatches int NOT NULL , \n"
2774                 "   adjustedLen int NOT NULL , \n"
2775                 "   length int NOT NULL , \n"
2776                 "   contained tinyint NOT NULL , \n"
2777                 "   seq_align text  NULL , \n"
2778                 "   merged_sa char (1) NOT NULL , \n"
2779                 "   PRIMARY KEY  \n"
2780                 "   ( \n"
2781                 "       pairId, \n"
2782                 "       overlapNum \n"
2783                 "   ) \n"
2784                 ") \n";
2785 
2786             auto_stmt->ExecuteUpdate( sql );
2787         }
2788 
2789         // Insert data into the table ...
2790         {
2791             sql =
2792                 "INSERT INTO #Overlaps VALUES( \n"
2793                 "1, 1, 0, 25794, 7126, 32916, '--', 1, 21, 7124, 7127, 0, \n"
2794                 "'Seq-align ::= { }', 'n')";
2795 
2796             auto_stmt->ExecuteUpdate( sql );
2797         }
2798 
2799         // Actual check ...
2800         {
2801             sql = "SELECT * FROM #Overlaps";
2802 
2803             auto_stmt->SendSql( sql );
2804             while( auto_stmt->HasMoreResults() ) {
2805                 if( auto_stmt->HasRows() ) {
2806                     unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
2807                     int col_num = -2;
2808 
2809     //                 switch ( rs->GetResultType() ) {
2810     //                 case eDB_RowResult:
2811     //                     col_num = rs->GetColumnNo();
2812     //                     break;
2813     //                 case eDB_ParamResult:
2814     //                     col_num = rs->GetColumnNo();
2815     //                     break;
2816     //                 case eDB_StatusResult:
2817     //                     col_num = rs->GetColumnNo();
2818     //                     break;
2819     //                 case eDB_ComputeResult:
2820     //                 case eDB_CursorResult:
2821     //                     col_num = rs->GetColumnNo();
2822     //                     break;
2823     //                 }
2824 
2825                     col_num = rs->GetTotalColumns();
2826                     BOOST_CHECK_EQUAL( 14, col_num );
2827                 }
2828             }
2829         }
2830     }
2831     catch(const CException& ex) {
2832         DBAPI_BOOST_FAIL(ex);
2833     }
2834 }
2835 
2836 ///////////////////////////////////////////////////////////////////////////////
2837 Int8
GetIdentity(const unique_ptr<IStatement> & auto_stmt)2838 GetIdentity(const unique_ptr<IStatement>& auto_stmt)
2839 {
2840     Int8 identity = 0;
2841 
2842     DumpResults(auto_stmt.get());
2843     // ClearParamList is necessary here ...
2844     auto_stmt->ClearParamList();
2845     auto_stmt->SendSql( "select CONVERT(NUMERIC(18, 0), @@identity)");
2846     while (auto_stmt->HasMoreResults()) {
2847         if (auto_stmt->HasRows()) {
2848             unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
2849             if (rs.get() != NULL) {
2850                 while (rs->Next()) {
2851                     identity = rs->GetVariant(1).GetInt8();
2852                 }
2853             }
2854         }
2855     }
2856 
2857     return identity;
2858 }
2859 
2860 ////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_Identity)2861 BOOST_AUTO_TEST_CASE(Test_Identity)
2862 {
2863     string sql;
2864     Int8 table_id = 0;
2865     Int8 identity_id = 0;
2866     EDB_Type curr_type = eDB_UnsupportedType;
2867     const IResultSetMetaData* md = NULL;
2868 
2869     try {
2870         unique_ptr<IStatement> auto_stmt(GetConnection().GetStatement());
2871 
2872         // Clean table ...
2873         auto_stmt->ExecuteUpdate("DELETE FROM " + GetTableName());
2874 
2875         // Insert data ...
2876         {
2877             // Pure SQL ...
2878             auto_stmt->ExecuteUpdate(
2879                 "INSERT INTO " + GetTableName() + "(int_field) VALUES(1)");
2880         }
2881 
2882         // Retrieve data ...
2883         {
2884             sql  = " SELECT id, int_field FROM " + GetTableName();
2885 
2886             auto_stmt->SendSql( sql );
2887 
2888             BOOST_CHECK(auto_stmt->HasMoreResults());
2889             BOOST_CHECK(auto_stmt->HasRows());
2890             unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
2891             BOOST_CHECK(rs.get() != NULL);
2892             BOOST_CHECK(rs->Next());
2893 
2894             md = rs->GetMetaData();
2895             BOOST_CHECK(md);
2896             curr_type = md->GetType(1);
2897             BOOST_CHECK_EQUAL(curr_type, eDB_BigInt);
2898 
2899             const CVariant& id_value = rs->GetVariant(1);
2900             BOOST_CHECK(!id_value.IsNull());
2901             table_id = id_value.GetInt8();
2902             BOOST_CHECK(!rs->Next());
2903         }
2904 
2905         // Retrieve identity ...
2906         {
2907             sql  = " SELECT CONVERT(NUMERIC(18, 0), @@identity) ";
2908 
2909             auto_stmt->SendSql(sql);
2910 
2911             BOOST_CHECK(auto_stmt->HasMoreResults());
2912             BOOST_CHECK(auto_stmt->HasRows());
2913             unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
2914             BOOST_CHECK(rs.get() != NULL);
2915             BOOST_CHECK(rs->Next());
2916             const CVariant& id_value = rs->GetVariant(1);
2917             BOOST_CHECK(!id_value.IsNull());
2918             identity_id = id_value.GetInt8();
2919             BOOST_CHECK(!rs->Next());
2920         }
2921 
2922         BOOST_CHECK_EQUAL(table_id, identity_id);
2923 
2924         // Check identity type ...
2925         {
2926             sql  = " SELECT @@identity ";
2927 
2928             auto_stmt->SendSql(sql);
2929 
2930             BOOST_CHECK(auto_stmt->HasMoreResults());
2931             BOOST_CHECK(auto_stmt->HasRows());
2932             unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
2933             BOOST_CHECK(rs.get() != NULL);
2934             BOOST_CHECK(rs->Next());
2935 
2936             md = rs->GetMetaData();
2937             BOOST_CHECK(md);
2938             curr_type = md->GetType(1);
2939             BOOST_CHECK_EQUAL(curr_type, eDB_Numeric);
2940 
2941             const CVariant& id_value = rs->GetVariant(1);
2942             BOOST_CHECK(!id_value.IsNull());
2943             string id_str = rs->GetVariant(1).GetString();
2944             string id_num = rs->GetVariant(1).GetNumeric();
2945             BOOST_CHECK_EQUAL(id_str, id_num);
2946 
2947             BOOST_CHECK(!rs->Next());
2948         }
2949 
2950     }
2951     catch(const CException& ex) {
2952         DBAPI_BOOST_FAIL(ex);
2953     }
2954 }
2955 
2956 ////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_StatementParameters)2957 BOOST_AUTO_TEST_CASE(Test_StatementParameters)
2958 {
2959     try {
2960         // Very first test ...
2961         {
2962             const string table_name(GetTableName());
2963 //             const string table_name("DBAPI_Sample..tmp_table_01");
2964             string sql;
2965             unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
2966 
2967             if (false) {
2968                 sql  = " CREATE TABLE " + table_name + "( \n";
2969                 sql += "    id NUMERIC(18, 0) IDENTITY NOT NULL, \n";
2970                 sql += "    int_field INT NULL \n";
2971                 sql += " )";
2972 
2973                 auto_stmt->ExecuteUpdate( sql );
2974             }
2975 
2976             // Clean previously inserted data ...
2977             {
2978                 auto_stmt->ExecuteUpdate( "DELETE FROM " + table_name );
2979             }
2980 
2981             {
2982                 sql  = " INSERT INTO " + table_name +
2983                     "(int_field) VALUES( @value ) \n";
2984 
2985                 auto_stmt->SetParam( CVariant(0), "@value" );
2986                 // Execute a statement with parameters ...
2987                 auto_stmt->ExecuteUpdate( sql );
2988 
2989                 auto_stmt->SetParam( CVariant(1), "@value" );
2990                 // Execute a statement with parameters ...
2991                 auto_stmt->ExecuteUpdate( sql );
2992 
2993                 // !!! Do not forget to clear a parameter list ....
2994                 // Workaround for the ctlib driver ...
2995                 // ClearParamList is necessary here ...
2996                 auto_stmt->ClearParamList();
2997             }
2998 
2999 
3000             {
3001                 sql  = " SELECT int_field FROM " + table_name +
3002                     " ORDER BY int_field";
3003                 // Execute a statement without parameters ...
3004                 auto_stmt->ExecuteUpdate( sql );
3005             }
3006 
3007             // Get number of records ...
3008             {
3009                 auto_stmt->SendSql( "SELECT COUNT(*) FROM " + table_name );
3010                 BOOST_CHECK( auto_stmt->HasMoreResults() );
3011                 BOOST_CHECK( auto_stmt->HasRows() );
3012                 unique_ptr<IResultSet> rs( auto_stmt->GetResultSet() );
3013                 BOOST_CHECK( rs->Next() );
3014                 BOOST_CHECK_EQUAL( rs->GetVariant(1).GetInt4(), 2 );
3015                 DumpResults(auto_stmt.get());
3016             }
3017 
3018             // Read first inserted value back ...
3019             {
3020                 // !!! Do not forget to clear a parameter list ....
3021                 // Workaround for the ctlib driver ...
3022                 // ClearParamList is necessary here ...
3023                 auto_stmt->ClearParamList();
3024 
3025                 auto_stmt->SetParam( CVariant(0), "@value" );
3026                 auto_stmt->SendSql( " SELECT int_field FROM " + table_name +
3027                                     " WHERE int_field = @value");
3028                 BOOST_CHECK( auto_stmt->HasMoreResults() );
3029                 BOOST_CHECK( auto_stmt->HasRows() );
3030                 unique_ptr<IResultSet> rs( auto_stmt->GetResultSet() );
3031                 BOOST_CHECK( rs->Next() );
3032                 BOOST_CHECK_EQUAL( rs->GetVariant(1).GetInt4(), 0 );
3033                 DumpResults(auto_stmt.get());
3034             }
3035 
3036             // Read second inserted value back ...
3037             {
3038                 // !!! Do not forget to clear a parameter list ....
3039                 // Workaround for the ctlib driver ...
3040                 // ClearParamList is necessary here ...
3041                 auto_stmt->ClearParamList();
3042 
3043                 auto_stmt->SetParam( CVariant(1), "@value" );
3044                 auto_stmt->SendSql( " SELECT int_field FROM " + table_name +
3045                                     " WHERE int_field = @value");
3046                 BOOST_CHECK( auto_stmt->HasMoreResults() );
3047                 BOOST_CHECK( auto_stmt->HasRows() );
3048                 unique_ptr<IResultSet> rs( auto_stmt->GetResultSet() );
3049                 BOOST_CHECK( rs->Next() );
3050                 BOOST_CHECK_EQUAL( rs->GetVariant(1).GetInt4(), 1 );
3051                 DumpResults(auto_stmt.get());
3052             }
3053 
3054             // Clean previously inserted data ...
3055             {
3056                 // !!! Do not forget to clear a parameter list ....
3057                 // Workaround for the ctlib driver ...
3058                 // ClearParamList is necessary here ...
3059                 auto_stmt->ClearParamList();
3060 
3061                 auto_stmt->ExecuteUpdate( "DELETE FROM " + table_name );
3062             }
3063         }
3064 
3065         // Use NULL with parameters ...
3066         if (GetArgs().GetServerType() == CDBConnParams::eSybaseSQLServer) {
3067             unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
3068 
3069             auto_stmt->SetParam( CVariant(eDB_VarChar), "@printfmt_par" );
3070             auto_stmt->SendSql( " SELECT name FROM syscolumns"
3071 //                                 " WHERE id = 4 AND printfmt = @printfmt_par");
3072                                 " WHERE printfmt = @printfmt_par");
3073             BOOST_CHECK( auto_stmt->HasMoreResults() );
3074             BOOST_CHECK( auto_stmt->HasRows() );
3075             unique_ptr<IResultSet> rs( auto_stmt->GetResultSet() );
3076             BOOST_CHECK( rs->Next() );
3077             DumpResults(auto_stmt.get());
3078         } else {
3079             GetArgs().PutMsgDisabled("Use NULL with parameters");
3080         }
3081     }
3082     catch(const CException& ex) {
3083         DBAPI_BOOST_FAIL(ex);
3084     }
3085 }
3086 
3087 ///////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_Query_Cancelation)3088 BOOST_AUTO_TEST_CASE(Test_Query_Cancelation)
3089 {
3090     string sql;
3091 
3092     try {
3093         // Cancel without a previously thrown exception.
3094         {
3095             // IStatement
3096             {
3097                 unique_ptr<IStatement> auto_stmt(GetConnection().GetStatement());
3098 
3099                 // 1
3100                 auto_stmt->SendSql("SELECT name FROM sysobjects");
3101                 auto_stmt->Cancel();
3102                 auto_stmt->Cancel();
3103 
3104                 // 2
3105                 auto_stmt->SendSql("SELECT name FROM sysobjects");
3106                 BOOST_CHECK( auto_stmt->HasMoreResults() );
3107                 BOOST_CHECK( auto_stmt->HasRows() );
3108                 {
3109                     unique_ptr<IResultSet> rs( auto_stmt->GetResultSet() );
3110                     BOOST_CHECK( rs.get() != NULL );
3111                 }
3112                 auto_stmt->Cancel();
3113                 auto_stmt->Cancel();
3114 
3115                 // 3
3116                 auto_stmt->SendSql("SELECT name FROM sysobjects");
3117                 BOOST_CHECK( auto_stmt->HasMoreResults() );
3118                 BOOST_CHECK( auto_stmt->HasRows() );
3119                 {
3120                     unique_ptr<IResultSet> rs( auto_stmt->GetResultSet() );
3121                     BOOST_CHECK( rs.get() != NULL );
3122                     BOOST_CHECK( rs->Next() );
3123                 }
3124                 auto_stmt->Cancel();
3125                 auto_stmt->Cancel();
3126 
3127                 // 4
3128                 auto_stmt->SendSql("SELECT name FROM sysobjects");
3129                 BOOST_CHECK(auto_stmt->HasMoreResults());
3130                 BOOST_CHECK(auto_stmt->HasRows());
3131                 {
3132                     int i = 0;
3133                     unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
3134                     BOOST_CHECK(rs.get() != NULL);
3135                     while (rs->Next()) {
3136                         ++i;
3137                     }
3138                     BOOST_CHECK(i > 0);
3139                 }
3140                 auto_stmt->Cancel();
3141                 auto_stmt->Cancel();
3142                 auto_stmt->Cancel();
3143             }
3144 
3145             // IColableStatement
3146             {
3147                 unique_ptr<ICallableStatement> auto_stmt;
3148 
3149                 const char *proc_name =
3150                     GetArgs().GetServerType() == CDBConnParams::eMSSqlServer ?
3151                                                      "sp_oledb_database" :
3152                                                      "sp_databases";
3153 
3154                 // 1
3155                 auto_stmt.reset(GetConnection().GetCallableStatement(proc_name));
3156                 auto_stmt->Execute();
3157                 DumpResults(auto_stmt.get());
3158                 auto_stmt->Execute();
3159                 DumpResults(auto_stmt.get());
3160 
3161                 // 2
3162                 auto_stmt->Execute();
3163                 auto_stmt->Cancel();
3164                 auto_stmt->Execute();
3165                 auto_stmt->Cancel();
3166                 auto_stmt->Cancel();
3167 
3168                 // 3
3169                 auto_stmt.reset(GetConnection().GetCallableStatement(proc_name));
3170                 auto_stmt->Execute();
3171                 auto_stmt->Cancel();
3172                 auto_stmt.reset(GetConnection().GetCallableStatement(proc_name));
3173                 auto_stmt->Execute();
3174                 auto_stmt->Cancel();
3175                 auto_stmt->Cancel();
3176 
3177                 // 4
3178                 auto_stmt.reset(GetConnection().GetCallableStatement(proc_name));
3179                 auto_stmt->Execute();
3180                 BOOST_CHECK(auto_stmt->HasMoreResults());
3181                 BOOST_CHECK(auto_stmt->HasRows());
3182                 {
3183                     unique_ptr<IResultSet> rs( auto_stmt->GetResultSet() );
3184                     BOOST_CHECK(rs.get() != NULL);
3185                 }
3186                 auto_stmt->Cancel();
3187                 auto_stmt->Cancel();
3188 
3189                 // 5
3190                 auto_stmt.reset(GetConnection().GetCallableStatement(proc_name));
3191                 auto_stmt->Execute();
3192                 BOOST_CHECK(auto_stmt->HasMoreResults());
3193                 BOOST_CHECK(auto_stmt->HasRows());
3194                 {
3195                     unique_ptr<IResultSet> rs( auto_stmt->GetResultSet() );
3196                     BOOST_CHECK(rs.get() != NULL);
3197                     BOOST_CHECK(rs->Next());
3198                 }
3199                 auto_stmt->Cancel();
3200                 auto_stmt->Cancel();
3201 
3202                 // 6
3203                 auto_stmt.reset(GetConnection().GetCallableStatement(proc_name));
3204                 auto_stmt->Execute();
3205                 BOOST_CHECK(auto_stmt->HasMoreResults());
3206                 BOOST_CHECK(auto_stmt->HasRows());
3207                 {
3208                     int i = 0;
3209                     unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
3210                     BOOST_CHECK(rs.get() != NULL);
3211                     while (rs->Next()) {
3212                         ++i;
3213                     }
3214                     BOOST_CHECK(i > 0);
3215                 }
3216                 auto_stmt->Cancel();
3217                 auto_stmt->Cancel();
3218                 auto_stmt->Cancel();
3219             }
3220 
3221             // BCP
3222             {
3223             }
3224         }
3225 
3226         // Cancel with a previously thrown exception.
3227         {
3228             // IStatement
3229             {
3230                 unique_ptr<IStatement> auto_stmt(GetConnection().GetStatement());
3231 
3232                 // 1
3233                 try {
3234                     auto_stmt->SendSql("SELECT oops FROM sysobjects");
3235                     BOOST_CHECK( auto_stmt->HasMoreResults() );
3236                 } catch(const CDB_Exception& _DEBUG_ARG(ex))
3237                 {
3238                     _TRACE(ex);
3239                     auto_stmt->Cancel();
3240                 }
3241                 auto_stmt->Cancel();
3242 
3243                 // Check that everything is fine ...
3244                 auto_stmt->SendSql("SELECT name FROM sysobjects");
3245                 DumpResults(auto_stmt.get());
3246 
3247                 // 2
3248                 try {
3249                     sql = "SELECT name FROM sysobjects WHERE name = 'oops'";
3250                     auto_stmt->SendSql(sql);
3251                     BOOST_CHECK( auto_stmt->HasMoreResults() );
3252                     BOOST_CHECK( auto_stmt->HasRows() );
3253                     unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
3254                     BOOST_CHECK(rs.get() != NULL);
3255                     rs->Next();
3256                 } catch(const CDB_Exception& _DEBUG_ARG(ex))
3257                 {
3258                     _TRACE(ex);
3259                     auto_stmt->Cancel();
3260                 }
3261                 auto_stmt->Cancel();
3262 
3263                 // Check that everything is fine ...
3264                 auto_stmt->SendSql("SELECT name FROM sysobjects");
3265                 DumpResults(auto_stmt.get());
3266 
3267                 // 3
3268                 try {
3269                     int i = 0;
3270                     auto_stmt->SendSql("SELECT name FROM sysobjects");
3271                     BOOST_CHECK( auto_stmt->HasMoreResults() );
3272                     BOOST_CHECK( auto_stmt->HasRows() );
3273                     unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
3274                     BOOST_CHECK(rs.get() != NULL);
3275                     while (rs->Next()) {
3276                         ++i;
3277                     }
3278                     BOOST_CHECK(i > 0);
3279                     rs->Next();
3280                 } catch(const CDB_Exception& _DEBUG_ARG(ex))
3281                 {
3282                     _TRACE(ex);
3283                     auto_stmt->Cancel();
3284                 }
3285                 auto_stmt->Cancel();
3286 
3287                 // Check that everything is fine ...
3288                 auto_stmt->SendSql("SELECT name FROM sysobjects");
3289                 DumpResults(auto_stmt.get());
3290             }
3291 
3292 
3293             // IColableStatement
3294             {
3295                 unique_ptr<ICallableStatement> auto_stmt;
3296 
3297                 // 1
3298                 try {
3299                     auto_stmt.reset(GetConnection().GetCallableStatement("sp_wrong"));
3300                     auto_stmt->ExecuteUpdate();
3301                 } catch(const CDB_Exception& _DEBUG_ARG(ex))
3302                 {
3303                     _TRACE(ex);
3304                     auto_stmt->Cancel();
3305                 }
3306 
3307                 try {
3308                     auto_stmt->ExecuteUpdate();
3309                 } catch(const CDB_Exception& _DEBUG_ARG(ex))
3310                 {
3311                     _TRACE(ex);
3312                     auto_stmt->Cancel();
3313                 }
3314             }
3315         }
3316     }
3317     catch(const CException& ex) {
3318         DBAPI_BOOST_FAIL(ex);
3319     }
3320 }
3321 
3322 ////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_BindByPos)3323 BOOST_AUTO_TEST_CASE(Test_BindByPos)
3324 {
3325     const long rec_num  = 10;
3326     const string table_name = GetTableName();
3327     const string str_value = "asdfghjkl";
3328     string sql;
3329 
3330     // Initialize data (strings are full of spaces) ...
3331     try {
3332         unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
3333 
3334         // First test ...
3335         {
3336             {
3337                 // Drop all records ...
3338                 sql  = " DELETE FROM " + table_name;
3339                 auto_stmt->ExecuteUpdate(sql);
3340             }
3341 
3342             {
3343                 sql  = " INSERT INTO " + table_name +
3344                     "(int_field, vc1000_field) "
3345                     "VALUES(@int_field, @vc1000_field) \n";
3346 
3347                 // !!! Do not forget to clear a parameter list ....
3348                 // Workaround for the ctlib driver ...
3349                 auto_stmt->ClearParamList();
3350 
3351                 auto_stmt->SetParam( CVariant(string(str_value)), 2);
3352 
3353                 // Insert data ...
3354                 for (long ind = 0; ind < rec_num; ++ind) {
3355                     if (ind % 2 == 0) {
3356                         auto_stmt->SetParam( CVariant( Int4(ind) ), 1);
3357                     } else {
3358                         auto_stmt->SetParam( CVariant(eDB_Int), 1);
3359                     }
3360 
3361                     // Execute a statement with parameters ...
3362                     auto_stmt->ExecuteUpdate( sql );
3363                 }
3364 
3365                 // Check record number ...
3366                 BOOST_CHECK_EQUAL(size_t(rec_num), GetNumOfRecords(auto_stmt,
3367                             GetTableName()));
3368             }
3369 
3370             // Check ...
3371             {
3372                 sql = "SELECT int_field, vc1000_field FROM " + table_name +
3373                     " ORDER BY id";
3374 
3375                 auto_stmt->SendSql( sql );
3376                 BOOST_CHECK(auto_stmt->HasMoreResults());
3377                 BOOST_CHECK(auto_stmt->HasRows());
3378                 unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
3379                 BOOST_CHECK(rs.get() != NULL);
3380 
3381                 for (long ind = 0; ind < rec_num; ++ind) {
3382                     BOOST_CHECK(rs->Next());
3383 
3384                     // const CVariant& int_field = rs->GetVariant(1);
3385                     const CVariant& vc1000_field = rs->GetVariant(2);
3386 
3387                     BOOST_CHECK( !vc1000_field.IsNull() );
3388                     BOOST_CHECK_EQUAL(vc1000_field.GetString(), str_value);
3389                 }
3390 
3391                 DumpResults(auto_stmt.get());
3392             }
3393         }
3394     }
3395     catch(const CDB_Exception& ex) {
3396         DBAPI_BOOST_FAIL(ex);
3397     }
3398 
3399 }
3400 
3401 ////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_ClearParamList)3402 BOOST_AUTO_TEST_CASE(Test_ClearParamList)
3403 {
3404     const long rec_num  = 10;
3405     const string table_name = GetTableName();
3406     const string str_value = "asdfghjkl";
3407     string sql;
3408 
3409     // Initialize data (strings are full of spaces) ...
3410     try {
3411         unique_ptr<IStatement> auto_stmt( GetConnection().GetStatement() );
3412 
3413         // First test ...
3414         {
3415             {
3416                 // Drop all records ...
3417                 sql  = " DELETE FROM " + GetTableName();
3418                 auto_stmt->ExecuteUpdate(sql);
3419             }
3420 
3421             {
3422                 sql  = " INSERT INTO " + GetTableName() +
3423                     "(int_field, vc1000_field) "
3424                     "VALUES(@int_field, @vc1000_field) \n";
3425 
3426                 // !!! Do not forget to clear a parameter list ....
3427                 // Workaround for the ctlib driver ...
3428                 auto_stmt->ClearParamList();
3429 
3430                 auto_stmt->SetParam( CVariant(string(str_value)), "@vc1000_field" );
3431 
3432                 // Insert data ...
3433                 for (long ind = 0; ind < rec_num; ++ind) {
3434                     if (ind % 2 == 0) {
3435                         auto_stmt->SetParam( CVariant( Int4(ind) ), "@int_field" );
3436                     } else {
3437                         auto_stmt->SetParam( CVariant(eDB_Int), "@int_field" );
3438                     }
3439 
3440                     // Execute a statement with parameters ...
3441                     auto_stmt->ExecuteUpdate( sql );
3442                 }
3443 
3444                 // Check record number ...
3445                 BOOST_CHECK_EQUAL(size_t(rec_num), GetNumOfRecords(auto_stmt,
3446                             GetTableName()));
3447             }
3448 
3449             // Check ...
3450             {
3451                 sql = "SELECT int_field, vc1000_field FROM " + table_name +
3452                     " ORDER BY id";
3453 
3454                 auto_stmt->SendSql( sql );
3455                 BOOST_CHECK(auto_stmt->HasMoreResults());
3456                 BOOST_CHECK(auto_stmt->HasRows());
3457                 unique_ptr<IResultSet> rs(auto_stmt->GetResultSet());
3458                 BOOST_CHECK(rs.get() != NULL);
3459 
3460                 for (long ind = 0; ind < rec_num; ++ind) {
3461                     BOOST_CHECK(rs->Next());
3462 
3463                     // const CVariant& int_field = rs->GetVariant(1);
3464                     const CVariant& vc1000_field = rs->GetVariant(2);
3465 
3466                     BOOST_CHECK( !vc1000_field.IsNull() );
3467                     BOOST_CHECK_EQUAL(vc1000_field.GetString(), str_value);
3468                     /*
3469                     if (ind % 2 == 0) {
3470                         BOOST_CHECK( !int_field.IsNull() );
3471                         BOOST_CHECK_EQUAL( int_field.GetInt4(), ind );
3472 
3473                         BOOST_CHECK( vc1000_field.IsNull() );
3474                     } else {
3475                         BOOST_CHECK( int_field.IsNull() );
3476 
3477                         BOOST_CHECK( !vc1000_field.IsNull() );
3478                         BOOST_CHECK_EQUAL( vc1000_field.GetString(),
3479                                            NStr::IntToString(ind) );
3480                     }
3481                     */
3482                 }
3483 
3484                 DumpResults(auto_stmt.get());
3485             }
3486         }
3487     }
3488     catch(const CDB_Exception& ex) {
3489         DBAPI_BOOST_FAIL(ex);
3490     }
3491 }
3492 
3493 ///////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(Test_Create_Destroy)3494 BOOST_AUTO_TEST_CASE(Test_Create_Destroy)
3495 {
3496     try {
3497         ///////////////////////
3498         // CreateStatement
3499         ///////////////////////
3500 
3501         // Destroy a statement before a connection get destroyed ...
3502         {
3503             unique_ptr<IConnection> local_conn(
3504                 GetDS().CreateConnection(eTakeOwnership)
3505                 );
3506             local_conn->Connect(GetArgs().GetConnParams());
3507 
3508             unique_ptr<IStatement> stmt(local_conn->CreateStatement());
3509             stmt->SendSql( "SELECT name FROM sysobjects" );
3510             DumpResults(stmt.get());
3511         }
3512 
3513         // Do not destroy statement, let it be destroyed ...
3514         {
3515             unique_ptr<IConnection> local_conn(
3516                 GetDS().CreateConnection(eTakeOwnership)
3517                 );
3518             local_conn->Connect(GetArgs().GetConnParams());
3519 
3520             IStatement* stmt(local_conn->CreateStatement());
3521             stmt->SendSql( "SELECT name FROM sysobjects" );
3522             DumpResults(stmt);
3523         }
3524 
3525         ///////////////////////
3526         // GetStatement
3527         ///////////////////////
3528 
3529         // Destroy a statement before a connection get destroyed ...
3530         {
3531             unique_ptr<IConnection> local_conn(
3532                 GetDS().CreateConnection(eTakeOwnership)
3533                 );
3534             local_conn->Connect(GetArgs().GetConnParams());
3535 
3536             unique_ptr<IStatement> stmt(local_conn->GetStatement());
3537             stmt->SendSql( "SELECT name FROM sysobjects" );
3538             DumpResults(stmt.get());
3539         }
3540 
3541         // Do not destroy statement, let it be destroyed ...
3542         {
3543             unique_ptr<IConnection> local_conn(
3544                 GetDS().CreateConnection(eTakeOwnership)
3545                 );
3546             local_conn->Connect(GetArgs().GetConnParams());
3547 
3548             IStatement* stmt(local_conn->GetStatement());
3549             stmt->SendSql( "SELECT name FROM sysobjects" );
3550             DumpResults(stmt);
3551         }
3552 
3553 
3554         ///////////////////////////
3555         // Close connection several times ...
3556         ///////////////////////////
3557     }
3558     catch(const CException& ex) {
3559         DBAPI_BOOST_FAIL(ex);
3560     }
3561 }
3562 
3563 
3564 END_NCBI_SCOPE
3565