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 char *ptr
= (char *) &rpkt
->retVal
;
89 DbRetVal rv
=conn
->connect(pkt
->userName
, pkt
->passWord
);
92 strcpy(rpkt
->errorString
, "User Authentication Failure");
94 printf("connection failure\n");
98 rv
= conn
->beginTrans();
103 void* SqlNetworkHandler::processSqlPrepare(PacketHeader
&header
, char *buffer
)
105 ResponsePacket
*rpkt
= new ResponsePacket();
106 rpkt
->isSelect
= false;
107 char *retval
= (char *) &rpkt
->retVal
;
108 SqlPacketPrepare
*pkt
= new SqlPacketPrepare();
109 pkt
->setBuffer(buffer
);
110 pkt
->setBufferSize(header
.packetLength
);
112 printDebug(DM_Network
, "PREPARE %s\n", pkt
->stmtString
);
113 AbsSqlStatement
*sqlstmt
= SqlFactory::createStatement(type
);
114 sqlstmt
->setConnection(conn
);
115 NetworkStmt
*nwStmt
= new NetworkStmt();
116 nwStmt
->stmtID
= ++stmtID
;
117 printDebug(DM_Network
, "Statement string %s\n", pkt
->stmtString
);
118 nwStmt
->stmt
= sqlstmt
;
119 DbRetVal rv
= sqlstmt
->prepare(pkt
->stmtString
);
122 printError(ErrSysInit
, "statement prepare failed\n");
124 strcpy(rpkt
->errorString
, "Error:Statement prepare failed");
127 int param
= sqlstmt
->noOfParamFields();
128 int proj
= sqlstmt
->noOfProjFields();
129 BindSqlField
*bindField
= NULL
;
130 BindSqlProjectField
*projField
= NULL
;
132 FieldInfo
* fInfo
= new FieldInfo();
133 for (int i
= 0; i
< param
; i
++) {
134 bindField
= new BindSqlField();
135 sqlstmt
->getParamFldInfo(i
+ 1, fInfo
);
136 strcpy(bindField
->fName
, fInfo
->fldName
);
137 bindField
->type
= fInfo
->type
;
138 bindField
->length
= fInfo
->length
;
139 bindField
->offset
= fInfo
->offset
;
140 strcpy(bindField
->defaultValueBuf
, fInfo
->defaultValueBuf
);
141 bindField
->isNull
= fInfo
->isNull
;
142 bindField
->isPrimary
= fInfo
->isPrimary
;
143 bindField
->isDefault
= fInfo
->isDefault
;
144 bindField
->isUnique
= fInfo
->isUnique
;
145 bindField
->value
= AllDataType::alloc(bindField
->type
, bindField
->length
);
146 nwStmt
->paramList
.append(bindField
);
149 FieldInfo
*fldInfo
= new FieldInfo();
150 for (int i
= 0; i
< proj
; i
++) {
151 projField
= new BindSqlProjectField();
152 sqlstmt
->getProjFldInfo(i
+ 1, fldInfo
);
153 strcpy(projField
->fName
, fInfo
->fldName
);
154 projField
->type
= fldInfo
->type
;
155 projField
->length
= fldInfo
->length
;
156 projField
->offset
= fldInfo
->offset
;
157 strcpy(projField
->defaultValueBuf
, fldInfo
->defaultValueBuf
);
158 projField
->isNull
= fldInfo
->isNull
;
159 projField
->isPrimary
= fldInfo
->isPrimary
;
160 projField
->isDefault
= fldInfo
->isDefault
;
161 projField
->isUnique
= fldInfo
->isUnique
;
162 projField
->value
= AllDataType::alloc(projField
->type
, projField
->length
);
163 nwStmt
->projList
.append(projField
);
166 stmtList
.append(nwStmt
);
168 if(sqlstmt
->isSelect()) rpkt
->isSelect
= true;
169 if (param
) *(retval
+2) = 1;
170 if (proj
) *(retval
+3) = 1;
171 rpkt
->stmtID
= nwStmt
->stmtID
;
172 strcpy(rpkt
->errorString
, "Success");
176 void * SqlNetworkHandler::processSqlExecute(PacketHeader
&header
, char *buffer
)
178 ResponsePacket
*rpkt
= new ResponsePacket();
179 char *retval
= (char *) &rpkt
->retVal
;
180 SqlPacketExecute
*pkt
= new SqlPacketExecute();
181 pkt
->setBuffer(buffer
);
182 pkt
->setBufferSize(header
.packetLength
);
183 pkt
->setStatementList(stmtList
);
185 printDebug(DM_Network
, "PREPARE %d\n", pkt
->stmtID
);
186 rpkt
->stmtID
= pkt
->stmtID
;
187 ListIterator stmtIter
= stmtList
.getIterator();
189 while (stmtIter
.hasElement())
191 stmt
= (NetworkStmt
*) stmtIter
.nextElement();
192 //TODO::Also check the srcNetworkID
193 if (stmt
->stmtID
== pkt
->stmtID
) break;
195 AbsSqlStatement
*sqlstmt
= stmt
->stmt
;
197 for (int i
=0; i
< pkt
->noParams
; i
++) {
198 BindSqlField
*bindField
= (BindSqlField
*) stmt
->paramList
.get(i
+1);
199 setParamValues(sqlstmt
, i
+1, bindField
->type
, bindField
->length
, (char *)bindField
->value
);
201 //SqlStatement *st = (SqlStatement *)sqlstmt;
202 if(sqlstmt
->isSelect()) {
203 int noProj
= stmt
->projList
.size();
204 for (int i
=0; i
< noProj
; i
++) {
205 BindSqlProjectField
*prjFld
= (BindSqlProjectField
*) stmt
->projList
.get(i
+1);
206 sqlstmt
->bindField(i
+1, prjFld
->value
);
209 DbRetVal rv
= sqlstmt
->execute(rows
);
212 strcpy(rpkt
->errorString
, "Execute failed");
217 strcpy(rpkt
->errorString
, "Success");
221 void * SqlNetworkHandler::processSqlFetch(PacketHeader
&header
, char *buffer
)
223 ResponsePacket
*rpkt
= new ResponsePacket();
224 char *retval
= (char *) &rpkt
->retVal
;
225 SqlPacketFetch
*pkt
= new SqlPacketFetch();
226 pkt
->setBuffer(buffer
);
228 rpkt
->stmtID
= pkt
->stmtID
;
229 ListIterator stmtIter
= stmtList
.getIterator();
231 while (stmtIter
.hasElement())
233 stmt
= (NetworkStmt
*) stmtIter
.nextElement();
234 //TODO::Also check teh srcNetworkID
235 if (stmt
->stmtID
== pkt
->stmtID
) break;
237 AbsSqlStatement
*sqlstmt
= stmt
->stmt
;
240 if ((data
= sqlstmt
->fetch(rv
)) != NULL
&& rv
== OK
) {
242 strcpy(rpkt
->errorString
, "Success");
245 if (data
== NULL
&& rv
== OK
) {
249 strcpy(rpkt
->errorString
, "Success fetch completed");
254 strcpy(rpkt
->errorString
, "fetch completed");
259 void * SqlNetworkHandler::processSqlFree(PacketHeader
&header
, char *buffer
)
261 ResponsePacket
*rpkt
= new ResponsePacket();
262 char *retval
= (char *) &rpkt
->retVal
;
263 SqlPacketFree
*pkt
= new SqlPacketFree();
264 pkt
->setBuffer(buffer
);
266 rpkt
->stmtID
= pkt
->stmtID
;
267 ListIterator stmtIter
= stmtList
.getIterator();
269 while (stmtIter
.hasElement())
271 stmt
= (NetworkStmt
*) stmtIter
.nextElement();
272 //TODO::Also check teh srcNetworkID
273 if (stmt
->stmtID
== pkt
->stmtID
) break;
275 AbsSqlStatement
*sqlstmt
= stmt
->stmt
;
277 ListIterator itprm
= stmt
->paramList
.getIterator();
278 BindSqlField
*fld
= NULL
;
279 while((fld
= (BindSqlField
*) itprm
.nextElement()) != NULL
) delete fld
;
280 stmt
->paramList
.reset();
281 ListIterator itprj
= stmt
->projList
.getIterator();
282 BindSqlProjectField
*pfld
= NULL
;
283 while((pfld
= (BindSqlProjectField
*) itprj
.nextElement()) != NULL
) delete pfld
;
284 stmt
->projList
.reset();
286 stmtList
.remove(stmt
);
289 strcpy(rpkt
->errorString
, "Success");
294 void * SqlNetworkHandler::processSqlCommit(PacketHeader
&header
, char *buffer
)
296 ResponsePacket
*rpkt
= new ResponsePacket();
297 char *retval
= (char *) &rpkt
->retVal
;
298 DbRetVal rv
= conn
->commit();
301 strcpy(rpkt
->errorString
, "Commit failure\n");
304 rv
= conn
->beginTrans();
306 strcpy(rpkt
->errorString
, "Success");
310 void *SqlNetworkHandler::processSqlRollback(PacketHeader
&header
, char *buffer
)
312 ResponsePacket
*rpkt
= new ResponsePacket();
313 char *retval
= (char *) &rpkt
->retVal
;
315 DbRetVal rv
= conn
->rollback();
318 strcpy(rpkt
->errorString
, "Rollback failure\n");
321 rv
= conn
->beginTrans();
323 strcpy(rpkt
->errorString
, "Success");
327 void *SqlNetworkHandler::processCommit(PacketHeader &header, char *buffer)
329 printDebug(DM_Network, "Processing COMMIT");
330 PacketCommit *pkt = new PacketCommit();
331 pkt->setBuffer(buffer);
332 pkt->setBufferSize(header.packetLength);
335 pkt->getExecPacketList(stmtList, pktList);
336 DbRetVal rv = applyExecPackets(stmtList, pktList);
340 printError(ErrSysFatal, "Unable to apply the exec packets\n");
346 void * SqlNetworkHandler::processFree(PacketHeader &header, char *buffer)
348 PacketFree *pkt = new PacketFree();
349 pkt->setBuffer(buffer);
350 pkt->setBufferSize(header.packetLength);
352 //printf("FREE %d \n", pkt->stmtID);
354 //This wont work for two statement executed in same transaction using same SqlStatement object using free.
355 //so do not delete now and put a flag 'readyfordelete' in NetworkStmt object and delete it during execute
357 ListIterator iter = stmtList.getIterator();
358 NetworkStmt *stmt, *removeStmt = NULL;
359 while (iter.hasElement())
361 stmt = (NetworkStmt*)iter.nextElement();
362 if (stmt->srcNetworkID == header.srcNetworkID
363 && stmt->stmtID == pkt->stmtID)
369 if (removeStmt) stmtList.remove(removeStmt);
370 else printf("Statement id %d not found in list \n", pkt->stmtID);
374 void * SqlNetworkHandler::processPrepare(PacketHeader &header, char *buffer)
376 PacketPrepare *pkt = new PacketPrepare();
377 pkt->setBuffer(buffer);
378 pkt->setBufferSize(header.packetLength);
380 printDebug(DM_Network, "PREPARE %d %s\n", pkt->stmtID, pkt->stmtString);
381 //for (int i =0 ; i < pkt->noParams; i++)
382 //printf("PREPARE type %d length %d \n", pkt->type[i], pkt->length[i]);
384 //TODO::add it to the SqlStatement list
385 AbsSqlStatement *sqlstmt = SqlFactory::createStatement(type);
386 sqlstmt->setConnection(conn);
387 NetworkStmt *nwStmt = new NetworkStmt();
388 printDebug(DM_Network, "Statement string %s\n", pkt->stmtString);
389 nwStmt->srcNetworkID = header.srcNetworkID;
390 nwStmt->stmtID = pkt->stmtID;
391 nwStmt->stmt = sqlstmt;
392 DbRetVal rv = sqlstmt->prepare(pkt->stmtString);
395 printError(ErrSysInit, "statement prepare failed\n");
399 BindSqlField *bindField = NULL;
401 for (int i = 0; i < pkt->noParams; i++)
403 bindField = new BindSqlField();
404 bindField->type = (DataType) pkt->type[i];
405 bindField->length = pkt->length[i];
406 bindField->value = AllDataType::alloc(bindField->type,
408 nwStmt->paramList.append(bindField);
410 stmtList.append(nwStmt);
415 DbRetVal SqlNetworkHandler::applyExecPackets(List sList, List pList)
417 ListIterator stmtIter = sList.getIterator();
419 DbRetVal rv = conn->beginTrans();
420 if (rv != OK) return rv;
421 ListIterator pktIter = pList.getIterator();
424 BindSqlField *bindField;
425 while (pktIter.hasElement())
427 pkt = (PacketExecute*) pktIter.nextElement();
430 while (stmtIter.hasElement())
432 nwstmt = (NetworkStmt*) stmtIter.nextElement();
433 if (nwstmt->stmtID == pkt->stmtID) {found = true ; break;}
436 printf("stmt not found in list. Negleting unreplicated table...\n");
439 ListIterator paramIter = nwstmt->paramList.getIterator();
441 while (paramIter.hasElement()) {
442 bindField = (BindSqlField*) paramIter.nextElement();
443 setParamValues(nwstmt->stmt, i+1, bindField->type, bindField->length, pkt->paramValues[i]);
447 DbRetVal rv = nwstmt->stmt->execute(rows);
450 printError(ErrSysFatal, "sql execute failed with rv %d\n", rv);
451 //TODO::log all things like SQL statements to a file
452 SqlNetworkHandler::conn->rollback();
453 printError(ErrPeerExecFailed, "Transaction Rolledback\n");
454 return ErrPeerExecFailed;
457 SqlNetworkHandler::conn->commit();
461 void SqlNetworkHandler::setParamValues(AbsSqlStatement
*stmt
, int parampos
, DataType type
,
462 int length
, char *value
)
467 stmt
->setIntParam(parampos
, *(int*)value
);
470 stmt
->setLongParam(parampos
, *(long*)value
);
473 stmt
->setLongLongParam(parampos
, *(long long*)value
);
476 stmt
->setShortParam(parampos
, *(short*)value
);
479 stmt
->setByteIntParam(parampos
, *(char*)value
);
482 stmt
->setDoubleParam(parampos
, *(double*)value
);
485 stmt
->setFloatParam(parampos
, *(float*)value
);
488 stmt
->setDateParam(parampos
, *(Date
*)value
);
491 stmt
->setTimeParam(parampos
, *(Time
*)value
);
494 stmt
->setTimeStampParam(parampos
, *(TimeStamp
*)value
);
498 char *d
=(char*)value
;
500 stmt
->setStringParam(parampos
, (char*)value
);
504 stmt
->setBinaryParam(parampos
, (char *) value
);