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 <SqlNwStatement.h>
23 DbRetVal
SqlNwStatement::prepare(char *stmtstr
)
27 SqlNwConnection
*conn
= (SqlNwConnection
*)con
;
28 if (! conn
->isConOpen()) {
29 printError(ErrNoConnection
, "No connection present");
30 return ErrNoConnection
;
32 if (isPrepared
) free();
33 if (nullInfoSel
) { ::free(nullInfoSel
); nullInfoSel
= NULL
; }
34 if (nullInfoDml
) { ::free(nullInfoDml
); nullInfoDml
= NULL
; }
35 SqlPacketPrepare
*pkt
= new SqlPacketPrepare();
36 pkt
->stmtString
= stmtstr
;
37 pkt
->stmtLength
= os::align(strlen(stmtstr
) + 1);
39 rv
= conn
->send(SQL_NW_PKT_PREPARE
, pkt
->getMarshalledBuffer(), pkt
->getBufferSize());
41 printError(rv
, "Data could not be sent");
47 printError(rv
, "Unable to Receive from peer");
50 ResponsePacket
*rpkt
= (ResponsePacket
*) ((TCPClient
*)conn
->nwClient
)->respPkt
;
51 char *ptr
= (char *) &rpkt
->retVal
;
52 if (*ptr
== 0) { delete pkt
; return ErrPeerResponse
; }
53 if (rpkt
->isSelect
) isSel
= true; else isSel
= false;
54 int params
= *(ptr
+ 2);
55 int proj
= *(ptr
+ 3);
56 stmtID
= rpkt
->stmtID
;
60 int fd
= ((TCPClient
*)(conn
->nwClient
))->sockfd
;
61 int numbytes
= os::recv(fd
, &header
, sizeof(PacketHeader
), 0);
63 printError(ErrOS
, "Error reading from socket\n");
66 // printf("HEADER says packet type is %d\n", header.packetType);
67 buffer
= (char*) malloc(header
.packetLength
);
68 numbytes
= os::recv(fd
,buffer
,header
.packetLength
,0);
70 printError(ErrOS
, "Error reading from socket\n");
73 SqlPacketParamMetadata
*mdpkt
= new SqlPacketParamMetadata();
74 mdpkt
->setBuffer(buffer
);
76 noOfParams
= mdpkt
->noParams
;
77 //allocate null info for dml paramterized stmts to be filled up
79 int nullInfoLen
= os::align(noOfParams
);
80 nullInfoDml
= (char *) malloc(nullInfoLen
);
81 memset(nullInfoDml
, 0, nullInfoLen
);
83 BindSqlField
*bindField
=NULL
;
84 FieldInfo
*fldInfo
= new FieldInfo();
85 char *ptr
= (char *) mdpkt
->data
;
86 for (int i
=0; i
< noOfParams
; i
++) {
87 *fldInfo
= *(FieldInfo
*) ptr
;
88 bindField
= new BindSqlField();
89 strcpy(bindField
->fName
, fldInfo
->fldName
);
90 bindField
->type
= fldInfo
->type
;
91 bindField
->length
= fldInfo
->length
;
92 bindField
->offset
= fldInfo
->offset
;
93 strcpy(bindField
->defaultValueBuf
, fldInfo
->defaultValueBuf
);
94 bindField
->isNull
= fldInfo
->isNull
;
95 bindField
->isPrimary
= fldInfo
->isPrimary
;
96 bindField
->isDefault
= fldInfo
->isDefault
;
97 bindField
->isUnique
= fldInfo
->isUnique
;
98 if (bindField
->type
== typeBinary
)
99 bindField
->value
= AllDataType::alloc(bindField
->type
, 2 * bindField
->length
);
100 else bindField
->value
= AllDataType::alloc(bindField
->type
, bindField
->length
);
101 paramList
.append(bindField
);
102 ptr
+= sizeof (FieldInfo
);
108 int fd
= ((TCPClient
*)(conn
->nwClient
))->sockfd
;
109 int numbytes
= os::recv(fd
, &header
, sizeof(PacketHeader
), 0);
110 if (numbytes
== -1) {
111 printError(ErrOS
, "Error reading from socket\n");
114 // printf("HEADER says packet type is %d\n", header.packetType);
115 buffer
= (char*) malloc(header
.packetLength
);
116 numbytes
= os::recv(fd
,buffer
,header
.packetLength
,0);
117 if (numbytes
== -1) {
118 printError(ErrOS
, "Error reading from socket\n");
121 SqlPacketProjMetadata
*prjmdpkt
= new SqlPacketProjMetadata();
122 prjmdpkt
->setBuffer(buffer
);
123 prjmdpkt
->unmarshall();
124 noOfProjs
= prjmdpkt
->noProjs
;
125 BindSqlProjectField
*prjFld
=NULL
;
126 FieldInfo
*fldInfo
= new FieldInfo();
127 char *ptr
= (char *) prjmdpkt
->data
;
128 for (int i
=0; i
< noOfProjs
; i
++) {
129 *fldInfo
= *(FieldInfo
*) ptr
;
130 prjFld
= new BindSqlProjectField();
131 strcpy(prjFld
->fName
, fldInfo
->fldName
);
132 prjFld
->type
= fldInfo
->type
;
133 prjFld
->length
= fldInfo
->length
;
134 prjFld
->offset
= fldInfo
->offset
;
135 strcpy(prjFld
->defaultValueBuf
, fldInfo
->defaultValueBuf
);
136 prjFld
->isNull
= fldInfo
->isNull
;
137 prjFld
->isPrimary
= fldInfo
->isPrimary
;
138 prjFld
->isDefault
= fldInfo
->isDefault
;
139 prjFld
->isUnique
= fldInfo
->isUnique
;
140 if (prjFld
->type
== typeBinary
)
141 prjFld
->value
= AllDataType::alloc(prjFld
->type
, 2 * prjFld
->length
);
142 else prjFld
->value
= AllDataType::alloc(prjFld
->type
, prjFld
->length
);
143 bindList
.append(prjFld
);
144 ptr
+= sizeof (FieldInfo
);
153 DbRetVal
SqlNwStatement::execute(int &rowsAffected
)
156 SqlNwConnection
*conn
= (SqlNwConnection
*)con
;
157 if (! conn
->isConOpen()) {
158 printError(ErrNoConnection
, "No connection present");
159 return ErrNoConnection
;
161 if (!isPrepared
) return ErrNotPrepared
;
162 SqlPacketExecute
*pkt
= new SqlPacketExecute();
163 pkt
->stmtID
= getStmtID();
164 pkt
->noParams
=paramList
.size();
165 pkt
->setParams(paramList
);
166 pkt
->setNullInfo(nullInfoDml
);
168 rv
= conn
->send(SQL_NW_PKT_EXECUTE
, pkt
->getMarshalledBuffer(), pkt
->getBufferSize());
170 printError(rv
, "Data could not be sent");
173 rv
= conn
->receive();
174 if (rv
!= OK
) return rv
;
175 memset(nullInfoDml
, 0, os::align(pkt
->noParams
));
176 //if(pkt->noParams) delete [] pkt->paramValues;
178 ResponsePacket
*rpkt
= (ResponsePacket
*) ((TCPClient
*)conn
->nwClient
)->respPkt
;
179 char *ptr
= (char *) &rpkt
->retVal
;
180 rowsAffected
= rpkt
->rows
;
182 printError(rpkt
->errRetVal
, "%s", rpkt
->errorString
);
183 return rpkt
->errRetVal
;
188 DbRetVal
SqlNwStatement::bindParam(int pos
, void* value
)
191 printError(ErrWarning
, "Deprecated. Use setParamXXX instead\n");
195 DbRetVal
SqlNwStatement::bindField(int pos
, void* value
)
197 if (!isPrepared
) return OK
;
198 BindSqlProjectField
*prjFld
= (BindSqlProjectField
*) bindList
.get(pos
);
199 prjFld
->value
= value
;
202 void* SqlNwStatement::fetch()
208 void* SqlNwStatement::fetch(DbRetVal
&ret
)
210 SqlNwConnection
*conn
= (SqlNwConnection
*)con
;
211 if (! conn
->isConOpen()) {
212 printError(ErrNoConnection
, "No connection present");
213 ret
= ErrNoConnection
;
216 if (!isPrepared
) return NULL
;
217 void *ptrToFirstField
= NULL
;
219 DbRetVal rv
= conn
->nwClient
->send(SQL_NW_PKT_FETCH
, getStmtID());
221 printError(rv
, "Data could not be sent");
225 /*SqlPacketFetch *pkt = new SqlPacketFetch();
226 pkt->stmtID = getStmtID();
228 DbRetVal rv = conn->send(SQL_NW_PKT_FETCH, pkt->getMarshalledBuffer(), pkt->getBufferSize());
230 printError(rv, "Data could not be sent");
233 // printf("HEADER says packet type is %d\n", header.packetType);
236 int fd
= ((TCPClient
*)(conn
->nwClient
))->sockfd
;
237 int numbytes
= os::recv(fd
, &rowLength
, 4, 0);
238 if (rowLength
==1 ) return NULL
;
239 else if (rowLength
== 2) {ret
= ErrUnknown
; return NULL
; }
241 if ((numbytes
= os::send(fd
, &dummy
, 4,MSG_NOSIGNAL
)) == -1) {
242 if (errno
== EPIPE
) {
243 printError(ErrNoConnection
, "connection not present");
246 printError(ErrOS
, "Unable to send the packet\n");
249 char *rowBuffer
= (char*) malloc(rowLength
);
250 numbytes
= os::recv(fd
,rowBuffer
,rowLength
,0);
251 if (numbytes
== -1) {
252 printError(ErrOS
, "Error reading from socket\n");
255 SqlPacketResultSet
*rspkt
= new SqlPacketResultSet();
256 rspkt
->setBuffer(rowBuffer
);
257 rspkt
->setProjList(bindList
);
258 rspkt
->noProjs
= bindList
.size();
259 if (nullInfoSel
== NULL
)
260 nullInfoSel
= (char *) malloc(os::align(rspkt
->noProjs
));
261 memset(nullInfoSel
, 0, os::align(rspkt
->noProjs
));
262 rspkt
->setNullInfo(nullInfoSel
);
264 delete [] rspkt
->projValues
;
265 ptrToFirstField
= bindList
.get(1);
268 return ptrToFirstField
;
272 void* SqlNwStatement::fetchAndPrint(bool SQL
)
274 if (!isPrepared
) return NULL
;
276 BindSqlProjectField
*fld
= NULL
;
278 if (NULL
== tuple
) return NULL
;
279 for(int i
= 0; i
< noOfProjs
; i
++) {
280 fld
= (BindSqlProjectField
*) bindList
.get(i
+ 1);
281 if (isFldNull(i
+1)) printf("NULL");
282 else AllDataType::printVal(fld
->value
, fld
->type
, fld
->length
);
288 void* SqlNwStatement::next()
293 DbRetVal
SqlNwStatement::close()
295 if (!isPrepared
) return OK
;
300 void* SqlNwStatement::getFieldValuePtr( int pos
)
302 BindSqlProjectField
*fld
=(BindSqlProjectField
*) bindList
.get(pos
+1);
306 int SqlNwStatement::noOfProjFields()
308 if (!isPrepared
) return 0;
312 int SqlNwStatement::noOfParamFields()
314 if (!isPrepared
) return 0;
318 DbRetVal
SqlNwStatement::getProjFldInfo (int projpos
, FieldInfo
*&fInfo
)
320 BindSqlProjectField
*prjFld
= (BindSqlProjectField
*) bindList
.get(projpos
);
321 strcpy(fInfo
->fldName
, prjFld
->fName
);
322 fInfo
->type
= prjFld
->type
;
323 fInfo
->length
= prjFld
->length
;
324 fInfo
->offset
= prjFld
->offset
;
325 strcpy(fInfo
->defaultValueBuf
, prjFld
->defaultValueBuf
);
326 fInfo
->isNull
= prjFld
->isNull
;
327 fInfo
->isPrimary
= prjFld
->isPrimary
;
328 fInfo
->isDefault
= prjFld
->isDefault
;
329 fInfo
->isUnique
= prjFld
->isUnique
;
333 DbRetVal
SqlNwStatement::getParamFldInfo (int parampos
, FieldInfo
*&fInfo
)
335 BindSqlField
*bindField
= (BindSqlField
*) paramList
.get(parampos
);
336 strcpy(fInfo
->fldName
, bindField
->fName
);
337 fInfo
->type
= bindField
->type
;
338 fInfo
->length
= bindField
->length
;
339 fInfo
->offset
= bindField
->offset
;
340 strcpy(fInfo
->defaultValueBuf
, bindField
->defaultValueBuf
);
341 fInfo
->isNull
= bindField
->isNull
;
342 fInfo
->isPrimary
= bindField
->isPrimary
;
343 fInfo
->isDefault
= bindField
->isDefault
;
344 fInfo
->isUnique
= bindField
->isUnique
;
348 DbRetVal
SqlNwStatement::free()
351 SqlNwConnection
*conn
= (SqlNwConnection
*)con
;
352 if (! conn
->isConOpen()) {
353 printError(ErrNoConnection
, "No connection present");
354 return ErrNoConnection
;
356 if (!isPrepared
) return OK
;
357 SqlPacketFree
*pkt
= new SqlPacketFree();
358 pkt
->stmtID
= getStmtID();
360 rv
= conn
->send(SQL_NW_PKT_FREE
, pkt
->getMarshalledBuffer(), pkt
->getBufferSize());
362 printError(rv
, "Data could not be sent");
365 rv
= conn
->receive();
366 if (rv
!= OK
) return rv
;
367 ResponsePacket
*rpkt
= (ResponsePacket
*) ((TCPClient
*)conn
->nwClient
)->respPkt
;
368 char *ptr
= (char *) &rpkt
->retVal
;
370 printf("there is some error\n");
371 return ErrPeerResponse
;
373 ListIterator itprm
= paramList
.getIterator();
374 BindSqlField
*fld
= NULL
;
375 while((fld
= (BindSqlField
*) itprm
.nextElement()) != NULL
) {
376 if (fld
->value
) ::free(fld
->value
); delete fld
;
379 ListIterator itprj
= bindList
.getIterator();
380 BindSqlProjectField
*pfld
= NULL
;
381 while((pfld
= (BindSqlProjectField
*) itprj
.nextElement()) != NULL
) {
384 if (nullInfoSel
) { ::free(nullInfoSel
); nullInfoSel
= NULL
; }
385 if (nullInfoDml
) { ::free(nullInfoDml
); nullInfoDml
= NULL
; }
393 // In all the following setXXXParam functions type and length fields are
394 // reinitialized to accommodate fix for MySQL bug #1382
395 // SQLDescribeParam returns the same type information
397 void SqlNwStatement::setShortParam(int paramPos
, short value
)
399 if (!isPrepared
) return;
400 if (paramPos
<= 0) return;
401 BindSqlField
*bindField
= (BindSqlField
*) paramList
.get(paramPos
);
402 bindField
->type
= typeShort
;
403 bindField
->length
= AllDataType::size(typeShort
);
404 *(short *) bindField
->value
= value
;
408 void SqlNwStatement::setIntParam(int paramPos
, int value
)
410 if (!isPrepared
) return ;
411 if (paramPos
<= 0) return;
412 BindSqlField
*bindField
= (BindSqlField
*) paramList
.get(paramPos
);
413 bindField
->type
= typeInt
;
414 bindField
->length
= sizeof(int);
415 *(int *) bindField
->value
= value
;
419 void SqlNwStatement::setLongParam(int paramPos
, long value
)
421 if (!isPrepared
) return ;
422 if (paramPos
<= 0) return;
423 BindSqlField
*bindField
= (BindSqlField
*) paramList
.get(paramPos
);
424 bindField
->type
= typeLong
;
425 bindField
->length
= sizeof(long);
426 *(long *) bindField
->value
= value
;
431 void SqlNwStatement::setLongLongParam(int paramPos
, long long value
)
433 if (!isPrepared
) return ;
434 if (paramPos
<= 0) return;
435 BindSqlField
*bindField
= (BindSqlField
*) paramList
.get(paramPos
);
436 bindField
->type
= typeLongLong
;
437 bindField
->length
= AllDataType::size(typeLongLong
);
438 *(long long *) bindField
->value
= value
;
442 void SqlNwStatement::setByteIntParam(int paramPos
, ByteInt value
)
444 if (!isPrepared
) return ;
445 if (paramPos
<= 0) return;
446 BindSqlField
*bindField
= (BindSqlField
*) paramList
.get(paramPos
);
447 bindField
->type
= typeByteInt
;
448 bindField
->length
= AllDataType::size(typeByteInt
);
449 *(ByteInt
*) bindField
->value
= value
;
453 void SqlNwStatement::setFloatParam(int paramPos
, float value
)
455 if (!isPrepared
) return ;
456 if (paramPos
<= 0) return;
457 BindSqlField
*bindField
= (BindSqlField
*) paramList
.get(paramPos
);
458 bindField
->type
= typeFloat
;
459 bindField
->length
= AllDataType::size(typeFloat
);
460 *(float *) bindField
->value
= value
;
464 void SqlNwStatement::setDoubleParam(int paramPos
, double value
)
466 if (!isPrepared
) return ;
467 if (paramPos
<= 0) return;
468 BindSqlField
*bindField
= (BindSqlField
*) paramList
.get(paramPos
);
469 bindField
->type
= typeDouble
;
470 bindField
->length
= AllDataType::size(typeDouble
);
471 *(double *) bindField
->value
= value
;
475 void SqlNwStatement::setStringParam(int paramPos
, char *value
)
477 if (!isPrepared
) return ;
478 if (paramPos
<= 0) return;
479 BindSqlField
*bindField
= (BindSqlField
*) paramList
.get(paramPos
);
480 bindField
->type
= typeString
;
481 strcpy((char *) bindField
->value
, value
);
485 void SqlNwStatement::setDateParam(int paramPos
, Date value
)
487 if (!isPrepared
) return ;
488 if (paramPos
<= 0) return;
489 BindSqlField
*bindField
= (BindSqlField
*) paramList
.get(paramPos
);
490 bindField
->type
= typeDate
;
491 bindField
->length
= sizeof(Date
);
492 *(Date
*)bindField
->value
= value
;
496 void SqlNwStatement::setTimeParam(int paramPos
, Time value
)
498 if (!isPrepared
) return ;
499 if (paramPos
<= 0) return;
500 BindSqlField
*bindField
= (BindSqlField
*) paramList
.get(paramPos
);
501 bindField
->type
= typeTime
;
502 bindField
->length
= sizeof(Time
);
503 * (Time
*) bindField
->value
= value
;
507 void SqlNwStatement::setTimeStampParam(int paramPos
, TimeStamp value
)
509 if (!isPrepared
) return ;
510 if (paramPos
<= 0) return;
511 BindSqlField
*bindField
= (BindSqlField
*) paramList
.get(paramPos
);
512 bindField
->type
= typeTimeStamp
;
513 bindField
->length
= sizeof(TimeStamp
);
514 *(TimeStamp
*) bindField
->value
= value
;
518 void SqlNwStatement::setBinaryParam(int paramPos
, void *value
, int length
)
520 if (!isPrepared
) return;
521 if (paramPos
<= 0) return;
522 BindSqlField
*bindField
= (BindSqlField
*) paramList
.get(paramPos
);
523 bindField
->type
= typeBinary
;
524 memcpy(bindField
->value
, value
, 2 * bindField
->length
);
528 void SqlNwStatement::getPrimaryKeyFieldName(char *tablename
, char *pkfieldname
)
530 if (pkfieldname
== NULL
) return;
535 List
SqlNwStatement::getAllTableNames(DbRetVal
&ret
)
539 ListIterator tblIter
= tblNameList
.getIterator();
540 while (tblIter
.hasElement()) delete tblIter
.nextElement();
543 SqlNwConnection
*conn
= (SqlNwConnection
*)con
;
544 if (! conn
->isConOpen()) {
545 printError(ErrNoConnection
, "No connection present");
546 ret
= ErrNoConnection
;
548 rv
= conn
->send(SQL_NW_PKT_SHOWTABLES
);
549 rv
= conn
->receive();
551 printError(rv
, "Unable to Receive from peer");
554 ResponsePacket
*rpkt
= (ResponsePacket
*) ((TCPClient
*)conn
->nwClient
)->respPkt
;
555 char *ptr
= (char *) &rpkt
->retVal
;
556 if (*ptr
== 0) { ret
= ErrPeerResponse
; }
557 stmtID
= rpkt
->stmtID
;
558 int noOfTables
= rpkt
->rows
;
560 int fd
= ((TCPClient
*)(conn
->nwClient
))->sockfd
;
561 int numbytes
= os::recv(fd
, &header
, sizeof(PacketHeader
), 0);
562 if (numbytes
== -1) {
563 printError(ErrOS
, "Error reading from socket\n");
566 // printf("HEADER says packet type is %d\n", header.packetType);
567 char *buffer
= (char*) malloc(header
.packetLength
);
568 numbytes
= os::recv(fd
,buffer
,header
.packetLength
,0);
569 if (numbytes
== -1) {
570 printError(ErrOS
, "Error reading from socket\n");
573 SqlPacketShowTables
*pkt
= new SqlPacketShowTables();
574 pkt
->setBuffer(buffer
);
575 rv
= pkt
->unmarshall();
577 printError(rv
, "Data could not be sent");
580 ptr
= (char *)pkt
->data
;
582 Identifier
*id
= new Identifier();
583 strncpy(id
->name
, ptr
, IDENTIFIER_LENGTH
);
584 ptr
+= IDENTIFIER_LENGTH
;
586 tblNameList
.append(id
);
591 bool SqlNwStatement::isFldNull(int pos
)
593 if (nullInfoSel
[pos
- 1]) return true;
597 bool SqlNwStatement::isFldNull(char *fname
)
599 for (int i
=0; i
< bindList
.size(); i
++) {
600 BindSqlProjectField
*fld
= (BindSqlProjectField
*) bindList
.get(i
+1);
601 if (strcmp(fname
, fld
->fName
) == 0) return isFldNull(i
+1);
605 void SqlNwStatement::setNull(int fldPos
)
607 if (nullInfoDml
) nullInfoDml
[fldPos
-1] = 1;