adding support for mutex from D flag
[csql.git] / src / odbc / odbcDbc.cxx
blobbe17a1d6095330442e2b8535aa89e3791ed2a4cd
1 /* Class CSqlOdbcDbc
2 Description: Connection Handle manager.
4 ODBC API's:
5 CSqlOdbcDbc::SQLAllocDbc();
6 CSqlOdbcDbc::SQLFreeDbc();
7 CSqlOdbcDbc::SQLConnect();
8 */
10 #include "odbcCommon.h"
11 #include <SqlNwConnection.h>
13 // Constructor
14 CSqlOdbcDbc::CSqlOdbcDbc( void ) :
15 handleType_( SQL_HANDLE_DBC ),
16 parentEnv_( 0 ),
17 state_( C1 ),
18 err_( SQL_HANDLE_DBC ),
19 mode_ (1),
20 curAccessMode_( ACCESSMODE_READ_WRITE ),
21 curIsolationLevel_( READ_REPEATABLE ),
22 accessMode_( ACCESSMODE_READ_WRITE ),
23 isolationLevel_( READ_COMMITTED ),
24 autoCommit_( SQL_AUTOCOMMIT_ON ),
25 fsqlConn_( NULL )
28 SQLRETURN SQLAllocConnect(
29 SQLHENV EnvironmentHandle,
30 SQLHDBC *ConnectionHandle)
32 return( CSqlOdbcDbc::SQLAllocHandle( EnvironmentHandle, ConnectionHandle ) );
35 // All ODBC API's below.
36 SQLRETURN CSqlOdbcDbc::SQLAllocHandle(
37 SQLHANDLE inputHandle, // IN
38 SQLHANDLE *outputHandle ) // OUT
41 CSqlOdbcEnv *inputEnv = (CSqlOdbcEnv*) inputHandle;
43 if( isValidHandle( inputEnv, SQL_HANDLE_ENV ) != SQL_SUCCESS )
44 return( SQL_INVALID_HANDLE );
46 // Stop if odbcVersion not set.
47 if( inputEnv->odbcVersion_ == 0 )
49 inputEnv->err_.set( ERROR_FUNCSEQ );
50 return( SQL_ERROR );
52 if (NULL == outputHandle)
54 globalError.set(ERROR_INVARGVAL);
55 return (SQL_ERROR);
58 // Allocate Connection object.
59 *outputHandle = (SQLHANDLE*) new CSqlOdbcDbc;
60 if( *outputHandle == NULL )
62 globalError.set( ERROR_MEMALLOC );
63 globalError.printStr( SQL_OV_ODBC3 );
64 return( SQL_ERROR );
67 inputEnv->dbcList_.append(*outputHandle);
68 inputEnv->state_ = E2;
69 ((CSqlOdbcDbc*) *outputHandle)->parentEnv_ = inputEnv;
70 ((CSqlOdbcDbc*) *outputHandle)->state_ = C2;
71 return( SQL_SUCCESS );
74 SQLRETURN SQLFreeConnect(
75 SQLHDBC ConnectionHandle)
77 return( CSqlOdbcDbc::SQLFreeHandle( ConnectionHandle ) );
80 SQLRETURN CSqlOdbcDbc::SQLFreeHandle(
81 SQLHANDLE inputHandle) // IN
83 CSqlOdbcDbc *inputDbc = (CSqlOdbcDbc*) inputHandle;
85 // Validate handle
86 if( isValidHandle( inputDbc, SQL_HANDLE_DBC ) != SQL_SUCCESS )
87 return( SQL_INVALID_HANDLE );
89 // Check whether we can proceed.
90 if( inputDbc->chkStateForSQLFreeHandle() != SQL_SUCCESS )
91 return( SQL_ERROR );
93 // Remove Dbc from Parent Env.
94 ListIterator iter = inputDbc->parentEnv_->dbcList_.getIterator();
95 CSqlOdbcDbc *dbcElem = NULL;
96 while(iter.hasElement())
98 dbcElem = (CSqlOdbcDbc *) iter.nextElement();
99 if (dbcElem == inputDbc) {
100 iter.reset();
101 inputDbc->parentEnv_->dbcList_.remove(dbcElem);
102 break;
105 if( inputDbc->parentEnv_->dbcList_.size() == 0 )
106 inputDbc->parentEnv_->state_ = E1;
108 inputDbc->handleType_ = -1; // Make object invalid.
109 delete inputDbc; // Delete Dbc.
111 return( SQL_SUCCESS );
114 SQLRETURN SQLDriverConnect(
115 SQLHDBC ConnectionHandle,
116 SQLHWND WindowHandle,
117 SQLCHAR * InConnectionString,
118 SQLSMALLINT StringLength1,
119 SQLCHAR * OutConnectionString,
120 SQLSMALLINT BufferLength,
121 SQLSMALLINT * StringLength2Ptr,
122 SQLUSMALLINT DriverCompletion)
124 #ifdef DEBUG
125 printError(ErrWarning, "SQLDriverConnect");
126 #endif
128 // Validate handle
129 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
130 return( SQL_INVALID_HANDLE );
132 return( ((CSqlOdbcDbc*) ConnectionHandle)->SQLConnect(InConnectionString,
133 SQL_NTS, (SQLCHAR*)"root", (SQLSMALLINT)strlen("root"),
134 (SQLCHAR*)"manager", (SQLSMALLINT)strlen("manager")) );
138 char * CSqlOdbcDbc::getFromUrl(char *url,char *name)
140 char *token=NULL, *subtoken=NULL;
141 char *saveptr1, *saveptr2,*str1,*str2;
142 for ( str1 = url; ; str1 = NULL) {
143 token = strtok_r(str1, ";" , &saveptr1);
144 if (token == NULL)
145 break;
146 // printf("TOKEN: %s\n",token);
147 str2 = token;
148 subtoken = strtok_r(str2, "=", &saveptr2);
149 //printf(" --> %s\n", subtoken);
150 if (subtoken != NULL){
151 if(strcasecmp(subtoken,name)==0)
153 return strtok_r(NULL,"=",&saveptr2);
157 return NULL;
160 SQLRETURN SQLConnect( // All param's are IN
161 SQLHDBC ConnectionHandle,
162 SQLCHAR *ServerName,
163 SQLSMALLINT NameLength1,
164 SQLCHAR *UserName,
165 SQLSMALLINT NameLength2,
166 SQLCHAR *Authentication,
167 SQLSMALLINT NameLength3)
169 #ifdef DEBUG
170 printError(ErrWarning, "SQLConnect");
171 #endif
173 // Validate handle
174 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
175 return( SQL_INVALID_HANDLE );
177 return( ((CSqlOdbcDbc*) ConnectionHandle)->SQLConnect( ServerName, NameLength1,
178 UserName, NameLength2, Authentication, NameLength3) );
181 SQLRETURN CSqlOdbcDbc::SQLConnect( // All param's are IN
182 SQLCHAR *serverName,
183 SQLSMALLINT len1,
184 SQLCHAR *user,
185 SQLSMALLINT len2,
186 SQLCHAR *pass,
187 SQLSMALLINT len3)
189 int rc;
190 char str[IDENTIFIER_LENGTH];
191 char *dsn=NULL;
192 char *hostName = NULL;
193 char *portNo = NULL;
194 char *connMode = NULL;
195 // Start with NO_ERR
196 err_.set( NO_ERR );
197 // Can we proceed ?
198 if( chkStateForSQLConnect() != SQL_SUCCESS )
199 return( SQL_ERROR );
201 // Invalid Buffer Length.
202 if( (len1 < 0 && len1 != SQL_NTS) || (len2 < 0 && len2 != SQL_NTS) || (len2 < 0 && len2 != SQL_NTS) )
204 err_.set( ERROR_BUFLEN );
205 return( SQL_ERROR );
207 if (fsqlConn_ != NULL)
209 err_.set( ERROR_CONNINUSE);
210 return ( SQL_ERROR );
212 if (NULL == serverName)
214 err_.set(ERROR_INVARGVAL);
215 return (SQL_ERROR);
217 if (NULL == user || NULL == pass)
219 err_.set(ERROR_INVARGVAL);
220 return (SQL_ERROR);
223 strncpy(str,(char *) serverName, IDENTIFIER_LENGTH);
224 dsn = getFromUrl(str,"DSN");
225 strncpy(str,(char *) serverName, IDENTIFIER_LENGTH);
226 connMode = getFromUrl(str,"MODE");
227 strncpy(str,(char *) serverName, IDENTIFIER_LENGTH);
228 hostName = getFromUrl(str,"SERVER");
229 strncpy(str,(char *) serverName, IDENTIFIER_LENGTH);
230 portNo = getFromUrl(str,"PORT");
231 //printf("Mode=%s , hostName=%s port=%s\n",connMode,hostName,portNo);
232 if(NULL != connMode){
233 if (hostName == NULL || strcasecmp((char*)hostName, "localhost") == 0 ){
234 if (strcasecmp((char*)connMode, "Gateway") == 0){
235 fsqlConn_ = SqlFactory::createConnection(CSqlGateway);
236 mode_ = 3;
237 }else if (strcasecmp((char*)connMode, "Adapter") == 0){
238 fsqlConn_ = SqlFactory::createConnection(CSqlAdapter);
239 mode_ = 2;
240 }else if (strcasecmp((char*)connMode, "csql") == 0){
241 fsqlConn_ = SqlFactory::createConnection(CSql);
242 mode_ = 1;
243 }else return ( SQL_ERROR );
244 } else {
245 if (portNo == NULL) {
246 err_.set(ERROR_INVARGVAL);
247 return (SQL_ERROR);
249 if (strcasecmp((char*)connMode, "Gateway") == 0){
250 fsqlConn_ = SqlFactory::createConnection(CSqlNetworkGateway);
251 SqlNwConnection *con = (SqlNwConnection *)fsqlConn_;
252 con->setHost(hostName, atoi(portNo));
253 mode_ = 6;
254 }else if (strcasecmp((char*)connMode, "Adapter") == 0){
255 fsqlConn_ = SqlFactory::createConnection(CSqlNetworkAdapter);
256 SqlNwConnection *con = (SqlNwConnection *)fsqlConn_;
257 con->setHost(hostName, atoi(portNo));
258 mode_ = 5;
259 }else if (strcasecmp((char*)connMode, "csql") == 0){
260 fsqlConn_ = SqlFactory::createConnection(CSqlNetwork);
261 SqlNwConnection *con = (SqlNwConnection *)fsqlConn_;
262 con->setHost(hostName, atoi(portNo));
263 mode_ = 4;
264 }else {
265 err_.set( ERROR_INVARGVAL );
266 return ( SQL_ERROR );
270 }else{
271 fsqlConn_ = SqlFactory::createConnection(CSql);
272 mode_ = 1;
274 rc = fsqlConn_->connect( (char*) user, (char*) pass );
275 if( rc != OK )
277 err_.set( ERROR_CONNREJCTD);
278 return( SQL_ERROR );
280 rc = fsqlConn_->beginTrans( isolationLevel_ );
281 if( rc != OK )
283 err_.set( ERROR_INVTRANSTATE );
284 return( SQL_ERROR );
286 curAccessMode_ = accessMode_;
287 curIsolationLevel_ = isolationLevel_;
289 // Update Dbc state
290 state_ = C4;
292 return( SQL_SUCCESS );
296 SQLRETURN SQLDisconnect(
297 SQLHDBC ConnectionHandle) // IN
299 #ifdef DEBUG
300 printError(ErrWarning, "SQLDisConnect");
301 #endif
302 // Validate Handle
303 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
304 return( SQL_INVALID_HANDLE );
305 SQLRETURN ret = ( ((CSqlOdbcDbc*) ConnectionHandle)->SQLDisconnect() );
306 return ret;
309 SQLRETURN CSqlOdbcDbc::SQLDisconnect( void )
311 SQLRETURN rc;
313 // Start with NO_ERR
314 err_.set( NO_ERR );
316 // Can we proceed ?
317 if( chkStateForSQLDisconnect() != SQL_SUCCESS )
318 return( SQL_ERROR );
320 ListIterator iter=stmtList_.getIterator();
321 while (iter.hasElement()) {
322 rc = CSqlOdbcStmt::SQLFreeHandle(iter.nextElement());
323 if( rc != OK )
324 return( SQL_ERROR );
327 // Rollback the transaction
328 if( fsqlConn_->rollback() != OK )
329 return( SQL_ERROR );
331 // Disconnect
332 if( fsqlConn_->disconnect() != OK )
333 return( SQL_ERROR );
335 delete fsqlConn_;
336 fsqlConn_ = NULL;
337 // Change the state of Dbc
338 state_ = C2;
340 return( SQL_SUCCESS );
343 SQLRETURN CSqlOdbcDbc::SQLEndTran(
344 SQLSMALLINT completionType) // IN
346 #ifdef DEBUG
347 printError(ErrWarning, "SQLEndTran: %hd", completionType);
348 #endif
350 SQLRETURN rc;
352 // Start with NO_ERR
353 err_.set( NO_ERR );
355 // Can we proceed ?
356 if( chkStateForSQLEndTran() != SQL_SUCCESS )
357 return( SQL_ERROR );
359 // Stop if no transaction is started.
360 if( state_ != C6 )
361 return( SQL_SUCCESS );
363 // Close cursors of all the statements
364 ListIterator iter = stmtList_.getIterator();
365 CSqlOdbcStmt *stmtElem = NULL;
366 while (iter.hasElement()) {
367 stmtElem = (CSqlOdbcStmt *) iter.nextElement();
368 stmtElem->SQLFreeHandle( SQL_CLOSE );
370 // Finish transaction
371 switch( completionType )
373 case SQL_COMMIT:
375 if( fsqlConn_->commit() != OK )
376 return( SQL_ERROR );
378 if( fsqlConn_->beginTrans( curIsolationLevel_ ) != OK )
379 return( SQL_ERROR );
381 break;
383 case SQL_ROLLBACK:
384 if( fsqlConn_->rollback() != OK )
385 return( SQL_ERROR );
387 rc = fsqlConn_->beginTrans( curIsolationLevel_ );
388 break;
390 default: err_.set( ERROR_OPTRANGE );
391 return( SQL_ERROR );
394 // Had statements ?
395 if( stmtList_.size() == 0 )
396 state_ = C4;
397 else
398 state_ = C5;
400 return( SQL_SUCCESS );
403 SQLRETURN SQLSetConnectOption(
404 SQLHDBC ConnectionHandle,
405 SQLUSMALLINT Option,
406 SQLUINTEGER Value)
408 return( SQLSetConnectAttr( ConnectionHandle, Option, (SQLPOINTER) Value, 0) );
411 SQLRETURN SQLSetConnectAttr(
412 SQLHDBC ConnectionHandle,
413 SQLINTEGER Attribute,
414 SQLPOINTER Value,
415 SQLINTEGER StringLength)
417 // Validate handle
418 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
419 return( SQL_INVALID_HANDLE );
421 return( ((CSqlOdbcDbc*)ConnectionHandle)->SQLSetConnectAttr( Attribute, Value, StringLength ) );
424 SQLRETURN CSqlOdbcDbc::SQLSetConnectAttr(
425 SQLINTEGER attribute,
426 SQLPOINTER value,
427 SQLINTEGER stringLength)
429 // Start with NO_ERR
430 err_.set( NO_ERR );
432 switch( attribute )
434 case SQL_ATTR_ACCESS_MODE:
435 // validate 'value'
436 if( (SQLUINTEGER) value == SQL_MODE_READ_ONLY )
437 accessMode_ = ACCESSMODE_READ_ONLY;
438 else if( (SQLUINTEGER) value == SQL_MODE_READ_WRITE )
439 accessMode_ = ACCESSMODE_READ_WRITE;
440 else
441 return( SQL_ERROR );
443 break;
444 case SQL_DEFAULT_TXN_ISOLATION:
445 case SQL_ATTR_TXN_ISOLATION:
446 // validate 'value'
447 if( (SQLUINTEGER) value == SQL_TXN_READ_UNCOMMITTED )
448 isolationLevel_ = READ_UNCOMMITTED;
449 else if( (SQLUINTEGER) value == SQL_TXN_READ_COMMITTED )
450 isolationLevel_ = READ_COMMITTED;
451 else if( (SQLUINTEGER) value == SQL_TXN_REPEATABLE_READ )
452 isolationLevel_ = READ_REPEATABLE;
453 // else if( (SQLUINTEGER) value == SQL_TXN_SERIALIZABLE )
454 // isolationLevel_ = SERIALIZABLE;
455 else
456 return( SQL_ERROR );
458 break;
459 case SQL_ATTR_AUTOCOMMIT:
460 autoCommit_ = (SQLUINTEGER) value;
461 if( state_ == C6 )
462 SQLEndTran( SQL_COMMIT );
463 break;
465 default: err_.set( ERROR_OPTRANGE );
466 return( SQL_ERROR );
469 return( SQL_SUCCESS );
472 SQLRETURN SQLGetConnectOption(
473 SQLHDBC ConnectionHandle,
474 SQLUSMALLINT Option,
475 SQLPOINTER Value)
477 return( SQLGetConnectAttr( ConnectionHandle, Option, Value, 0, 0) );
480 SQLRETURN SQLGetConnectAttr(
481 SQLHDBC ConnectionHandle,
482 SQLINTEGER Attribute,
483 SQLPOINTER Value,
484 SQLINTEGER BufferLength,
485 SQLINTEGER *StringLength)
487 // Validate handle
488 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
489 return( SQL_INVALID_HANDLE );
491 return( ((CSqlOdbcDbc*)ConnectionHandle)->SQLGetConnectAttr( Attribute, Value, BufferLength, StringLength ) );
494 SQLRETURN CSqlOdbcDbc::SQLGetConnectAttr(
495 SQLINTEGER attribute,
496 SQLPOINTER value,
497 SQLINTEGER bufferLength,
498 SQLINTEGER *stringLength)
500 // Start with NO_ERR
501 err_.set( NO_ERR );
503 switch( attribute )
505 case SQL_ATTR_ACCESS_MODE:
506 // Get ODBC Access Mode
507 if( accessMode_ == ACCESSMODE_READ_ONLY )
508 *((SQLUINTEGER*) value) = SQL_MODE_READ_ONLY;
509 else if( accessMode_ == ACCESSMODE_READ_WRITE )
510 *((SQLUINTEGER*) value) = SQL_MODE_READ_WRITE;
511 else
512 return( SQL_ERROR );
514 break;
515 case SQL_DEFAULT_TXN_ISOLATION:
516 case SQL_ATTR_TXN_ISOLATION:
517 // validate 'value'
518 if( (SQLUINTEGER) isolationLevel_ == READ_UNCOMMITTED )
519 *((SQLUINTEGER*) value) = SQL_TXN_READ_UNCOMMITTED;
520 else if( (SQLUINTEGER) isolationLevel_ == READ_COMMITTED )
521 *((SQLUINTEGER*) value) = SQL_TXN_READ_COMMITTED;
522 else if( (SQLUINTEGER) isolationLevel_ == READ_REPEATABLE )
523 *((SQLUINTEGER*) value) = SQL_TXN_REPEATABLE_READ;
524 // else if( (SQLUINTEGER) isolationLevel_ == SERIALIZABLE )
525 // *((SQLUINTEGER*) value) = SQL_TXN_SERIALIZABLE;
526 else
527 return( SQL_ERROR );
529 break;
530 case SQL_ATTR_AUTOCOMMIT:
531 *((SQLUINTEGER*) value) = autoCommit_;
532 break;
534 default: err_.set( ERROR_OPTRANGE );
535 return( SQL_ERROR );
538 return( SQL_SUCCESS );
541 /*SQLRETURN SQLGetFunctions(
542 SQLHDBC ConnectionHandle,
543 SQLUSMALLINT FunctionId,
544 SQLUSMALLINT * SupportedPtr)
546 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
547 return( SQL_INVALID_HANDLE );
548 return( ((CSqlOdbcDbc*)ConnectionHandle)->SQLGetFunctions(FunctionId,SupportedPtr) );
551 SQLRETURN CSqlOdbcDbc::SQLGetFunctions(
552 SQLUSMALLINT FunctionId,
553 SQLUSMALLINT * SupportedPtr)
555 if (NULL == SupportedPtr)
557 err_.set(ERROR_INVARGVAL);
558 return (SQL_ERROR);
560 if(isFunctionSupports(FunctionId))
561 *SupportedPtr = SQL_TRUE ;
562 else
563 *SupportedPtr = SQL_FALSE;
564 return (SQL_SUCCESS);
569 SQLRETURN SQLGetInfo(
570 SQLHDBC ConnectionHandle,
571 SQLUSMALLINT InfoType,
572 SQLPOINTER InfoValuePtr,
573 SQLSMALLINT BufferLength,
574 SQLSMALLINT * StringLengthPtr)
576 if( isValidHandle( ConnectionHandle, SQL_HANDLE_DBC ) != SQL_SUCCESS )
577 return( SQL_INVALID_HANDLE );
579 return( ((CSqlOdbcDbc*)ConnectionHandle)->SQLGetInfo( InfoType,InfoValuePtr,BufferLength,StringLengthPtr ) );
583 SQLRETURN CSqlOdbcDbc::SQLGetInfo(
584 SQLUSMALLINT InfoType,
585 SQLPOINTER InfoValuePtr,
586 SQLSMALLINT BufferLength,
587 SQLSMALLINT * StringLengthPtr)
589 return (SQL_SUCCESS);