SqlNwConnection and statement can be created by SqlFactory class.
[csql.git] / src / network / SqlNetworkHandler.cxx
blob104fcdd98aaf36465e7292875b1826603f642310
1 /***************************************************************************
2 * Copyright (C) 2007 by Prabakaran Thirumalai *
3 * praba_tuty@yahoo.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #include <SqlNetworkHandler.h>
21 #include <AbsSqlConnection.h>
22 #include <SqlConnection.h>
23 #include <SqlOdbcConnection.h>
24 #include <AbsSqlStatement.h>
25 #include <SqlStatement.h>
26 #include <SqlOdbcStatement.h>
27 #include <SqlLogStatement.h>
28 #include <Parser.h>
30 List SqlNetworkHandler::stmtList;
31 AbsSqlConnection* SqlNetworkHandler::conn;
32 SqlApiImplType SqlNetworkHandler::type;
33 int SqlNetworkHandler::stmtID;
35 void *SqlNetworkHandler::process(PacketHeader &header, char *buffer)
37 DbRetVal rv = OK;
38 char *ptr = NULL;
39 ResponsePacket *rpkt = NULL;
40 switch(header.packetType)
42 // case NW_PKT_PREPARE:
43 //return processPrepare(header, buffer);
44 // break;
45 //case NW_PKT_COMMIT:
46 //return processCommit(header, buffer);
47 // break;
48 case SQL_NW_PKT_CONNECT:
49 return processSqlConnect(header, buffer);
50 break;
51 case SQL_NW_PKT_PREPARE:
52 return processSqlPrepare(header, buffer);
53 break;
54 case SQL_NW_PKT_EXECUTE:
55 return processSqlExecute(header, buffer);
56 break;
57 case SQL_NW_PKT_FETCH:
58 return processSqlFetch(header, buffer);
59 break;
60 case SQL_NW_PKT_COMMIT:
61 return processSqlCommit(header, buffer);
62 break;
63 case SQL_NW_PKT_ROLLBACK:
64 return processSqlRollback(header, buffer);
65 break;
66 case SQL_NW_PKT_DISCONNECT:
67 conn->rollback();
68 rv = conn->disconnect();
69 rpkt = new ResponsePacket();
70 ptr = (char *) &rpkt->retVal;
71 *ptr = 1;
72 strcpy(rpkt->errorString, "Success");
73 return rpkt;
74 case SQL_NW_PKT_FREE:
75 return processSqlFree(header, buffer);
76 break;
80 void * SqlNetworkHandler::processSqlConnect(PacketHeader &header, char *buffer)
82 ResponsePacket *rpkt = new ResponsePacket();
83 printDebug(DM_Network, "Processing CONNECT");
84 SqlPacketConnect *pkt = new SqlPacketConnect();
85 pkt->setBuffer(buffer);
86 pkt->setBufferSize(header.packetLength);
87 pkt->unmarshall();
88 type = (SqlApiImplType) pkt->sqlApiImplType;
89 conn = createConnection(type);
90 char *ptr = (char *) &rpkt->retVal;
91 DbRetVal rv=conn->connect(pkt->userName, pkt->passWord);
92 if (rv != OK) {
93 *ptr = 0;
94 strcpy(rpkt->errorString, "User Authentication Failure");
95 return rpkt;
96 printf("connection failure\n");
98 if (rv == OK) {
99 *ptr = 1;
100 rv = conn->beginTrans();
101 return rpkt;
105 void* SqlNetworkHandler::processSqlPrepare(PacketHeader &header, char *buffer)
107 ResponsePacket *rpkt = new ResponsePacket();
108 rpkt->isSelect = false;
109 char *retval = (char *) &rpkt->retVal;
110 SqlPacketPrepare *pkt = new SqlPacketPrepare();
111 pkt->setBuffer(buffer);
112 pkt->setBufferSize(header.packetLength);
113 pkt->unmarshall();
114 printDebug(DM_Network, "PREPARE %s\n", pkt->stmtString);
115 AbsSqlStatement *sqlstmt = createStatement(type);
116 sqlstmt->setConnection(conn);
117 NetworkStmt *nwStmt = new NetworkStmt();
118 nwStmt->stmtID = ++stmtID;
119 printDebug(DM_Network, "Statement string %s\n", pkt->stmtString);
120 nwStmt->stmt = sqlstmt;
121 DbRetVal rv = sqlstmt->prepare(pkt->stmtString);
122 if (rv != OK)
124 printError(ErrSysInit, "statement prepare failed\n");
125 *retval = 0;
126 strcpy(rpkt->errorString, "Error:Statement prepare failed");
127 return rpkt;
129 int param = sqlstmt->noOfParamFields();
130 int proj = sqlstmt->noOfProjFields();
131 BindSqlField *bindField = NULL;
132 BindSqlProjectField *projField = NULL;
133 //populate paramList
134 FieldInfo * fInfo = new FieldInfo();
135 for (int i = 0; i < param; i++) {
136 bindField = new BindSqlField();
137 sqlstmt->getParamFldInfo(i + 1, fInfo);
138 strcpy(bindField->fName, fInfo->fldName);
139 bindField->type = fInfo->type;
140 bindField->length = fInfo->length;
141 bindField->offset = fInfo->offset;
142 strcpy(bindField->defaultValueBuf, fInfo->defaultValueBuf);
143 bindField->isNull = fInfo->isNull;
144 bindField->isPrimary = fInfo->isPrimary;
145 bindField->isDefault = fInfo->isDefault;
146 bindField->isUnique = fInfo->isUnique;
147 bindField->value = AllDataType::alloc(bindField->type, bindField->length);
148 nwStmt->paramList.append(bindField);
150 delete fInfo;
151 FieldInfo *fldInfo = new FieldInfo();
152 for (int i = 0; i < proj; i++) {
153 projField = new BindSqlProjectField();
154 sqlstmt->getProjFldInfo(i + 1, fldInfo);
155 strcpy(projField->fName, fldInfo->fldName);
156 projField->type = fldInfo->type;
157 projField->length = fldInfo->length;
158 projField->offset = fldInfo->offset;
159 strcpy(projField->defaultValueBuf, fldInfo->defaultValueBuf);
160 projField->isNull = fldInfo->isNull;
161 projField->isPrimary = fldInfo->isPrimary;
162 projField->isDefault = fldInfo->isDefault;
163 projField->isUnique = fldInfo->isUnique;
164 projField->value = AllDataType::alloc(projField->type, projField->length);
165 nwStmt->projList.append(projField);
167 delete fldInfo;
168 stmtList.append(nwStmt);
169 *retval = 1;
170 if(sqlstmt->isSelect()) rpkt->isSelect = true;
171 if (param) *(retval+2) = 1;
172 if (proj) *(retval+3) = 1;
173 rpkt->stmtID = nwStmt->stmtID;
174 strcpy(rpkt->errorString, "Success");
175 return rpkt;
178 void * SqlNetworkHandler::processSqlExecute(PacketHeader &header, char *buffer)
180 ResponsePacket *rpkt = new ResponsePacket();
181 char *retval = (char *) &rpkt->retVal;
182 SqlPacketExecute *pkt = new SqlPacketExecute();
183 pkt->setBuffer(buffer);
184 pkt->setBufferSize(header.packetLength);
185 pkt->setStatementList(stmtList);
186 pkt->unmarshall();
187 printDebug(DM_Network, "PREPARE %d\n", pkt->stmtID);
188 rpkt->stmtID = pkt->stmtID;
189 ListIterator stmtIter = stmtList.getIterator();
190 NetworkStmt *stmt;
191 while (stmtIter.hasElement())
193 stmt = (NetworkStmt*) stmtIter.nextElement();
194 //TODO::Also check the srcNetworkID
195 if (stmt->stmtID == pkt->stmtID ) break;
197 AbsSqlStatement *sqlstmt = stmt->stmt;
198 int rows = 0;
199 for (int i=0; i < pkt->noParams; i++) {
200 BindSqlField *bindField = (BindSqlField *) stmt->paramList.get(i+1);
201 setParamValues(sqlstmt, i+1, bindField->type, bindField->length, (char *)bindField->value);
203 //SqlStatement *st = (SqlStatement *)sqlstmt;
204 if(sqlstmt->isSelect()) {
205 int noProj = stmt->projList.size();
206 for (int i=0; i < noProj; i++) {
207 BindSqlProjectField *prjFld = (BindSqlProjectField *) stmt->projList.get(i+1);
208 sqlstmt->bindField(i+1, prjFld->value);
211 DbRetVal rv = sqlstmt->execute(rows);
212 if (rv != OK) {
213 *retval = 0;
214 strcpy(rpkt->errorString, "Execute failed");
215 return rpkt;
217 *retval = 1;
218 rpkt->rows = rows;
219 strcpy(rpkt->errorString, "Success");
220 return rpkt;
223 void * SqlNetworkHandler::processSqlFetch(PacketHeader &header, char *buffer)
225 ResponsePacket *rpkt = new ResponsePacket();
226 char *retval = (char *) &rpkt->retVal;
227 SqlPacketFetch *pkt = new SqlPacketFetch();
228 pkt->setBuffer(buffer);
229 pkt->unmarshall();
230 rpkt->stmtID = pkt->stmtID;
231 ListIterator stmtIter = stmtList.getIterator();
232 NetworkStmt *stmt;
233 while (stmtIter.hasElement())
235 stmt = (NetworkStmt*) stmtIter.nextElement();
236 //TODO::Also check teh srcNetworkID
237 if (stmt->stmtID == pkt->stmtID ) break;
239 AbsSqlStatement *sqlstmt = stmt->stmt;
240 void *data=NULL;
241 DbRetVal rv = OK;
242 if ((data = sqlstmt->fetch(rv)) != NULL && rv == OK) {
243 *retval = 1;
244 strcpy(rpkt->errorString, "Success");
245 return rpkt;
247 if (data == NULL && rv == OK) {
248 sqlstmt->close();
249 *retval = 1;
250 *(retval + 1) = 1;
251 strcpy(rpkt->errorString, "Success fetch completed");
252 return rpkt;
254 else {
255 *retval = 0;
256 strcpy(rpkt->errorString, "fetch completed");
257 return rpkt;
261 void * SqlNetworkHandler::processSqlFree(PacketHeader &header, char *buffer)
263 ResponsePacket *rpkt = new ResponsePacket();
264 char *retval = (char *) &rpkt->retVal;
265 SqlPacketFree *pkt = new SqlPacketFree();
266 pkt->setBuffer(buffer);
267 pkt->unmarshall();
268 rpkt->stmtID = pkt->stmtID;
269 ListIterator stmtIter = stmtList.getIterator();
270 NetworkStmt *stmt;
271 while (stmtIter.hasElement())
273 stmt = (NetworkStmt*) stmtIter.nextElement();
274 //TODO::Also check teh srcNetworkID
275 if (stmt->stmtID == pkt->stmtID ) break;
277 AbsSqlStatement *sqlstmt = stmt->stmt;
278 sqlstmt->free();
279 ListIterator itprm = stmt->paramList.getIterator();
280 BindSqlField *fld = NULL;
281 while((fld = (BindSqlField *) itprm.nextElement()) != NULL) delete fld;
282 stmt->paramList.reset();
283 ListIterator itprj = stmt->projList.getIterator();
284 BindSqlProjectField *pfld = NULL;
285 while((pfld = (BindSqlProjectField *) itprj.nextElement()) != NULL) delete pfld;
286 stmt->projList.reset();
287 delete stmt->stmt;
288 stmtList.remove(stmt);
289 delete stmt;
290 *retval = 1;
291 strcpy(rpkt->errorString, "Success");
292 return rpkt;
296 void * SqlNetworkHandler::processSqlCommit(PacketHeader &header, char *buffer)
298 ResponsePacket *rpkt = new ResponsePacket();
299 char *retval = (char *) &rpkt->retVal;
300 DbRetVal rv = conn->commit();
301 if (rv != OK) {
302 *retval = 0;
303 strcpy(rpkt->errorString, "Commit failure\n");
304 return rpkt;
306 rv = conn->beginTrans();
307 *retval = 1;
308 strcpy(rpkt->errorString, "Success");
309 return rpkt;
312 void *SqlNetworkHandler::processSqlRollback(PacketHeader &header, char *buffer)
314 ResponsePacket *rpkt = new ResponsePacket();
315 char *retval = (char *) &rpkt->retVal;
317 DbRetVal rv = conn->rollback();
318 if (rv != OK) {
319 *retval = 0;
320 strcpy(rpkt->errorString, "Rollback failure\n");
321 return rpkt;
323 rv = conn->beginTrans();
324 *retval = 1;
325 strcpy(rpkt->errorString, "Success");
326 return rpkt;
329 void *SqlNetworkHandler::processCommit(PacketHeader &header, char *buffer)
331 printDebug(DM_Network, "Processing COMMIT");
332 PacketCommit *pkt = new PacketCommit();
333 pkt->setBuffer(buffer);
334 pkt->setBufferSize(header.packetLength);
335 pkt->unmarshall();
336 List pktList;
337 pkt->getExecPacketList(stmtList, pktList);
338 DbRetVal rv = applyExecPackets(stmtList, pktList);
339 int response = 1;
340 if (rv != OK)
342 printError(ErrSysFatal, "Unable to apply the exec packets\n");
343 response =0;
345 return response;
348 void * SqlNetworkHandler::processFree(PacketHeader &header, char *buffer)
350 PacketFree *pkt = new PacketFree();
351 pkt->setBuffer(buffer);
352 pkt->setBufferSize(header.packetLength);
353 pkt->unmarshall();
354 //printf("FREE %d \n", pkt->stmtID);
355 int response =1;
356 //This wont work for two statement executed in same transaction using same SqlStatement object using free.
357 //so do not delete now and put a flag 'readyfordelete' in NetworkStmt object and delete it during execute
359 ListIterator iter = stmtList.getIterator();
360 NetworkStmt *stmt, *removeStmt = NULL;
361 while (iter.hasElement())
363 stmt = (NetworkStmt*)iter.nextElement();
364 if (stmt->srcNetworkID == header.srcNetworkID
365 && stmt->stmtID == pkt->stmtID)
367 removeStmt = stmt;
368 break;
371 if (removeStmt) stmtList.remove(removeStmt);
372 else printf("Statement id %d not found in list \n", pkt->stmtID);
374 return response;
376 void * SqlNetworkHandler::processPrepare(PacketHeader &header, char *buffer)
378 PacketPrepare *pkt = new PacketPrepare();
379 pkt->setBuffer(buffer);
380 pkt->setBufferSize(header.packetLength);
381 pkt->unmarshall();
382 printDebug(DM_Network, "PREPARE %d %s\n", pkt->stmtID, pkt->stmtString);
383 //for (int i =0 ; i < pkt->noParams; i++)
384 //printf("PREPARE type %d length %d \n", pkt->type[i], pkt->length[i]);
385 int response =1;
386 //TODO::add it to the SqlStatement list
387 AbsSqlStatement *sqlstmt = SqlFactory::createStatement(type);
388 sqlstmt->setConnection(conn);
389 NetworkStmt *nwStmt = new NetworkStmt();
390 printDebug(DM_Network, "Statement string %s\n", pkt->stmtString);
391 nwStmt->srcNetworkID = header.srcNetworkID;
392 nwStmt->stmtID = pkt->stmtID;
393 nwStmt->stmt = sqlstmt;
394 DbRetVal rv = sqlstmt->prepare(pkt->stmtString);
395 if (rv != OK)
397 printError(ErrSysInit, "statement prepare failed\n");
398 response = 0;
399 return response;
401 BindSqlField *bindField = NULL;
402 //populate paramList
403 for (int i = 0; i < pkt->noParams; i++)
405 bindField = new BindSqlField();
406 bindField->type = (DataType) pkt->type[i];
407 bindField->length = pkt->length[i];
408 bindField->value = AllDataType::alloc(bindField->type,
409 bindField->length);
410 nwStmt->paramList.append(bindField);
412 stmtList.append(nwStmt);
413 return response;
417 DbRetVal SqlNetworkHandler::applyExecPackets(List sList, List pList)
419 ListIterator stmtIter = sList.getIterator();
420 NetworkStmt *nwstmt;
421 DbRetVal rv = conn->beginTrans();
422 if (rv != OK) return rv;
423 ListIterator pktIter = pList.getIterator();
424 PacketExecute *pkt;
425 int i = 0;
426 BindSqlField *bindField;
427 while (pktIter.hasElement())
429 pkt = (PacketExecute*) pktIter.nextElement();
430 stmtIter.reset();
431 bool found = false;
432 while (stmtIter.hasElement())
434 nwstmt = (NetworkStmt*) stmtIter.nextElement();
435 if (nwstmt->stmtID == pkt->stmtID) {found = true ; break;}
437 if (!found) {
438 printf("stmt not found in list. Negleting unreplicated table...\n");
439 continue;
441 ListIterator paramIter = nwstmt->paramList.getIterator();
442 i = 0;
443 while (paramIter.hasElement()) {
444 bindField = (BindSqlField*) paramIter.nextElement();
445 setParamValues(nwstmt->stmt, i+1, bindField->type, bindField->length, pkt->paramValues[i]);
446 i++;
448 int rows= 0;
449 DbRetVal rv = nwstmt->stmt->execute(rows);
450 if (rv != OK )
452 printError(ErrSysFatal, "sql execute failed with rv %d\n", rv);
453 //TODO::log all things like SQL statements to a file
454 SqlNetworkHandler::conn->rollback();
455 printError(ErrPeerExecFailed, "Transaction Rolledback\n");
456 return ErrPeerExecFailed;
459 SqlNetworkHandler::conn->commit();
460 return OK;
463 void SqlNetworkHandler::setParamValues(AbsSqlStatement *stmt, int parampos, DataType type,
464 int length, char *value)
466 switch(type)
468 case typeInt:
469 stmt->setIntParam(parampos, *(int*)value);
470 break;
471 case typeLong:
472 stmt->setLongParam(parampos, *(long*)value);
473 break;
474 case typeLongLong:
475 stmt->setLongLongParam(parampos, *(long long*)value);
476 break;
477 case typeShort:
478 stmt->setShortParam(parampos, *(short*)value);
479 break;
480 case typeByteInt:
481 stmt->setByteIntParam(parampos, *(char*)value);
482 break;
483 case typeDouble:
484 stmt->setDoubleParam(parampos, *(double*)value);
485 break;
486 case typeFloat:
487 stmt->setFloatParam(parampos, *(float*)value);
488 break;
489 case typeDate:
490 stmt->setDateParam(parampos, *(Date*)value);
491 break;
492 case typeTime:
493 stmt->setTimeParam(parampos, *(Time*)value);
494 break;
495 case typeTimeStamp:
496 stmt->setTimeStampParam(parampos, *(TimeStamp*)value);
497 break;
498 case typeString:
500 char *d =(char*)value;
501 d[length-1] = '\0';
502 stmt->setStringParam(parampos, (char*)value);
503 break;
505 case typeBinary:
506 stmt->setBinaryParam(parampos, (char *) value);
507 break;
509 return;
512 AbsSqlConnection * SqlNetworkHandler::createConnection(SqlApiImplType type)
514 AbsSqlConnection *con = NULL;
515 switch(type) {
516 case CSqlNetwork:
517 con = SqlFactory::createConnection(CSql);
518 break;
519 case CSqlNetworkAdapter:
520 con = SqlFactory::createConnection(CSqlAdapter);
521 break;
522 case CSqlNetworkGateway:
523 con = SqlFactory::createConnection(CSqlGateway);
524 break;
525 default:
526 return NULL;
530 AbsSqlStatement * SqlNetworkHandler::createStatement(SqlApiImplType type)
532 AbsSqlStatement *stmt = NULL;
533 switch(type) {
534 case CSqlNetwork:
535 stmt = SqlFactory::createStatement(CSql);
536 break;
537 case CSqlNetworkAdapter:
538 stmt = SqlFactory::createStatement(CSqlAdapter);
539 break;
540 case CSqlNetworkGateway:
541 stmt = SqlFactory::createStatement(CSqlGateway);
542 break;
543 default:
544 return NULL;