windows changes
[csql.git] / src / odbc / odbcDbc.cxx
blobe91339499cf4a5afde84916443da92210781f2ab
1 /* Class CSqlOdbcDbc
2 Description: Connection Handle manager.
4 ODBC API's:
5 CSqlOdbcDbc::SQLAllocDbc();
6 CSqlOdbcDbc::SQLFreeDbc();
7 CSqlOdbcDbc::SQLConnect();
8 */
10 #ifdef WINNT
11 #define strtok_r strtok
12 #endif
13 #include "odbcCommon.h"
14 #include <SqlNwConnection.h>
16 // Constructor
17 CSqlOdbcDbc::CSqlOdbcDbc( void ) :
18 handleType_( SQL_HANDLE_DBC ),
19 parentEnv_( 0 ),
20 state_( C1 ),
21 err_( SQL_HANDLE_DBC ),
22 mode_ (1),
23 curAccessMode_( ACCESSMODE_READ_WRITE ),
24 curIsolationLevel_( READ_REPEATABLE ),
25 accessMode_( ACCESSMODE_READ_WRITE ),
26 isolationLevel_( READ_COMMITTED ),
27 autoCommit_( SQL_AUTOCOMMIT_ON ),
28 fsqlConn_( NULL )
31 SQLRETURN SQLAllocConnect(
32 SQLHENV EnvironmentHandle,
33 SQLHDBC *ConnectionHandle)
35 return( CSqlOdbcDbc::SQLAllocHandle( EnvironmentHandle, ConnectionHandle ) );
38 // All ODBC API's below.
39 SQLRETURN CSqlOdbcDbc::SQLAllocHandle(
40 SQLHANDLE inputHandle, // IN
41 SQLHANDLE *outputHandle ) // OUT
44 CSqlOdbcEnv *inputEnv = (CSqlOdbcEnv*) inputHandle;
46 if( isValidHandle( inputEnv, SQL_HANDLE_ENV ) != SQL_SUCCESS )
47 return( SQL_INVALID_HANDLE );
49 // Stop if odbcVersion not set.
50 if( inputEnv->odbcVersion_ == 0 )
52 inputEnv->err_.set( ERROR_FUNCSEQ );
53 return( SQL_ERROR );
55 if (NULL == outputHandle)
57 globalError.set(ERROR_INVARGVAL);
58 return (SQL_ERROR);
61 // Allocate Connection object.
62 *outputHandle = (SQLHANDLE*) new CSqlOdbcDbc;
63 if( *outputHandle == NULL )
65 globalError.set( ERROR_MEMALLOC );
66 globalError.printStr( SQL_OV_ODBC3 );
67 return( SQL_ERROR );
70 inputEnv->dbcList_.append(*outputHandle);
71 inputEnv->state_ = E2;
72 ((CSqlOdbcDbc*) *outputHandle)->parentEnv_ = inputEnv;
73 ((CSqlOdbcDbc*) *outputHandle)->state_ = C2;
74 return( SQL_SUCCESS );
77 SQLRETURN SQLFreeConnect(
78 SQLHDBC ConnectionHandle)
80 return( CSqlOdbcDbc::SQLFreeHandle( ConnectionHandle ) );
83 SQLRETURN CSqlOdbcDbc::SQLFreeHandle(
84 SQLHANDLE inputHandle) // IN
86 CSqlOdbcDbc *inputDbc = (CSqlOdbcDbc*) inputHandle;
88 // Validate handle
89 if( isValidHandle( inputDbc, SQL_HANDLE_DBC ) != SQL_SUCCESS )
90 return( SQL_INVALID_HANDLE );
92 // Check whether we can proceed.
93 if( inputDbc->chkStateForSQLFreeHandle() != SQL_SUCCESS )
94 return( SQL_ERROR );
96 // Remove Dbc from Parent Env.
97 ListIterator iter = inputDbc->parentEnv_->dbcList_.getIterator();
98 CSqlOdbcDbc *dbcElem = NULL;
99 while(iter.hasElement())
101 dbcElem = (CSqlOdbcDbc *) iter.nextElement();
102 if (dbcElem == inputDbc) {
103 iter.reset();
104 inputDbc->parentEnv_->dbcList_.remove(dbcElem);
105 break;
108 if( inputDbc->parentEnv_->dbcList_.size() == 0 )
109 inputDbc->parentEnv_->state_ = E1;
111 inputDbc->handleType_ = -1; // Make object invalid.
112 delete inputDbc; // Delete Dbc.
114 return( SQL_SUCCESS );
117 SQLRETURN SQLDriverConnect(
118 SQLHDBC ConnectionHandle,
119 SQLHWND WindowHandle,
120 SQLCHAR * InConnectionString,
121 SQLSMALLINT StringLength1,
122 SQLCHAR * OutConnectionString,
123 SQLSMALLINT BufferLength,
124 SQLSMALLINT * StringLength2Ptr,
125 SQLUSMALLINT DriverCompletion)
127 #ifdef DEBUG
128 printError(ErrWarning, "SQLDriverConnect");
129 #endif
131 // Validate handle
132 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
133 return( SQL_INVALID_HANDLE );
135 return( ((CSqlOdbcDbc*) ConnectionHandle)->SQLConnect(InConnectionString,
136 SQL_NTS, (SQLCHAR*)"root", (SQLSMALLINT)strlen("root"),
137 (SQLCHAR*)"manager", (SQLSMALLINT)strlen("manager")) );
141 char * CSqlOdbcDbc::getFromUrl(char *url,char *name)
143 char *token=NULL, *subtoken=NULL;
144 char *saveptr1, *saveptr2,*str1,*str2;
145 for ( str1 = url; ; str1 = NULL) {
146 token = strtok_r(str1, ";" , &saveptr1);
147 if (token == NULL)
148 break;
149 // printf("TOKEN: %s\n",token);
150 str2 = token;
151 subtoken = strtok_r(str2, "=", &saveptr2);
152 //printf(" --> %s\n", subtoken);
153 if (subtoken != NULL){
154 if(strcasecmp(subtoken,name)==0)
156 return strtok_r(NULL,"=",&saveptr2);
160 return NULL;
163 SQLRETURN SQLConnect( // All param's are IN
164 SQLHDBC ConnectionHandle,
165 SQLCHAR *ServerName,
166 SQLSMALLINT NameLength1,
167 SQLCHAR *UserName,
168 SQLSMALLINT NameLength2,
169 SQLCHAR *Authentication,
170 SQLSMALLINT NameLength3)
172 #ifdef DEBUG
173 printError(ErrWarning, "SQLConnect");
174 #endif
176 // Validate handle
177 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
178 return( SQL_INVALID_HANDLE );
180 return( ((CSqlOdbcDbc*) ConnectionHandle)->SQLConnect( ServerName, NameLength1,
181 UserName, NameLength2, Authentication, NameLength3) );
184 SQLRETURN CSqlOdbcDbc::SQLConnect( // All param's are IN
185 SQLCHAR *serverName,
186 SQLSMALLINT len1,
187 SQLCHAR *user,
188 SQLSMALLINT len2,
189 SQLCHAR *pass,
190 SQLSMALLINT len3)
192 int rc;
193 char str[IDENTIFIER_LENGTH];
194 char *dsn=NULL;
195 char *hostName = NULL;
196 char *portNo = NULL;
197 char *connMode = NULL;
198 // Start with NO_ERR
199 err_.set( NO_ERR );
200 // Can we proceed ?
201 if( chkStateForSQLConnect() != SQL_SUCCESS )
202 return( SQL_ERROR );
204 // Invalid Buffer Length.
205 if( (len1 < 0 && len1 != SQL_NTS) || (len2 < 0 && len2 != SQL_NTS) || (len2 < 0 && len2 != SQL_NTS) )
207 err_.set( ERROR_BUFLEN );
208 return( SQL_ERROR );
210 if (fsqlConn_ != NULL)
212 err_.set( ERROR_CONNINUSE);
213 return ( SQL_ERROR );
215 if (NULL == serverName)
217 err_.set(ERROR_INVARGVAL);
218 return (SQL_ERROR);
220 if (NULL == user || NULL == pass)
222 err_.set(ERROR_INVARGVAL);
223 return (SQL_ERROR);
226 strncpy(str,(char *) serverName, IDENTIFIER_LENGTH);
227 dsn = getFromUrl(str,"DSN");
228 strncpy(str,(char *) serverName, IDENTIFIER_LENGTH);
229 connMode = getFromUrl(str,"MODE");
230 strncpy(str,(char *) serverName, IDENTIFIER_LENGTH);
231 hostName = getFromUrl(str,"SERVER");
232 strncpy(str,(char *) serverName, IDENTIFIER_LENGTH);
233 portNo = getFromUrl(str,"PORT");
234 //printf("Mode=%s , hostName=%s port=%s\n",connMode,hostName,portNo);
235 if(NULL != connMode){
236 if (hostName == NULL || strcasecmp((char*)hostName, "localhost") == 0 ){
237 if (strcasecmp((char*)connMode, "Gateway") == 0){
238 fsqlConn_ = SqlFactory::createConnection(CSqlGateway);
239 mode_ = 3;
240 }else if (strcasecmp((char*)connMode, "Adapter") == 0){
241 fsqlConn_ = SqlFactory::createConnection(CSqlAdapter);
242 mode_ = 2;
243 }else if (strcasecmp((char*)connMode, "csql") == 0){
244 fsqlConn_ = SqlFactory::createConnection(CSql);
245 mode_ = 1;
246 }else return ( SQL_ERROR );
247 } else {
248 if (portNo == NULL) {
249 err_.set(ERROR_INVARGVAL);
250 return (SQL_ERROR);
252 if (strcasecmp((char*)connMode, "Gateway") == 0){
253 fsqlConn_ = SqlFactory::createConnection(CSqlNetworkGateway);
254 SqlNwConnection *con = (SqlNwConnection *)fsqlConn_;
255 con->setHost(hostName, atoi(portNo));
256 mode_ = 6;
257 }else if (strcasecmp((char*)connMode, "Adapter") == 0){
258 fsqlConn_ = SqlFactory::createConnection(CSqlNetworkAdapter);
259 SqlNwConnection *con = (SqlNwConnection *)fsqlConn_;
260 con->setHost(hostName, atoi(portNo));
261 mode_ = 5;
262 }else if (strcasecmp((char*)connMode, "csql") == 0){
263 fsqlConn_ = SqlFactory::createConnection(CSqlNetwork);
264 SqlNwConnection *con = (SqlNwConnection *)fsqlConn_;
265 con->setHost(hostName, atoi(portNo));
266 mode_ = 4;
267 }else {
268 err_.set( ERROR_INVARGVAL );
269 return ( SQL_ERROR );
273 }else{
274 fsqlConn_ = SqlFactory::createConnection(CSql);
275 mode_ = 1;
277 rc = fsqlConn_->connect( (char*) user, (char*) pass );
278 if( rc != OK )
280 err_.set( ERROR_CONNREJCTD);
281 return( SQL_ERROR );
283 rc = fsqlConn_->beginTrans( isolationLevel_ );
284 if( rc != OK )
286 err_.set( ERROR_INVTRANSTATE );
287 return( SQL_ERROR );
289 curAccessMode_ = accessMode_;
290 curIsolationLevel_ = isolationLevel_;
292 // Update Dbc state
293 state_ = C4;
295 return( SQL_SUCCESS );
299 SQLRETURN SQLDisconnect(
300 SQLHDBC ConnectionHandle) // IN
302 #ifdef DEBUG
303 printError(ErrWarning, "SQLDisConnect");
304 #endif
305 // Validate Handle
306 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
307 return( SQL_INVALID_HANDLE );
308 SQLRETURN ret = ( ((CSqlOdbcDbc*) ConnectionHandle)->SQLDisconnect() );
309 return ret;
312 SQLRETURN CSqlOdbcDbc::SQLDisconnect( void )
314 SQLRETURN rc;
316 // Start with NO_ERR
317 err_.set( NO_ERR );
319 // Can we proceed ?
320 if( chkStateForSQLDisconnect() != SQL_SUCCESS )
321 return( SQL_ERROR );
323 ListIterator iter=stmtList_.getIterator();
324 while (iter.hasElement()) {
325 rc = CSqlOdbcStmt::SQLFreeHandle(iter.nextElement());
326 if( rc != OK )
327 return( SQL_ERROR );
330 // Rollback the transaction
331 if( fsqlConn_->rollback() != OK )
332 return( SQL_ERROR );
334 // Disconnect
335 if( fsqlConn_->disconnect() != OK )
336 return( SQL_ERROR );
338 delete fsqlConn_;
339 fsqlConn_ = NULL;
340 // Change the state of Dbc
341 state_ = C2;
343 return( SQL_SUCCESS );
346 SQLRETURN CSqlOdbcDbc::SQLEndTran(
347 SQLSMALLINT completionType) // IN
349 #ifdef DEBUG
350 printError(ErrWarning, "SQLEndTran: %hd", completionType);
351 #endif
353 SQLRETURN rc;
355 // Start with NO_ERR
356 err_.set( NO_ERR );
358 // Can we proceed ?
359 if( chkStateForSQLEndTran() != SQL_SUCCESS )
360 return( SQL_ERROR );
362 // Stop if no transaction is started.
363 if( state_ != C6 )
364 return( SQL_SUCCESS );
366 // Close cursors of all the statements
367 ListIterator iter = stmtList_.getIterator();
368 CSqlOdbcStmt *stmtElem = NULL;
369 while (iter.hasElement()) {
370 stmtElem = (CSqlOdbcStmt *) iter.nextElement();
371 stmtElem->SQLFreeHandle( SQL_CLOSE );
373 // Finish transaction
374 switch( completionType )
376 case SQL_COMMIT:
378 if( fsqlConn_->commit() != OK )
379 return( SQL_ERROR );
381 if( fsqlConn_->beginTrans( curIsolationLevel_ ) != OK )
382 return( SQL_ERROR );
384 break;
386 case SQL_ROLLBACK:
387 if( fsqlConn_->rollback() != OK )
388 return( SQL_ERROR );
390 rc = fsqlConn_->beginTrans( curIsolationLevel_ );
391 break;
393 default: err_.set( ERROR_OPTRANGE );
394 return( SQL_ERROR );
397 // Had statements ?
398 if( stmtList_.size() == 0 )
399 state_ = C4;
400 else
401 state_ = C5;
403 return( SQL_SUCCESS );
406 SQLRETURN SQLSetConnectOption(
407 SQLHDBC ConnectionHandle,
408 SQLUSMALLINT Option,
409 SQLUINTEGER Value)
411 return( SQLSetConnectAttr( ConnectionHandle, Option, (SQLPOINTER) Value, 0) );
414 SQLRETURN SQLSetConnectAttr(
415 SQLHDBC ConnectionHandle,
416 SQLINTEGER Attribute,
417 SQLPOINTER Value,
418 SQLINTEGER StringLength)
420 // Validate handle
421 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
422 return( SQL_INVALID_HANDLE );
424 return( ((CSqlOdbcDbc*)ConnectionHandle)->SQLSetConnectAttr( Attribute, Value, StringLength ) );
427 SQLRETURN CSqlOdbcDbc::SQLSetConnectAttr(
428 SQLINTEGER attribute,
429 SQLPOINTER value,
430 SQLINTEGER stringLength)
432 // Start with NO_ERR
433 err_.set( NO_ERR );
435 switch( attribute )
437 case SQL_ATTR_ACCESS_MODE:
438 // validate 'value'
439 if( (SQLUINTEGER) value == SQL_MODE_READ_ONLY )
440 accessMode_ = ACCESSMODE_READ_ONLY;
441 else if( (SQLUINTEGER) value == SQL_MODE_READ_WRITE )
442 accessMode_ = ACCESSMODE_READ_WRITE;
443 else
444 return( SQL_ERROR );
446 break;
447 case SQL_DEFAULT_TXN_ISOLATION:
448 case SQL_ATTR_TXN_ISOLATION:
449 // validate 'value'
450 if( (SQLUINTEGER) value == SQL_TXN_READ_UNCOMMITTED )
451 isolationLevel_ = READ_UNCOMMITTED;
452 else if( (SQLUINTEGER) value == SQL_TXN_READ_COMMITTED )
453 isolationLevel_ = READ_COMMITTED;
454 else if( (SQLUINTEGER) value == SQL_TXN_REPEATABLE_READ )
455 isolationLevel_ = READ_REPEATABLE;
456 // else if( (SQLUINTEGER) value == SQL_TXN_SERIALIZABLE )
457 // isolationLevel_ = SERIALIZABLE;
458 else
459 return( SQL_ERROR );
461 break;
462 case SQL_ATTR_AUTOCOMMIT:
463 autoCommit_ = (SQLUINTEGER) value;
464 if( state_ == C6 )
465 SQLEndTran( SQL_COMMIT );
466 break;
468 default: err_.set( ERROR_OPTRANGE );
469 return( SQL_ERROR );
472 return( SQL_SUCCESS );
475 SQLRETURN SQLGetConnectOption(
476 SQLHDBC ConnectionHandle,
477 SQLUSMALLINT Option,
478 SQLPOINTER Value)
480 return( SQLGetConnectAttr( ConnectionHandle, Option, Value, 0, 0) );
483 SQLRETURN SQLGetConnectAttr(
484 SQLHDBC ConnectionHandle,
485 SQLINTEGER Attribute,
486 SQLPOINTER Value,
487 SQLINTEGER BufferLength,
488 SQLINTEGER *StringLength)
490 // Validate handle
491 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
492 return( SQL_INVALID_HANDLE );
494 return( ((CSqlOdbcDbc*)ConnectionHandle)->SQLGetConnectAttr( Attribute, Value, BufferLength, StringLength ) );
497 SQLRETURN CSqlOdbcDbc::SQLGetConnectAttr(
498 SQLINTEGER attribute,
499 SQLPOINTER value,
500 SQLINTEGER bufferLength,
501 SQLINTEGER *stringLength)
503 // Start with NO_ERR
504 err_.set( NO_ERR );
506 switch( attribute )
508 case SQL_ATTR_ACCESS_MODE:
509 // Get ODBC Access Mode
510 if( accessMode_ == ACCESSMODE_READ_ONLY )
511 *((SQLUINTEGER*) value) = SQL_MODE_READ_ONLY;
512 else if( accessMode_ == ACCESSMODE_READ_WRITE )
513 *((SQLUINTEGER*) value) = SQL_MODE_READ_WRITE;
514 else
515 return( SQL_ERROR );
517 break;
518 case SQL_DEFAULT_TXN_ISOLATION:
519 case SQL_ATTR_TXN_ISOLATION:
520 // validate 'value'
521 if( (SQLUINTEGER) isolationLevel_ == READ_UNCOMMITTED )
522 *((SQLUINTEGER*) value) = SQL_TXN_READ_UNCOMMITTED;
523 else if( (SQLUINTEGER) isolationLevel_ == READ_COMMITTED )
524 *((SQLUINTEGER*) value) = SQL_TXN_READ_COMMITTED;
525 else if( (SQLUINTEGER) isolationLevel_ == READ_REPEATABLE )
526 *((SQLUINTEGER*) value) = SQL_TXN_REPEATABLE_READ;
527 // else if( (SQLUINTEGER) isolationLevel_ == SERIALIZABLE )
528 // *((SQLUINTEGER*) value) = SQL_TXN_SERIALIZABLE;
529 else
530 return( SQL_ERROR );
532 break;
533 case SQL_ATTR_AUTOCOMMIT:
534 *((SQLUINTEGER*) value) = autoCommit_;
535 break;
537 default: err_.set( ERROR_OPTRANGE );
538 return( SQL_ERROR );
541 return( SQL_SUCCESS );
544 /*SQLRETURN SQLGetFunctions(
545 SQLHDBC ConnectionHandle,
546 SQLUSMALLINT FunctionId,
547 SQLUSMALLINT * SupportedPtr)
549 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
550 return( SQL_INVALID_HANDLE );
551 return( ((CSqlOdbcDbc*)ConnectionHandle)->SQLGetFunctions(FunctionId,SupportedPtr) );
554 SQLRETURN CSqlOdbcDbc::SQLGetFunctions(
555 SQLUSMALLINT FunctionId,
556 SQLUSMALLINT * SupportedPtr)
558 if (NULL == SupportedPtr)
560 err_.set(ERROR_INVARGVAL);
561 return (SQL_ERROR);
563 if(isFunctionSupports(FunctionId))
564 *SupportedPtr = SQL_TRUE ;
565 else
566 *SupportedPtr = SQL_FALSE;
567 return (SQL_SUCCESS);
572 SQLRETURN SQLGetInfo(
573 SQLHDBC ConnectionHandle,
574 SQLUSMALLINT InfoType,
575 SQLPOINTER InfoValuePtr,
576 SQLSMALLINT BufferLength,
577 SQLSMALLINT * StringLengthPtr)
579 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
580 return( SQL_INVALID_HANDLE );
582 return( ((CSqlOdbcDbc*)ConnectionHandle)->SQLGetInfo( InfoType,InfoValuePtr,BufferLength,StringLengthPtr ) );
586 SQLRETURN CSqlOdbcDbc::SQLGetInfo(
587 SQLUSMALLINT InfoType,
588 SQLPOINTER InfoValuePtr,
589 SQLSMALLINT BufferLength,
590 SQLSMALLINT * StringLengthPtr)
592 return (SQL_SUCCESS);