1 /***************************************************************************
2 * Copyright (C) 2007 by Prabakaran Thirumalai *
3 * praba_tuty@yahoo.com *
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. *
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. *
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>
30 List
SqlNetworkHandler::stmtList
;
31 AbsSqlConnection
* SqlNetworkHandler::conn
;
32 SqlApiImplType
SqlNetworkHandler::type
;
33 int SqlNetworkHandler::stmtID
;
35 void *SqlNetworkHandler::process(PacketHeader
&header
, char *buffer
)
39 ResponsePacket
*rpkt
= NULL
;
40 switch(header
.packetType
)
42 // case NW_PKT_PREPARE:
43 //return processPrepare(header, buffer);
46 //return processCommit(header, buffer);
48 case SQL_NW_PKT_CONNECT
:
49 return processSqlConnect(header
, buffer
);
51 case SQL_NW_PKT_PREPARE
:
52 return processSqlPrepare(header
, buffer
);
54 case SQL_NW_PKT_EXECUTE
:
55 return processSqlExecute(header
, buffer
);
57 case SQL_NW_PKT_FETCH
:
58 return processSqlFetch(header
, buffer
);
60 case SQL_NW_PKT_COMMIT
:
61 return processSqlCommit(header
, buffer
);
63 case SQL_NW_PKT_ROLLBACK
:
64 return processSqlRollback(header
, buffer
);
66 case SQL_NW_PKT_DISCONNECT
:
68 rv
= conn
->disconnect();
69 rpkt
= new ResponsePacket();
70 ptr
= (char *) &rpkt
->retVal
;
72 strcpy(rpkt
->errorString
, "Success");
75 return processSqlFree(header
, buffer
);
77 case SQL_NW_PKT_SHOWTABLES
:
78 return processSqlShowTables(header
, buffer
);
83 void * SqlNetworkHandler::processSqlConnect(PacketHeader
&header
, char *buffer
)
85 ResponsePacket
*rpkt
= new ResponsePacket();
86 printDebug(DM_Network
, "Processing CONNECT");
87 SqlPacketConnect
*pkt
= new SqlPacketConnect();
88 pkt
->setBuffer(buffer
);
89 pkt
->setBufferSize(header
.packetLength
);
91 type
= (SqlApiImplType
) pkt
->sqlApiImplType
;
92 conn
= createConnection(type
);
93 char *ptr
= (char *) &rpkt
->retVal
;
94 DbRetVal rv
=conn
->connect(pkt
->userName
, pkt
->passWord
);
97 strcpy(rpkt
->errorString
, "User Authentication Failure");
99 printf("connection failure\n");
103 rv
= conn
->beginTrans();
108 void* SqlNetworkHandler::processSqlPrepare(PacketHeader
&header
, char *buffer
)
110 ResponsePacket
*rpkt
= new ResponsePacket();
111 rpkt
->isSelect
= false;
112 char *retval
= (char *) &rpkt
->retVal
;
113 SqlPacketPrepare
*pkt
= new SqlPacketPrepare();
114 pkt
->setBuffer(buffer
);
115 pkt
->setBufferSize(header
.packetLength
);
117 printDebug(DM_Network
, "PREPARE %s\n", pkt
->stmtString
);
118 AbsSqlStatement
*sqlstmt
= createStatement(type
);
119 sqlstmt
->setConnection(conn
);
120 NetworkStmt
*nwStmt
= new NetworkStmt();
121 nwStmt
->stmtID
= ++stmtID
;
122 printDebug(DM_Network
, "Statement string %s\n", pkt
->stmtString
);
123 nwStmt
->stmt
= sqlstmt
;
124 DbRetVal rv
= sqlstmt
->prepare(pkt
->stmtString
);
127 printError(ErrSysInit
, "statement prepare failed\n");
129 strcpy(rpkt
->errorString
, "Error:Statement prepare failed");
132 int param
= sqlstmt
->noOfParamFields();
133 int proj
= sqlstmt
->noOfProjFields();
134 BindSqlField
*bindField
= NULL
;
135 BindSqlProjectField
*projField
= NULL
;
137 FieldInfo
* fInfo
= new FieldInfo();
138 for (int i
= 0; i
< param
; i
++) {
139 bindField
= new BindSqlField();
140 sqlstmt
->getParamFldInfo(i
+ 1, fInfo
);
141 strcpy(bindField
->fName
, fInfo
->fldName
);
142 bindField
->type
= fInfo
->type
;
143 bindField
->length
= fInfo
->length
;
144 bindField
->offset
= fInfo
->offset
;
145 strcpy(bindField
->defaultValueBuf
, fInfo
->defaultValueBuf
);
146 bindField
->isNull
= fInfo
->isNull
;
147 bindField
->isPrimary
= fInfo
->isPrimary
;
148 bindField
->isDefault
= fInfo
->isDefault
;
149 bindField
->isUnique
= fInfo
->isUnique
;
150 bindField
->value
= AllDataType::alloc(bindField
->type
, bindField
->length
);
151 nwStmt
->paramList
.append(bindField
);
154 FieldInfo
*fldInfo
= new FieldInfo();
155 for (int i
= 0; i
< proj
; i
++) {
156 projField
= new BindSqlProjectField();
157 sqlstmt
->getProjFldInfo(i
+ 1, fldInfo
);
158 strcpy(projField
->fName
, fldInfo
->fldName
);
159 projField
->type
= fldInfo
->type
;
160 projField
->length
= fldInfo
->length
;
161 projField
->offset
= fldInfo
->offset
;
162 strcpy(projField
->defaultValueBuf
, fldInfo
->defaultValueBuf
);
163 projField
->isNull
= fldInfo
->isNull
;
164 projField
->isPrimary
= fldInfo
->isPrimary
;
165 projField
->isDefault
= fldInfo
->isDefault
;
166 projField
->isUnique
= fldInfo
->isUnique
;
167 projField
->value
= AllDataType::alloc(projField
->type
, projField
->length
);
168 nwStmt
->projList
.append(projField
);
171 stmtList
.append(nwStmt
);
173 if(sqlstmt
->isSelect()) rpkt
->isSelect
= true;
174 if (param
) *(retval
+2) = 1;
175 if (proj
) *(retval
+3) = 1;
176 rpkt
->stmtID
= nwStmt
->stmtID
;
177 strcpy(rpkt
->errorString
, "Success");
181 void * SqlNetworkHandler::processSqlExecute(PacketHeader
&header
, char *buffer
)
183 ResponsePacket
*rpkt
= new ResponsePacket();
184 char *retval
= (char *) &rpkt
->retVal
;
185 SqlPacketExecute
*pkt
= new SqlPacketExecute();
186 pkt
->setBuffer(buffer
);
187 pkt
->setBufferSize(header
.packetLength
);
188 pkt
->setStatementList(stmtList
);
190 printDebug(DM_Network
, "PREPARE %d\n", pkt
->stmtID
);
191 rpkt
->stmtID
= pkt
->stmtID
;
192 ListIterator stmtIter
= stmtList
.getIterator();
194 while (stmtIter
.hasElement())
196 stmt
= (NetworkStmt
*) stmtIter
.nextElement();
197 //TODO::Also check the srcNetworkID
198 if (stmt
->stmtID
== pkt
->stmtID
) break;
200 AbsSqlStatement
*sqlstmt
= stmt
->stmt
;
202 for (int i
=0; i
< pkt
->noParams
; i
++) {
203 BindSqlField
*bindField
= (BindSqlField
*) stmt
->paramList
.get(i
+1);
204 setParamValues(sqlstmt
, i
+1, bindField
->type
, bindField
->length
, (char *)bindField
->value
);
206 //SqlStatement *st = (SqlStatement *)sqlstmt;
207 if(sqlstmt
->isSelect()) {
208 int noProj
= stmt
->projList
.size();
209 for (int i
=0; i
< noProj
; i
++) {
210 BindSqlProjectField
*prjFld
= (BindSqlProjectField
*) stmt
->projList
.get(i
+1);
211 sqlstmt
->bindField(i
+1, prjFld
->value
);
214 DbRetVal rv
= sqlstmt
->execute(rows
);
217 strcpy(rpkt
->errorString
, "Execute failed");
222 strcpy(rpkt
->errorString
, "Success");
226 void * SqlNetworkHandler::processSqlFetch(PacketHeader
&header
, char *buffer
)
228 ResponsePacket
*rpkt
= new ResponsePacket();
229 char *retval
= (char *) &rpkt
->retVal
;
230 SqlPacketFetch
*pkt
= new SqlPacketFetch();
231 pkt
->setBuffer(buffer
);
233 rpkt
->stmtID
= pkt
->stmtID
;
234 ListIterator stmtIter
= stmtList
.getIterator();
236 while (stmtIter
.hasElement())
238 stmt
= (NetworkStmt
*) stmtIter
.nextElement();
239 //TODO::Also check teh srcNetworkID
240 if (stmt
->stmtID
== pkt
->stmtID
) break;
242 AbsSqlStatement
*sqlstmt
= stmt
->stmt
;
245 if ((data
= sqlstmt
->fetch(rv
)) != NULL
&& rv
== OK
) {
247 strcpy(rpkt
->errorString
, "Success");
250 if (data
== NULL
&& rv
== OK
) {
254 strcpy(rpkt
->errorString
, "Success fetch completed");
259 strcpy(rpkt
->errorString
, "fetch completed");
264 void * SqlNetworkHandler::processSqlFree(PacketHeader
&header
, char *buffer
)
266 ResponsePacket
*rpkt
= new ResponsePacket();
267 char *retval
= (char *) &rpkt
->retVal
;
268 SqlPacketFree
*pkt
= new SqlPacketFree();
269 pkt
->setBuffer(buffer
);
271 rpkt
->stmtID
= pkt
->stmtID
;
272 ListIterator stmtIter
= stmtList
.getIterator();
274 while (stmtIter
.hasElement())
276 stmt
= (NetworkStmt
*) stmtIter
.nextElement();
277 //TODO::Also check teh srcNetworkID
278 if (stmt
->stmtID
== pkt
->stmtID
) break;
280 AbsSqlStatement
*sqlstmt
= stmt
->stmt
;
282 ListIterator itprm
= stmt
->paramList
.getIterator();
283 BindSqlField
*fld
= NULL
;
284 while((fld
= (BindSqlField
*) itprm
.nextElement()) != NULL
) delete fld
;
285 stmt
->paramList
.reset();
286 ListIterator itprj
= stmt
->projList
.getIterator();
287 BindSqlProjectField
*pfld
= NULL
;
288 while((pfld
= (BindSqlProjectField
*) itprj
.nextElement()) != NULL
) delete pfld
;
289 stmt
->projList
.reset();
291 stmtList
.remove(stmt
);
294 strcpy(rpkt
->errorString
, "Success");
299 void * SqlNetworkHandler::processSqlCommit(PacketHeader
&header
, char *buffer
)
301 ResponsePacket
*rpkt
= new ResponsePacket();
302 char *retval
= (char *) &rpkt
->retVal
;
303 DbRetVal rv
= conn
->commit();
306 strcpy(rpkt
->errorString
, "Commit failure\n");
309 rv
= conn
->beginTrans();
311 strcpy(rpkt
->errorString
, "Success");
315 void *SqlNetworkHandler::processSqlRollback(PacketHeader
&header
, char *buffer
)
317 ResponsePacket
*rpkt
= new ResponsePacket();
318 char *retval
= (char *) &rpkt
->retVal
;
320 DbRetVal rv
= conn
->rollback();
323 strcpy(rpkt
->errorString
, "Rollback failure\n");
326 rv
= conn
->beginTrans();
328 strcpy(rpkt
->errorString
, "Success");
332 void *SqlNetworkHandler::processCommit(PacketHeader &header, char *buffer)
334 printDebug(DM_Network, "Processing COMMIT");
335 PacketCommit *pkt = new PacketCommit();
336 pkt->setBuffer(buffer);
337 pkt->setBufferSize(header.packetLength);
340 pkt->getExecPacketList(stmtList, pktList);
341 DbRetVal rv = applyExecPackets(stmtList, pktList);
345 printError(ErrSysFatal, "Unable to apply the exec packets\n");
351 void * SqlNetworkHandler::processFree(PacketHeader &header, char *buffer)
353 PacketFree *pkt = new PacketFree();
354 pkt->setBuffer(buffer);
355 pkt->setBufferSize(header.packetLength);
357 //printf("FREE %d \n", pkt->stmtID);
359 //This wont work for two statement executed in same transaction using same SqlStatement object using free.
360 //so do not delete now and put a flag 'readyfordelete' in NetworkStmt object and delete it during execute
362 ListIterator iter = stmtList.getIterator();
363 NetworkStmt *stmt, *removeStmt = NULL;
364 while (iter.hasElement())
366 stmt = (NetworkStmt*)iter.nextElement();
367 if (stmt->srcNetworkID == header.srcNetworkID
368 && stmt->stmtID == pkt->stmtID)
374 if (removeStmt) stmtList.remove(removeStmt);
375 else printf("Statement id %d not found in list \n", pkt->stmtID);
379 void * SqlNetworkHandler::processPrepare(PacketHeader &header, char *buffer)
381 PacketPrepare *pkt = new PacketPrepare();
382 pkt->setBuffer(buffer);
383 pkt->setBufferSize(header.packetLength);
385 printDebug(DM_Network, "PREPARE %d %s\n", pkt->stmtID, pkt->stmtString);
386 //for (int i =0 ; i < pkt->noParams; i++)
387 //printf("PREPARE type %d length %d \n", pkt->type[i], pkt->length[i]);
389 //TODO::add it to the SqlStatement list
390 AbsSqlStatement *sqlstmt = SqlFactory::createStatement(type);
391 sqlstmt->setConnection(conn);
392 NetworkStmt *nwStmt = new NetworkStmt();
393 printDebug(DM_Network, "Statement string %s\n", pkt->stmtString);
394 nwStmt->srcNetworkID = header.srcNetworkID;
395 nwStmt->stmtID = pkt->stmtID;
396 nwStmt->stmt = sqlstmt;
397 DbRetVal rv = sqlstmt->prepare(pkt->stmtString);
400 printError(ErrSysInit, "statement prepare failed\n");
404 BindSqlField *bindField = NULL;
406 for (int i = 0; i < pkt->noParams; i++)
408 bindField = new BindSqlField();
409 bindField->type = (DataType) pkt->type[i];
410 bindField->length = pkt->length[i];
411 bindField->value = AllDataType::alloc(bindField->type,
413 nwStmt->paramList.append(bindField);
415 stmtList.append(nwStmt);
420 DbRetVal SqlNetworkHandler::applyExecPackets(List sList, List pList)
422 ListIterator stmtIter = sList.getIterator();
424 DbRetVal rv = conn->beginTrans();
425 if (rv != OK) return rv;
426 ListIterator pktIter = pList.getIterator();
429 BindSqlField *bindField;
430 while (pktIter.hasElement())
432 pkt = (PacketExecute*) pktIter.nextElement();
435 while (stmtIter.hasElement())
437 nwstmt = (NetworkStmt*) stmtIter.nextElement();
438 if (nwstmt->stmtID == pkt->stmtID) {found = true ; break;}
441 printf("stmt not found in list. Negleting unreplicated table...\n");
444 ListIterator paramIter = nwstmt->paramList.getIterator();
446 while (paramIter.hasElement()) {
447 bindField = (BindSqlField*) paramIter.nextElement();
448 setParamValues(nwstmt->stmt, i+1, bindField->type, bindField->length, pkt->paramValues[i]);
452 DbRetVal rv = nwstmt->stmt->execute(rows);
455 printError(ErrSysFatal, "sql execute failed with rv %d\n", rv);
456 //TODO::log all things like SQL statements to a file
457 SqlNetworkHandler::conn->rollback();
458 printError(ErrPeerExecFailed, "Transaction Rolledback\n");
459 return ErrPeerExecFailed;
462 SqlNetworkHandler::conn->commit();
466 void SqlNetworkHandler::setParamValues(AbsSqlStatement
*stmt
, int parampos
, DataType type
,
467 int length
, char *value
)
472 stmt
->setIntParam(parampos
, *(int*)value
);
475 stmt
->setLongParam(parampos
, *(long*)value
);
478 stmt
->setLongLongParam(parampos
, *(long long*)value
);
481 stmt
->setShortParam(parampos
, *(short*)value
);
484 stmt
->setByteIntParam(parampos
, *(char*)value
);
487 stmt
->setDoubleParam(parampos
, *(double*)value
);
490 stmt
->setFloatParam(parampos
, *(float*)value
);
493 stmt
->setDateParam(parampos
, *(Date
*)value
);
496 stmt
->setTimeParam(parampos
, *(Time
*)value
);
499 stmt
->setTimeStampParam(parampos
, *(TimeStamp
*)value
);
503 char *d
=(char*)value
;
505 stmt
->setStringParam(parampos
, (char*)value
);
509 stmt
->setBinaryParam(parampos
, (char *) value
);
515 AbsSqlConnection
* SqlNetworkHandler::createConnection(SqlApiImplType type
)
517 AbsSqlConnection
*con
= NULL
;
520 con
= SqlFactory::createConnection(CSql
);
522 case CSqlNetworkAdapter
:
523 con
= SqlFactory::createConnection(CSqlAdapter
);
525 case CSqlNetworkGateway
:
526 con
= SqlFactory::createConnection(CSqlGateway
);
534 AbsSqlStatement
* SqlNetworkHandler::createStatement(SqlApiImplType type
)
536 AbsSqlStatement
*stmt
= NULL
;
539 stmt
= SqlFactory::createStatement(CSql
);
541 case CSqlNetworkAdapter
:
542 stmt
= SqlFactory::createStatement(CSqlAdapter
);
544 case CSqlNetworkGateway
:
545 stmt
= SqlFactory::createStatement(CSqlGateway
);
553 void * SqlNetworkHandler::processSqlShowTables(PacketHeader
&header
, char *buffer
)
555 ResponsePacket
*rpkt
= new ResponsePacket();
556 rpkt
->isSelect
= false;
557 char *retval
= (char *) &rpkt
->retVal
;
558 AbsSqlStatement
*sqlstmt
= createStatement(type
);
559 sqlstmt
->setConnection(conn
);
560 NetworkStmt
*nwStmt
= new NetworkStmt();
561 nwStmt
->stmtID
= ++stmtID
;
562 nwStmt
->stmt
= sqlstmt
;
564 nwStmt
->tableNamesList
= sqlstmt
->getAllTableNames(rv
);
565 stmtList
.append(nwStmt
);
567 rpkt
->rows
= nwStmt
->tableNamesList
.size();
568 strcpy(rpkt
->errorString
, "Success");