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
);
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
);
88 type
= (SqlApiImplType
) pkt
->sqlApiImplType
;
89 conn
= createConnection(type
);
90 char *ptr
= (char *) &rpkt
->retVal
;
91 DbRetVal rv
=conn
->connect(pkt
->userName
, pkt
->passWord
);
94 strcpy(rpkt
->errorString
, "User Authentication Failure");
96 printf("connection failure\n");
100 rv
= conn
->beginTrans();
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
);
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
);
124 printError(ErrSysInit
, "statement prepare failed\n");
126 strcpy(rpkt
->errorString
, "Error:Statement prepare failed");
129 int param
= sqlstmt
->noOfParamFields();
130 int proj
= sqlstmt
->noOfProjFields();
131 BindSqlField
*bindField
= NULL
;
132 BindSqlProjectField
*projField
= NULL
;
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
);
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
);
168 stmtList
.append(nwStmt
);
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");
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
);
187 printDebug(DM_Network
, "PREPARE %d\n", pkt
->stmtID
);
188 rpkt
->stmtID
= pkt
->stmtID
;
189 ListIterator stmtIter
= stmtList
.getIterator();
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
;
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
);
214 strcpy(rpkt
->errorString
, "Execute failed");
219 strcpy(rpkt
->errorString
, "Success");
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
);
230 rpkt
->stmtID
= pkt
->stmtID
;
231 ListIterator stmtIter
= stmtList
.getIterator();
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
;
242 if ((data
= sqlstmt
->fetch(rv
)) != NULL
&& rv
== OK
) {
244 strcpy(rpkt
->errorString
, "Success");
247 if (data
== NULL
&& rv
== OK
) {
251 strcpy(rpkt
->errorString
, "Success fetch completed");
256 strcpy(rpkt
->errorString
, "fetch completed");
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
);
268 rpkt
->stmtID
= pkt
->stmtID
;
269 ListIterator stmtIter
= stmtList
.getIterator();
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
;
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();
288 stmtList
.remove(stmt
);
291 strcpy(rpkt
->errorString
, "Success");
296 void * SqlNetworkHandler::processSqlCommit(PacketHeader
&header
, char *buffer
)
298 ResponsePacket
*rpkt
= new ResponsePacket();
299 char *retval
= (char *) &rpkt
->retVal
;
300 DbRetVal rv
= conn
->commit();
303 strcpy(rpkt
->errorString
, "Commit failure\n");
306 rv
= conn
->beginTrans();
308 strcpy(rpkt
->errorString
, "Success");
312 void *SqlNetworkHandler::processSqlRollback(PacketHeader
&header
, char *buffer
)
314 ResponsePacket
*rpkt
= new ResponsePacket();
315 char *retval
= (char *) &rpkt
->retVal
;
317 DbRetVal rv
= conn
->rollback();
320 strcpy(rpkt
->errorString
, "Rollback failure\n");
323 rv
= conn
->beginTrans();
325 strcpy(rpkt
->errorString
, "Success");
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);
337 pkt->getExecPacketList(stmtList, pktList);
338 DbRetVal rv = applyExecPackets(stmtList, pktList);
342 printError(ErrSysFatal, "Unable to apply the exec packets\n");
348 void * SqlNetworkHandler::processFree(PacketHeader &header, char *buffer)
350 PacketFree *pkt = new PacketFree();
351 pkt->setBuffer(buffer);
352 pkt->setBufferSize(header.packetLength);
354 //printf("FREE %d \n", pkt->stmtID);
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)
371 if (removeStmt) stmtList.remove(removeStmt);
372 else printf("Statement id %d not found in list \n", pkt->stmtID);
376 void * SqlNetworkHandler::processPrepare(PacketHeader &header, char *buffer)
378 PacketPrepare *pkt = new PacketPrepare();
379 pkt->setBuffer(buffer);
380 pkt->setBufferSize(header.packetLength);
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]);
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);
397 printError(ErrSysInit, "statement prepare failed\n");
401 BindSqlField *bindField = NULL;
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,
410 nwStmt->paramList.append(bindField);
412 stmtList.append(nwStmt);
417 DbRetVal SqlNetworkHandler::applyExecPackets(List sList, List pList)
419 ListIterator stmtIter = sList.getIterator();
421 DbRetVal rv = conn->beginTrans();
422 if (rv != OK) return rv;
423 ListIterator pktIter = pList.getIterator();
426 BindSqlField *bindField;
427 while (pktIter.hasElement())
429 pkt = (PacketExecute*) pktIter.nextElement();
432 while (stmtIter.hasElement())
434 nwstmt = (NetworkStmt*) stmtIter.nextElement();
435 if (nwstmt->stmtID == pkt->stmtID) {found = true ; break;}
438 printf("stmt not found in list. Negleting unreplicated table...\n");
441 ListIterator paramIter = nwstmt->paramList.getIterator();
443 while (paramIter.hasElement()) {
444 bindField = (BindSqlField*) paramIter.nextElement();
445 setParamValues(nwstmt->stmt, i+1, bindField->type, bindField->length, pkt->paramValues[i]);
449 DbRetVal rv = nwstmt->stmt->execute(rows);
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();
463 void SqlNetworkHandler::setParamValues(AbsSqlStatement
*stmt
, int parampos
, DataType type
,
464 int length
, char *value
)
469 stmt
->setIntParam(parampos
, *(int*)value
);
472 stmt
->setLongParam(parampos
, *(long*)value
);
475 stmt
->setLongLongParam(parampos
, *(long long*)value
);
478 stmt
->setShortParam(parampos
, *(short*)value
);
481 stmt
->setByteIntParam(parampos
, *(char*)value
);
484 stmt
->setDoubleParam(parampos
, *(double*)value
);
487 stmt
->setFloatParam(parampos
, *(float*)value
);
490 stmt
->setDateParam(parampos
, *(Date
*)value
);
493 stmt
->setTimeParam(parampos
, *(Time
*)value
);
496 stmt
->setTimeStampParam(parampos
, *(TimeStamp
*)value
);
500 char *d
=(char*)value
;
502 stmt
->setStringParam(parampos
, (char*)value
);
506 stmt
->setBinaryParam(parampos
, (char *) value
);
512 AbsSqlConnection
* SqlNetworkHandler::createConnection(SqlApiImplType type
)
514 AbsSqlConnection
*con
= NULL
;
517 con
= SqlFactory::createConnection(CSql
);
519 case CSqlNetworkAdapter
:
520 con
= SqlFactory::createConnection(CSqlAdapter
);
522 case CSqlNetworkGateway
:
523 con
= SqlFactory::createConnection(CSqlGateway
);
530 AbsSqlStatement
* SqlNetworkHandler::createStatement(SqlApiImplType type
)
532 AbsSqlStatement
*stmt
= NULL
;
535 stmt
= SqlFactory::createStatement(CSql
);
537 case CSqlNetworkAdapter
:
538 stmt
= SqlFactory::createStatement(CSqlAdapter
);
540 case CSqlNetworkGateway
:
541 stmt
= SqlFactory::createStatement(CSqlGateway
);