setBinaryParam 3rd parameter added
[csql.git] / src / sqlnetwork / SqlNwStatement.cxx
blobf26eaf24d27a6177a833d5eb791f4f7b05f2962c
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 <SqlNwStatement.h>
21 #include <Network.h>
23 DbRetVal SqlNwStatement::prepare(char *stmtstr)
25 DbRetVal rv = OK;
26 isSel = false;
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);
38 pkt->marshall();
39 rv = conn->send(SQL_NW_PKT_PREPARE, pkt->getMarshalledBuffer(), pkt->getBufferSize());
40 if (rv != OK) {
41 printError(rv, "Data could not be sent");
42 return rv;
44 int response = 0;
45 rv = conn->receive();
46 if (rv != OK) {
47 printError(rv, "Unable to Receive from peer");
48 return rv;
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;
57 char *buffer = NULL;
58 if (params) {
59 PacketHeader header;
60 int fd = ((TCPClient *)(conn->nwClient))->sockfd;
61 int numbytes = os::recv(fd, &header, sizeof(PacketHeader), 0);
62 if (numbytes == -1) {
63 printError(ErrOS, "Error reading from socket\n");
64 return ErrOS;
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);
69 if (numbytes == -1) {
70 printError(ErrOS, "Error reading from socket\n");
71 return ErrOS;
73 SqlPacketParamMetadata *mdpkt = new SqlPacketParamMetadata();
74 mdpkt->setBuffer(buffer);
75 mdpkt->unmarshall();
76 noOfParams = mdpkt->noParams;
77 //allocate null info for dml paramterized stmts to be filled up
78 //during set null
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);
104 delete mdpkt;
106 if (proj) {
107 PacketHeader header;
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");
112 return ErrOS;
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");
119 return ErrOS;
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);
146 delete prjmdpkt;
148 isPrepared = true;
149 delete pkt;
150 return rv;
153 DbRetVal SqlNwStatement::execute(int &rowsAffected)
155 DbRetVal rv = OK;
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);
167 pkt->marshall();
168 rv = conn->send(SQL_NW_PKT_EXECUTE, pkt->getMarshalledBuffer(), pkt->getBufferSize());
169 if (rv != OK) {
170 printError(rv, "Data could not be sent");
171 return rv;
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;
177 delete pkt;
178 ResponsePacket *rpkt = (ResponsePacket *) ((TCPClient *)conn->nwClient)->respPkt;
179 char *ptr = (char *) &rpkt->retVal;
180 rowsAffected = rpkt->rows;
181 if (*ptr != 1) {
182 printError(rpkt->errRetVal, "%s", rpkt->errorString);
183 return rpkt->errRetVal;
185 return rv;
188 DbRetVal SqlNwStatement::bindParam(int pos, void* value)
190 DbRetVal rv = OK;
191 printError(ErrWarning, "Deprecated. Use setParamXXX instead\n");
192 return rv;
195 DbRetVal SqlNwStatement::bindField(int pos, void* value)
197 if (!isPrepared) return OK;
198 BindSqlProjectField *prjFld = (BindSqlProjectField *) bindList.get(pos);
199 prjFld->value = value;
200 return OK;
202 void* SqlNwStatement::fetch()
204 DbRetVal rv = OK;
205 return fetch(rv);
208 void* SqlNwStatement::fetch(DbRetVal &ret)
210 SqlNwConnection *conn = (SqlNwConnection*)con;
211 if (! conn->isConOpen()) {
212 printError(ErrNoConnection, "No connection present");
213 ret = ErrNoConnection;
214 return NULL;
216 if (!isPrepared) return NULL;
217 void *ptrToFirstField = NULL;
219 DbRetVal rv = conn->nwClient->send(SQL_NW_PKT_FETCH, getStmtID());
220 if (rv != OK) {
221 printError(rv, "Data could not be sent");
222 return NULL;
225 /*SqlPacketFetch *pkt = new SqlPacketFetch();
226 pkt->stmtID = getStmtID();
227 pkt->marshall();
228 DbRetVal rv = conn->send(SQL_NW_PKT_FETCH, pkt->getMarshalledBuffer(), pkt->getBufferSize());
229 if (rv != OK) {
230 printError(rv, "Data could not be sent");
231 return NULL;
233 // printf("HEADER says packet type is %d\n", header.packetType);
234 int rowLength=0;
235 int dummy =0;
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");
244 return NULL;
246 printError(ErrOS, "Unable to send the packet\n");
247 return NULL;
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");
253 return NULL;
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);
263 rspkt->unmarshall();
264 delete [] rspkt->projValues;
265 ptrToFirstField = bindList.get(1);
266 delete rspkt;
267 //delete pkt;
268 return ptrToFirstField;
272 void* SqlNwStatement::fetchAndPrint(bool SQL)
274 if (!isPrepared) return NULL;
275 void *tuple = NULL;
276 BindSqlProjectField *fld = NULL;
277 tuple = fetch();
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);
283 printf("\t");
285 return tuple;
288 void* SqlNwStatement::next()
290 return fetch();
293 DbRetVal SqlNwStatement::close()
295 if (!isPrepared) return OK;
296 //TODO
297 return OK;
300 void* SqlNwStatement::getFieldValuePtr( int pos )
302 BindSqlProjectField *fld=(BindSqlProjectField *) bindList.get(pos+1);
303 return fld->value;
306 int SqlNwStatement::noOfProjFields()
308 if (!isPrepared) return 0;
309 return noOfProjs;
312 int SqlNwStatement::noOfParamFields()
314 if (!isPrepared) return 0;
315 return noOfParams;
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;
330 return OK;
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;
345 return OK;
348 DbRetVal SqlNwStatement::free()
350 DbRetVal rv = OK;
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();
359 pkt->marshall();
360 rv = conn->send(SQL_NW_PKT_FREE, pkt->getMarshalledBuffer(), pkt->getBufferSize());
361 if (rv != OK) {
362 printError(rv, "Data could not be sent");
363 return rv;
365 rv = conn->receive();
366 if (rv != OK) return rv;
367 ResponsePacket *rpkt = (ResponsePacket *) ((TCPClient *)conn->nwClient)->respPkt;
368 char *ptr = (char *) &rpkt->retVal;
369 if (*ptr != 1) {
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;
378 paramList.reset();
379 ListIterator itprj = bindList.getIterator();
380 BindSqlProjectField *pfld = NULL;
381 while((pfld = (BindSqlProjectField *) itprj.nextElement()) != NULL) {
382 delete pfld;
384 if (nullInfoSel) { ::free(nullInfoSel); nullInfoSel = NULL; }
385 if (nullInfoDml) { ::free(nullInfoDml); nullInfoDml = NULL; }
386 bindList.reset();
388 isPrepared = false;
389 delete pkt;
390 return rv;
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;
405 return;
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;
416 return;
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;
427 return;
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;
439 return;
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;
450 return;
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;
461 return;
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;
472 return;
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);
482 return;
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;
493 return;
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;
504 return;
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;
515 return;
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);
525 return;
528 void SqlNwStatement::getPrimaryKeyFieldName(char *tablename, char *pkfieldname)
530 if (pkfieldname == NULL) return;
531 //TODO
532 return;
535 List SqlNwStatement::getAllTableNames(DbRetVal &ret)
537 DbRetVal rv = OK;
539 ListIterator tblIter = tblNameList.getIterator();
540 while (tblIter.hasElement()) delete tblIter.nextElement();
541 tblNameList.reset();
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();
550 if (rv != OK) {
551 printError(rv, "Unable to Receive from peer");
552 ret = rv;
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;
559 PacketHeader header;
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");
564 ret = ErrOS;
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");
571 ret = ErrOS;
573 SqlPacketShowTables *pkt = new SqlPacketShowTables();
574 pkt->setBuffer(buffer);
575 rv = pkt->unmarshall();
576 if (rv != OK) {
577 printError(rv, "Data could not be sent");
578 ret = rv;
580 ptr = (char *)pkt->data;
581 while (noOfTables) {
582 Identifier *id = new Identifier();
583 strncpy(id->name, ptr, IDENTIFIER_LENGTH);
584 ptr += IDENTIFIER_LENGTH;
585 noOfTables--;
586 tblNameList.append(id);
588 return tblNameList;
591 bool SqlNwStatement::isFldNull(int pos)
593 if (nullInfoSel[pos - 1]) return true;
594 else return false;
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;