1 // Copyright (c) 1999-2018 David Muse
2 // See the file COPYING for more information
3
4 #include <config.h>
5 #include <sqlrelay/sqlrserver.h>
6 #include <rudiments/character.h>
7 #include <rudiments/stdio.h>
8 #include <rudiments/process.h>
9
10 #define NEED_DATATYPESTRING 1
11 #include <datatypes.h>
12 #include <defines.h>
13 #define NEED_BEFORE_BIND_VARIABLE 1
14 #define NEED_AFTER_BIND_VARIABLE 1
15 #define NEED_IS_BIND_DELIMITER 1
16 #include <bindvariables.h>
17
18 class sqlrservercursorprivate {
19 friend class sqlrservercursor;
20
21 regularexpression _createtemp;
22
23 uint16_t _id;
24
25 char *_querybuffer;
26 uint32_t _querylength;
27 sqlrquerystatus_t _querystatus;
28 stringbuffer _querywithfakeinputbinds;
29
30 xmldom *_querytree;
31 stringbuffer _translatedquery;
32
33 memorypool _bindpool;
34 memorypool _bindmappingspool;
35 namevaluepairs *_bindmappings;
36
37 uint16_t _inbindcount;
38 sqlrserverbindvar *_inbindvars;
39 uint16_t _outbindcount;
40 sqlrserverbindvar *_outbindvars;
41 uint16_t _inoutbindcount;
42 sqlrserverbindvar *_inoutbindvars;
43
44 uint64_t _totalrowsfetched;
45
46 bool _currentrowreformatted;
47
48 uint64_t _commandstartsec;
49 uint64_t _commandstartusec;
50 uint64_t _commandendsec;
51 uint64_t _commandendusec;
52 uint64_t _querystartsec;
53 uint64_t _querystartusec;
54 uint64_t _queryendsec;
55 uint64_t _queryendusec;
56 uint64_t _fetchstartsec;
57 uint64_t _fetchstartusec;
58 uint64_t _fetchendsec;
59 uint64_t _fetchendusec;
60 uint64_t _fetchusec;
61
62 uint32_t _maxerrorlength;
63
64 char *_error;
65 uint32_t _errorlength;
66 int64_t _errnum;
67 bool _liveconnection;
68
69 sqlrcursorstate_t _state;
70
71 sqlrquerycursor *_customquerycursor;
72
73 bool _columninfoisvalid;
74
75 bool _queryhasbeenpreprocessed;
76 bool _queryhasbeenprepared;
77 bool _queryhasbeenexecuted;
78 bool _queryneedsintercept;
79 bool _querywasintercepted;
80 bool _bindswerefaked;
81 bool _fakeinputbindsforthisquery;
82 sqlrquerytype_t _querytype;
83
84 const char **_columnnames;
85 uint16_t *_columnnamelengths;
86 uint16_t *_columntypes;
87 const char **_columntypenames;
88 uint16_t *_columntypenamelengths;
89 uint32_t *_columnlengths;
90 uint32_t *_columnprecisions;
91 uint32_t *_columnscales;
92 uint16_t *_columnisnullables;
93 uint16_t *_columnisprimarykeys;
94 uint16_t *_columnisuniques;
95 uint16_t *_columnispartofkeys;
96 uint16_t *_columnisunsigneds;
97 uint16_t *_columniszerofilleds;
98 uint16_t *_columnisbinarys;
99 uint16_t *_columnisautoincrements;
100 const char **_columntables;
101 uint16_t *_columntablelengths;
102
103 const char **_fieldnames;
104 const char **_fields;
105 uint64_t *_fieldlengths;
106 bool *_blobs;
107 bool *_nulls;
108
109 uint64_t _querytimeout;
110 bool _executedirect;
111 bool _executerpc;
112
113 bool _resultsetheaderhasbeenhandled;
114
115 unsigned char _moduledata[1024];
116 };
117
sqlrservercursor(sqlrserverconnection * conn,uint16_t id)118 sqlrservercursor::sqlrservercursor(sqlrserverconnection *conn, uint16_t id) {
119
120 pvt=new sqlrservercursorprivate;
121
122 this->conn=conn;
123
124 pvt->_maxerrorlength=conn->cont->getConfig()->getMaxErrorLength();
125
126 pvt->_bindmappings=new namevaluepairs;
127
128 setInputBindCount(0);
129 pvt->_inbindvars=new sqlrserverbindvar[
130 conn->cont->getConfig()->getMaxBindCount()];
131 setOutputBindCount(0);
132 pvt->_outbindvars=new sqlrserverbindvar[
133 conn->cont->getConfig()->getMaxBindCount()];
134 setInputOutputBindCount(0);
135 pvt->_inoutbindvars=new sqlrserverbindvar[
136 conn->cont->getConfig()->getMaxBindCount()];
137
138 pvt->_totalrowsfetched=0;
139
140 pvt->_currentrowreformatted=false;
141
142 pvt->_commandstartsec=0;
143 pvt->_commandstartusec=0;
144 pvt->_commandendsec=0;
145 pvt->_commandendusec=0;
146 pvt->_querystartsec=0;
147 pvt->_querystartusec=0;
148 pvt->_queryendsec=0;
149 pvt->_queryendusec=0;
150 pvt->_fetchstartsec=0;
151 pvt->_fetchstartusec=0;
152 pvt->_fetchendsec=0;
153 pvt->_fetchendusec=0;
154 pvt->_fetchusec=0;
155
156 setState(SQLRCURSORSTATE_AVAILABLE);
157
158 setCreateTempTablePattern("(create|CREATE|declare|DECLARE)[ \\r\\n]+((global|GLOBAL|local|LOCAL)?[ \\r\\n]+)?(temp|TEMP|temporary|TEMPORARY)?[ \\r\\n]+(table|TABLE)[ \\r\\n]+");
159
160 pvt->_querybuffer=
161 new char[conn->cont->getConfig()->getMaxQuerySize()+1];
162 setQueryLength(0);
163
164 setQueryStatus(SQLRQUERYSTATUS_ERROR);
165
166 setQueryTree(NULL);
167
168 pvt->_error=new char[pvt->_maxerrorlength+1];
169 pvt->_errorlength=0;
170 pvt->_errnum=0;
171 pvt->_liveconnection=true;
172
173 setCommandStart(0,0);
174 setCommandEnd(0,0);
175 setQueryStart(0,0);
176 setQueryEnd(0,0);
177
178 setCustomQueryCursor(NULL);
179
180 clearTotalRowsFetched();
181
182 pvt->_id=id;
183
184 pvt->_columninfoisvalid=false;
185
186 pvt->_queryhasbeenpreprocessed=false;
187 pvt->_queryhasbeenprepared=false;
188 pvt->_queryhasbeenexecuted=false;
189 pvt->_queryneedsintercept=false;
190 pvt->_querywasintercepted=false;
191 pvt->_bindswerefaked=false;
192 pvt->_fakeinputbindsforthisquery=false;
193 pvt->_querytype=SQLRQUERYTYPE_ETC;
194
195 pvt->_columnnames=NULL;
196 pvt->_columnnamelengths=NULL;
197 pvt->_columntypes=NULL;
198 pvt->_columntypenames=NULL;
199 pvt->_columntypenamelengths=NULL;
200 pvt->_columnlengths=NULL;
201 pvt->_columnprecisions=NULL;
202 pvt->_columnscales=NULL;
203 pvt->_columnisnullables=NULL;
204 pvt->_columnisprimarykeys=NULL;
205 pvt->_columnisuniques=NULL;
206 pvt->_columnispartofkeys=NULL;
207 pvt->_columnisunsigneds=NULL;
208 pvt->_columniszerofilleds=NULL;
209 pvt->_columnisbinarys=NULL;
210 pvt->_columnisautoincrements=NULL;
211 pvt->_columntables=NULL;
212 pvt->_columntablelengths=NULL;
213
214 pvt->_fieldnames=NULL;
215 pvt->_fields=NULL;
216 pvt->_fieldlengths=NULL;
217 pvt->_blobs=NULL;
218 pvt->_nulls=NULL;
219 uint32_t colcount=conn->cont->getMaxColumnCount();
220 if (colcount) {
221 allocateColumnPointers(colcount);
222 allocateFieldPointers(colcount);
223 }
224
225 pvt->_querytimeout=conn->cont->getQueryTimeout();
226 pvt->_executedirect=conn->cont->getExecuteDirect();
227 pvt->_executerpc=false;
228
229 pvt->_resultsetheaderhasbeenhandled=false;
230 }
231
~sqlrservercursor()232 sqlrservercursor::~sqlrservercursor() {
233 delete[] pvt->_querybuffer;
234 delete pvt->_querytree;
235 delete pvt->_bindmappings;
236 delete[] pvt->_inbindvars;
237 delete[] pvt->_outbindvars;
238 delete[] pvt->_inoutbindvars;
239 delete pvt->_customquerycursor;
240 delete[] pvt->_error;
241 deallocateColumnPointers();
242 deallocateFieldPointers();
243 delete pvt;
244 }
245
open()246 bool sqlrservercursor::open() {
247 return true;
248 }
249
close()250 bool sqlrservercursor::close() {
251 // by default do nothing
252 return true;
253 }
254
queryType(const char * query,uint32_t length)255 sqlrquerytype_t sqlrservercursor::queryType(const char *query,
256 uint32_t length) {
257
258 // skip past leading garbage
259 const char *ptr=conn->cont->skipWhitespaceAndComments(query);
260
261 // initialize to "etc"
262 sqlrquerytype_t retval=SQLRQUERYTYPE_ETC;
263
264 // look for specific query types
265 if (!charstring::compare(ptr,"select",6)) {
266 retval=SQLRQUERYTYPE_SELECT;
267 ptr=ptr+6;
268 } else if (!charstring::compare(ptr,"insert",6)) {
269 retval=SQLRQUERYTYPE_INSERT;
270 ptr=ptr+6;
271 } else if (!charstring::compare(ptr,"update",6)) {
272 retval=SQLRQUERYTYPE_UPDATE;
273 ptr=ptr+6;
274 } else if (!charstring::compare(ptr,"delete",6)) {
275 retval=SQLRQUERYTYPE_DELETE;
276 ptr=ptr+6;
277 } else if (!charstring::compare(ptr,"create",6)) {
278 retval=SQLRQUERYTYPE_CREATE;
279 ptr=ptr+6;
280 } else if (!charstring::compare(ptr,"drop",4)) {
281 retval=SQLRQUERYTYPE_DROP;
282 ptr=ptr+4;
283 } else if (!charstring::compare(ptr,"alter",5)) {
284 retval=SQLRQUERYTYPE_ALTER;
285 ptr=ptr+5;
286 } else if (!charstring::compare(ptr,"begin") ||
287 !charstring::compare(ptr,"begin work")) {
288 return SQLRQUERYTYPE_BEGIN;
289 } else if (!charstring::compare(ptr,"start",5)) {
290 retval=SQLRQUERYTYPE_BEGIN;
291 ptr=ptr+5;
292 } else if (!charstring::compare(ptr,"commit",6)) {
293 return SQLRQUERYTYPE_COMMIT;
294 } else if (!charstring::compare(ptr,"rollback",8)) {
295 return SQLRQUERYTYPE_ROLLBACK;
296 }
297
298 // for some query types, verify that whitespace follows
299 if (retval!=SQLRQUERYTYPE_ETC) {
300 if (!character::isWhitespace(*ptr)) {
301 retval=SQLRQUERYTYPE_ETC;
302 }
303 }
304 return retval;
305 }
306
isCustomQuery()307 bool sqlrservercursor::isCustomQuery() {
308 return false;
309 }
310
prepareQuery(const char * query,uint32_t length)311 bool sqlrservercursor::prepareQuery(const char *query, uint32_t length) {
312 // by default, do nothing...
313 return true;
314 }
315
supportsNativeBinds(const char * query,uint32_t length)316 bool sqlrservercursor::supportsNativeBinds(const char *query,
317 uint32_t length) {
318 return true;
319 }
320
inputBind(const char * variable,uint16_t variablesize,const char * value,uint32_t valuesize,int16_t * isnull)321 bool sqlrservercursor::inputBind(const char *variable,
322 uint16_t variablesize,
323 const char *value,
324 uint32_t valuesize,
325 int16_t *isnull) {
326 // by default, do nothing...
327 return true;
328 }
329
inputBind(const char * variable,uint16_t variablesize,int64_t * value)330 bool sqlrservercursor::inputBind(const char *variable,
331 uint16_t variablesize,
332 int64_t *value) {
333 // by default, do nothing...
334 return true;
335 }
336
inputBind(const char * variable,uint16_t variablesize,double * value,uint32_t precision,uint32_t scale)337 bool sqlrservercursor::inputBind(const char *variable,
338 uint16_t variablesize,
339 double *value,
340 uint32_t precision,
341 uint32_t scale) {
342 // by default, do nothing...
343 return true;
344 }
345
dateToString(char * buffer,uint16_t buffersize,int16_t year,int16_t month,int16_t day,int16_t hour,int16_t minute,int16_t second,int32_t microsecond,const char * tz,bool isnegative)346 void sqlrservercursor::dateToString(char *buffer, uint16_t buffersize,
347 int16_t year, int16_t month, int16_t day,
348 int16_t hour, int16_t minute, int16_t second,
349 int32_t microsecond, const char *tz,
350 bool isnegative) {
351
352 const char *format=conn->cont->getConfig()->
353 getFakeInputBindVariablesDateFormat();
354 if (charstring::isNullOrEmpty(format)) {
355 format="YYYY-MM-DD HH:MI:SS";
356 }
357
358 // FIXME: it'd be nice if we could pass buffer/buffersize
359 // into convertDateTime
360 char *newdate=conn->cont->convertDateTime(format,
361 year,month,day,
362 hour,minute,second,
363 microsecond,isnegative);
364 charstring::safeCopy(buffer,buffersize,newdate);
365 delete[] newdate;
366 }
367
inputBind(const char * variable,uint16_t variablesize,int64_t year,int16_t month,int16_t day,int16_t hour,int16_t minute,int16_t second,int32_t microsecond,const char * tz,bool isnegative,char * buffer,uint16_t buffersize,int16_t * isnull)368 bool sqlrservercursor::inputBind(const char *variable,
369 uint16_t variablesize,
370 int64_t year,
371 int16_t month,
372 int16_t day,
373 int16_t hour,
374 int16_t minute,
375 int16_t second,
376 int32_t microsecond,
377 const char *tz,
378 bool isnegative,
379 char *buffer,
380 uint16_t buffersize,
381 int16_t *isnull) {
382 dateToString(buffer,buffersize,year,month,day,
383 hour,minute,second,microsecond,tz,isnegative);
384 if (buffer[0]=='\0') {
385 *isnull=conn->nullBindValue();
386 }
387 return inputBind(variable,variablesize,buffer,buffersize,isnull);
388 }
389
inputBindBlob(const char * variable,uint16_t variablesize,const char * value,uint32_t valuesize,int16_t * isnull)390 bool sqlrservercursor::inputBindBlob(const char *variable,
391 uint16_t variablesize,
392 const char *value,
393 uint32_t valuesize,
394 int16_t *isnull) {
395 // fall back to string bind implementation
396 return inputBind(variable,variablesize,value,valuesize,isnull);
397 }
398
inputBindClob(const char * variable,uint16_t variablesize,const char * value,uint32_t valuesize,int16_t * isnull)399 bool sqlrservercursor::inputBindClob(const char *variable,
400 uint16_t variablesize,
401 const char *value,
402 uint32_t valuesize,
403 int16_t *isnull) {
404 // fall back to string bind implementation
405 return inputBind(variable,variablesize,value,valuesize,isnull);
406 }
407
outputBind(const char * variable,uint16_t variablesize,char * value,uint32_t valuesize,int16_t * isnull)408 bool sqlrservercursor::outputBind(const char *variable,
409 uint16_t variablesize,
410 char *value,
411 uint32_t valuesize,
412 int16_t *isnull) {
413 // by default, do nothing...
414 return true;
415 }
416
outputBind(const char * variable,uint16_t variablesize,int64_t * value,int16_t * isnull)417 bool sqlrservercursor::outputBind(const char *variable,
418 uint16_t variablesize,
419 int64_t *value,
420 int16_t *isnull) {
421 // by default, do nothing...
422 return true;
423 }
424
outputBind(const char * variable,uint16_t variablesize,double * value,uint32_t * precision,uint32_t * scale,int16_t * isnull)425 bool sqlrservercursor::outputBind(const char *variable,
426 uint16_t variablesize,
427 double *value,
428 uint32_t *precision,
429 uint32_t *scale,
430 int16_t *isnull) {
431 // by default, do nothing...
432 return true;
433 }
434
outputBind(const char * variable,uint16_t variablesize,int16_t * year,int16_t * month,int16_t * day,int16_t * hour,int16_t * minute,int16_t * second,int32_t * microsecond,const char ** tz,bool * isnegative,char * buffer,uint16_t buffersize,int16_t * isnull)435 bool sqlrservercursor::outputBind(const char *variable,
436 uint16_t variablesize,
437 int16_t *year,
438 int16_t *month,
439 int16_t *day,
440 int16_t *hour,
441 int16_t *minute,
442 int16_t *second,
443 int32_t *microsecond,
444 const char **tz,
445 bool *isnegative,
446 char *buffer,
447 uint16_t buffersize,
448 int16_t *isnull) {
449 // by default, do nothing...
450 return true;
451 }
452
outputBindBlob(const char * variable,uint16_t variablesize,uint16_t index,int16_t * isnull)453 bool sqlrservercursor::outputBindBlob(const char *variable,
454 uint16_t variablesize,
455 uint16_t index,
456 int16_t *isnull) {
457 // by default, do nothing...
458 return true;
459 }
460
outputBindClob(const char * variable,uint16_t variablesize,uint16_t index,int16_t * isnull)461 bool sqlrservercursor::outputBindClob(const char *variable,
462 uint16_t variablesize,
463 uint16_t index,
464 int16_t *isnull) {
465 // by default, do nothing...
466 return true;
467 }
468
outputBindCursor(const char * variable,uint16_t variablesize,sqlrservercursor * cursor)469 bool sqlrservercursor::outputBindCursor(const char *variable,
470 uint16_t variablesize,
471 sqlrservercursor *cursor) {
472 // by default, do nothing...
473 return true;
474 }
475
getLobOutputBindLength(uint16_t index,uint64_t * length)476 bool sqlrservercursor::getLobOutputBindLength(uint16_t index, uint64_t *length) {
477 *length=0;
478 return true;
479 }
480
getLobOutputBindSegment(uint16_t index,char * buffer,uint64_t buffersize,uint64_t offset,uint64_t charstoread,uint64_t * charsread)481 bool sqlrservercursor::getLobOutputBindSegment(uint16_t index,
482 char *buffer, uint64_t buffersize,
483 uint64_t offset, uint64_t charstoread,
484 uint64_t *charsread) {
485 *charsread=0;
486 return false;
487 }
488
closeLobOutputBind(uint16_t index)489 void sqlrservercursor::closeLobOutputBind(uint16_t index) {
490 // by default, do nothing
491 }
492
inputOutputBind(const char * variable,uint16_t variablesize,char * value,uint32_t valuesize,int16_t * isnull)493 bool sqlrservercursor::inputOutputBind(const char *variable,
494 uint16_t variablesize,
495 char *value,
496 uint32_t valuesize,
497 int16_t *isnull) {
498 // by default, do nothing...
499 return true;
500 }
501
inputOutputBind(const char * variable,uint16_t variablesize,int64_t * value,int16_t * isnull)502 bool sqlrservercursor::inputOutputBind(const char *variable,
503 uint16_t variablesize,
504 int64_t *value,
505 int16_t *isnull) {
506 // by default, do nothing...
507 return true;
508 }
509
inputOutputBind(const char * variable,uint16_t variablesize,double * value,uint32_t * precision,uint32_t * scale,int16_t * isnull)510 bool sqlrservercursor::inputOutputBind(const char *variable,
511 uint16_t variablesize,
512 double *value,
513 uint32_t *precision,
514 uint32_t *scale,
515 int16_t *isnull) {
516 // by default, do nothing...
517 return true;
518 }
519
inputOutputBind(const char * variable,uint16_t variablesize,int16_t * year,int16_t * month,int16_t * day,int16_t * hour,int16_t * minute,int16_t * second,int32_t * microsecond,const char ** tz,bool * isnegative,char * buffer,uint16_t buffersize,int16_t * isnull)520 bool sqlrservercursor::inputOutputBind(const char *variable,
521 uint16_t variablesize,
522 int16_t *year,
523 int16_t *month,
524 int16_t *day,
525 int16_t *hour,
526 int16_t *minute,
527 int16_t *second,
528 int32_t *microsecond,
529 const char **tz,
530 bool *isnegative,
531 char *buffer,
532 uint16_t buffersize,
533 int16_t *isnull) {
534 // by default, do nothing...
535 return true;
536 }
537
inputOutputBindBlob(const char * variable,uint16_t variablesize,uint16_t index,int16_t * isnull)538 bool sqlrservercursor::inputOutputBindBlob(const char *variable,
539 uint16_t variablesize,
540 uint16_t index,
541 int16_t *isnull) {
542 // by default, do nothing...
543 return true;
544 }
545
inputOutputBindClob(const char * variable,uint16_t variablesize,uint16_t index,int16_t * isnull)546 bool sqlrservercursor::inputOutputBindClob(const char *variable,
547 uint16_t variablesize,
548 uint16_t index,
549 int16_t *isnull) {
550 // by default, do nothing...
551 return true;
552 }
553
getLobInputOutputBindLength(uint16_t index,uint64_t * length)554 bool sqlrservercursor::getLobInputOutputBindLength(uint16_t index,
555 uint64_t *length) {
556 *length=0;
557 return true;
558 }
559
getLobInputOutputBindSegment(uint16_t index,char * buffer,uint64_t buffersize,uint64_t offset,uint64_t charstoread,uint64_t * charsread)560 bool sqlrservercursor::getLobInputOutputBindSegment(uint16_t index,
561 char *buffer, uint64_t buffersize,
562 uint64_t offset, uint64_t charstoread,
563 uint64_t *charsread) {
564 *charsread=0;
565 return false;
566 }
567
closeLobInputOutputBind(uint16_t index)568 void sqlrservercursor::closeLobInputOutputBind(uint16_t index) {
569 // by default, do nothing
570 }
571
checkForTempTable(const char * query,uint32_t length)572 void sqlrservercursor::checkForTempTable(const char *query, uint32_t length) {
573
574 // see if the query matches the pattern for a temporary query that
575 // creates a temporary table
576 const char *ptr=skipCreateTempTableClause(query);
577 if (!ptr) {
578 return;
579 }
580
581 // get the table name
582 stringbuffer tablename;
583 const char *endptr=query+length;
584 while (*ptr && !character::isWhitespace(*ptr) && ptr<endptr) {
585 tablename.append(*ptr);
586 ptr++;
587 }
588
589 // append to list of temp tables
590 conn->cont->addSessionTempTableForDrop(tablename.getString());
591 }
592
truncateTableQuery()593 const char *sqlrservercursor::truncateTableQuery() {
594 return "delete from";
595 }
596
executeQuery(const char * query,uint32_t length)597 bool sqlrservercursor::executeQuery(const char *query, uint32_t length) {
598 // by default, do nothing...
599 return true;
600 }
601
fetchFromBindCursor()602 bool sqlrservercursor::fetchFromBindCursor() {
603 // by default, do nothing...
604 return true;
605 }
606
nextResultSet(bool * nextresultsetavailable)607 bool sqlrservercursor::nextResultSet(bool *nextresultsetavailable) {
608 // by default, a next result set is not available
609 *nextresultsetavailable = false;
610 return true;
611 }
612
queryIsNotSelect()613 bool sqlrservercursor::queryIsNotSelect() {
614
615 // scan the query, bypassing whitespace and comments.
616 const char *ptr=
617 conn->cont->skipWhitespaceAndComments(pvt->_querybuffer);
618
619 // if the query is a select but not a select into then return false,
620 // otherwise return true
621 if (!charstring::compareIgnoringCase(ptr,"select",6) &&
622 charstring::compareIgnoringCase(ptr,"select into ",12)) {
623 return false;
624 }
625 return true;
626 }
627
queryIsCommitOrRollback()628 bool sqlrservercursor::queryIsCommitOrRollback() {
629
630 // scan the query, bypassing whitespace and comments.
631 const char *ptr=
632 conn->cont->skipWhitespaceAndComments(pvt->_querybuffer);
633
634 // if the query is a commit or rollback, return true
635 // otherwise return false
636 return (!charstring::compareIgnoringCase(ptr,"commit",6) ||
637 !charstring::compareIgnoringCase(ptr,"rollback",8));
638 }
639
errorMessage(char * errorbuffer,uint32_t errorbuffersize,uint32_t * errorlength,int64_t * errorcode,bool * liveconnection)640 void sqlrservercursor::errorMessage(char *errorbuffer,
641 uint32_t errorbuffersize,
642 uint32_t *errorlength,
643 int64_t *errorcode,
644 bool *liveconnection) {
645
646 // if the cursor happens to have an error, then return that
647 if (pvt->_errorlength) {
648 charstring::safeCopy(errorbuffer,errorbuffersize,
649 pvt->_error,pvt->_errorlength);
650 *errorlength=pvt->_errorlength;
651 if (*errorlength>errorbuffersize) {
652 *errorlength=errorbuffersize;
653 }
654 *errorcode=pvt->_errnum;
655 *liveconnection=pvt->_liveconnection;
656 }
657
658 // otherwise return the connection's error
659 conn->errorMessage(errorbuffer,errorbuffersize,
660 errorlength,errorcode,liveconnection);
661 }
662
knowsRowCount()663 bool sqlrservercursor::knowsRowCount() {
664 return false;
665 }
666
rowCount()667 uint64_t sqlrservercursor::rowCount() {
668 return 0;
669 }
670
knowsAffectedRows()671 bool sqlrservercursor::knowsAffectedRows() {
672 return true;
673 }
674
affectedRows()675 uint64_t sqlrservercursor::affectedRows() {
676 return 0;
677 }
678
colCount()679 uint32_t sqlrservercursor::colCount() {
680 return 0;
681 }
682
columnTypeFormat()683 uint16_t sqlrservercursor::columnTypeFormat() {
684 return (uint16_t)COLUMN_TYPE_IDS;
685 }
686
getColumnName(uint32_t col)687 const char *sqlrservercursor::getColumnName(uint32_t col) {
688 return NULL;
689 }
690
getColumnNameLength(uint32_t col)691 uint16_t sqlrservercursor::getColumnNameLength(uint32_t col) {
692 return charstring::length(getColumnName(col));
693 }
694
getColumnType(uint32_t col)695 uint16_t sqlrservercursor::getColumnType(uint32_t col) {
696 return UNKNOWN_DATATYPE;
697 }
698
getColumnTypeName(uint32_t col)699 const char *sqlrservercursor::getColumnTypeName(uint32_t col) {
700 return datatypestring[getColumnType(col)];
701 }
702
getColumnTypeNameLength(uint32_t col)703 uint16_t sqlrservercursor::getColumnTypeNameLength(uint32_t col) {
704 return charstring::length(getColumnTypeName(col));
705 }
706
getColumnLength(uint32_t col)707 uint32_t sqlrservercursor::getColumnLength(uint32_t col) {
708 return 0;
709 }
710
getColumnPrecision(uint32_t col)711 uint32_t sqlrservercursor::getColumnPrecision(uint32_t col) {
712 return 0;
713 }
714
getColumnScale(uint32_t col)715 uint32_t sqlrservercursor::getColumnScale(uint32_t col) {
716 return 0;
717 }
718
getColumnIsNullable(uint32_t col)719 uint16_t sqlrservercursor::getColumnIsNullable(uint32_t col) {
720 return 0;
721 }
722
getColumnIsPrimaryKey(uint32_t col)723 uint16_t sqlrservercursor::getColumnIsPrimaryKey(uint32_t col) {
724 return 0;
725 }
726
getColumnIsUnique(uint32_t col)727 uint16_t sqlrservercursor::getColumnIsUnique(uint32_t col) {
728 return 0;
729 }
730
getColumnIsPartOfKey(uint32_t col)731 uint16_t sqlrservercursor::getColumnIsPartOfKey(uint32_t col) {
732 return 0;
733 }
734
getColumnIsUnsigned(uint32_t col)735 uint16_t sqlrservercursor::getColumnIsUnsigned(uint32_t col) {
736 return 0;
737 }
738
getColumnIsZeroFilled(uint32_t col)739 uint16_t sqlrservercursor::getColumnIsZeroFilled(uint32_t col) {
740 return 0;
741 }
742
getColumnIsBinary(uint32_t col)743 uint16_t sqlrservercursor::getColumnIsBinary(uint32_t col) {
744 return 0;
745 }
746
getColumnIsAutoIncrement(uint32_t col)747 uint16_t sqlrservercursor::getColumnIsAutoIncrement(uint32_t col) {
748 return 0;
749 }
750
getColumnTable(uint32_t col)751 const char *sqlrservercursor::getColumnTable(uint32_t col) {
752 return NULL;
753 }
754
getColumnTableLength(uint32_t col)755 uint16_t sqlrservercursor::getColumnTableLength(uint32_t col) {
756 return charstring::length(getColumnTable(col));
757 }
758
ignoreDateDdMmParameter(uint32_t col,const char * data,uint32_t size)759 bool sqlrservercursor::ignoreDateDdMmParameter(uint32_t col,
760 const char *data, uint32_t size) {
761 return false;
762 }
763
noRowsToReturn()764 bool sqlrservercursor::noRowsToReturn() {
765 return true;
766 }
767
skipRow(bool * error)768 bool sqlrservercursor::skipRow(bool *error) {
769 return fetchRow(error);
770 }
771
fetchRow(bool * error)772 bool sqlrservercursor::fetchRow(bool *error) {
773 *error=false;
774 // by default, indicate that we are at the end of the result set
775 return false;
776 }
777
nextRow()778 void sqlrservercursor::nextRow() {
779 // by default, do nothing
780 }
781
getField(uint32_t col,const char ** field,uint64_t * fieldlength,bool * blob,bool * null)782 void sqlrservercursor::getField(uint32_t col,
783 const char **field, uint64_t *fieldlength,
784 bool *blob, bool *null) {
785 // by default, do nothing
786 *field=NULL;
787 *fieldlength=0;
788 *blob=false;
789 *null=false;
790 }
791
getLobFieldLength(uint32_t col,uint64_t * length)792 bool sqlrservercursor::getLobFieldLength(uint32_t col, uint64_t *length) {
793 *length=0;
794 return true;
795 }
796
getLobFieldSegment(uint32_t col,char * buffer,uint64_t buffersize,uint64_t offset,uint64_t charstoread,uint64_t * charsread)797 bool sqlrservercursor::getLobFieldSegment(uint32_t col,
798 char *buffer, uint64_t buffersize,
799 uint64_t offset, uint64_t charstoread,
800 uint64_t *charsread) {
801 *charsread=0;
802 return false;
803 }
804
closeLobField(uint32_t col)805 void sqlrservercursor::closeLobField(uint32_t col) {
806 // by default, do nothing
807 }
808
closeResultSet()809 void sqlrservercursor::closeResultSet() {
810 // by default, do nothing...
811 return;
812 }
813
getId()814 uint16_t sqlrservercursor::getId() {
815 return pvt->_id;
816 }
817
fakeInputBinds()818 bool sqlrservercursor::fakeInputBinds() {
819
820 // return false if there aren't any input binds
821 if (!pvt->_inbindcount) {
822 return false;
823 }
824
825 // re-init the buffer
826 pvt->_querywithfakeinputbinds.clear();
827
828 // loop through the query, performing substitutions
829 queryparsestate_t parsestate=IN_QUERY;
830
831 // use 1-based index for bind variables
832 int64_t bindindex=1;
833
834 // run through the querybuffer...
835 char *ptr=pvt->_querybuffer;
836 const char *endptr=pvt->_querybuffer+pvt->_querylength;
837 char prev='\0';
838 do {
839
840 // if we're in the query...
841 if (parsestate==IN_QUERY) {
842
843 // if we find a quote, we're in quotes
844 if (*ptr=='\'') {
845 parsestate=IN_QUOTES;
846 }
847
848 // if we find whitespace or a couple of other things
849 // then the next thing could be a bind variable
850 if (beforeBindVariable(ptr)) {
851 parsestate=BEFORE_BIND;
852 }
853
854 // append the character
855 pvt->_querywithfakeinputbinds.append(*ptr);
856
857 // move on
858 if (*ptr=='\\' && prev=='\\') {
859 prev='\0';
860 } else {
861 prev=*ptr;
862 }
863 ptr++;
864 continue;
865 }
866
867 // copy anything in quotes verbatim
868 if (parsestate==IN_QUOTES) {
869
870 // if we find a quote, but not an escaped quote,
871 // then we're back in the query
872 // (or we're in between one of these: '...''...'
873 // which is functionally the same)
874 if (*ptr=='\'' && prev!='\\') {
875 parsestate=IN_QUERY;
876 }
877
878 // append the character
879 pvt->_querywithfakeinputbinds.append(*ptr);
880
881 // move on
882 if (*ptr=='\\' && prev=='\\') {
883 prev='\0';
884 } else {
885 prev=*ptr;
886 }
887 ptr++;
888 continue;
889 }
890
891 if (parsestate==BEFORE_BIND) {
892
893 // if we find a bind variable...
894 if (isBindDelimiter(ptr,
895 conn->cont->getConfig()->
896 getBindVariableDelimiterQuestionMarkSupported(),
897 conn->cont->getConfig()->
898 getBindVariableDelimiterColonSupported(),
899 conn->cont->getConfig()->
900 getBindVariableDelimiterAtSignSupported(),
901 conn->cont->getConfig()->
902 getBindVariableDelimiterDollarSignSupported())
903 ) {
904 parsestate=IN_BIND;
905 continue;
906 }
907
908 // if we didn't find a bind variable then we're just
909 // back in the query
910 parsestate=IN_QUERY;
911 continue;
912 }
913
914 // if we're in a bind variable...
915 if (parsestate==IN_BIND) {
916
917 // look through the list of vars
918 for (int16_t i=0; i<pvt->_inbindcount; i++) {
919
920 // if we find a match, perform the substitution
921 // and skip past the variable...
922 //
923 // for bind-by-name cases, we need to check
924 // after the variable for whitespace, a comma,
925 // a semicolon, or a right parenthesis to make
926 // sure that we don't make the following
927 // mistake:
928 //
929 // select :var1,:var15 from mytable
930 //
931 // :var1=3
932 // :var15=2
933 //
934 // correct:
935 // select 3,2 from mytable
936 //
937 // mistake:
938 // select 3,35 from mytable
939 if (
940 (*ptr=='?' &&
941 charstring::toInteger(
942 pvt->_inbindvars[i].
943 variable+1)==bindindex)
944
945 ||
946
947 (!charstring::compare(ptr+1,
948 pvt->_inbindvars[i].
949 variable+1,
950 pvt->_inbindvars[i].
951 variablesize-1)
952 &&
953 (afterBindVariable(
954 ptr+pvt->_inbindvars[i].
955 variablesize) ||
956 ptr+1+pvt->_inbindvars[i].
957 variablesize-1==endptr))) {
958
959 performSubstitution(
960 &(pvt->_querywithfakeinputbinds),i);
961 if (*ptr=='?') {
962 ptr++;
963 } else {
964 ptr=ptr+pvt->_inbindvars[i].
965 variablesize;
966 }
967 bindindex++;
968 break;
969 }
970 }
971
972 parsestate=IN_QUERY;
973 continue;
974 }
975
976 } while (ptr<endptr);
977
978 return true;
979 }
980
performSubstitution(stringbuffer * buffer,int16_t index)981 void sqlrservercursor::performSubstitution(stringbuffer *buffer,
982 int16_t index) {
983
984 if (pvt->_inbindvars[index].type==SQLRSERVERBINDVARTYPE_STRING ||
985 pvt->_inbindvars[index].type==SQLRSERVERBINDVARTYPE_CLOB) {
986
987 if (conn->cont->getConfig()->
988 getFakeInputBindVariablesUnicodeStrings()) {
989 buffer->append('N');
990 }
991
992 buffer->append('\'');
993
994 size_t length=pvt->_inbindvars[index].valuesize;
995
996 for (size_t ind=0; ind<length; ind++) {
997
998 char ch=pvt->_inbindvars[index].value.stringval[ind];
999
1000 // escape quotes and NULL's
1001 if (ch=='\'') {
1002 buffer->append('\'');
1003 } else if (ch=='\0') {
1004 // FIXME: I assume this is how NULL's should
1005 // be escaped, but I'm not really sure for
1006 // all db's...
1007 buffer->append("\\0");
1008 }
1009 buffer->append(ch);
1010 }
1011
1012 buffer->append('\'');
1013
1014 } else if (pvt->_inbindvars[index].type==
1015 SQLRSERVERBINDVARTYPE_BLOB) {
1016 encodeBlob(buffer,pvt->_inbindvars[index].value.stringval,
1017 pvt->_inbindvars[index].valuesize);
1018 } else if (pvt->_inbindvars[index].type==
1019 SQLRSERVERBINDVARTYPE_INTEGER) {
1020 buffer->append(pvt->_inbindvars[index].
1021 value.integerval);
1022 } else if (pvt->_inbindvars[index].type==
1023 SQLRSERVERBINDVARTYPE_DOUBLE) {
1024 char *dbuf=NULL;
1025 if (!pvt->_inbindvars[index].
1026 value.doubleval.precision &&
1027 !pvt->_inbindvars[index].
1028 value.doubleval.scale) {
1029 dbuf=charstring::parseNumber(
1030 pvt->_inbindvars[index].
1031 value.doubleval.value);
1032 } else {
1033 dbuf=charstring::parseNumber(
1034 pvt->_inbindvars[index].
1035 value.doubleval.value,
1036 pvt->_inbindvars[index].
1037 value.doubleval.precision,
1038 pvt->_inbindvars[index].
1039 value.doubleval.scale);
1040 }
1041 // In some regions a comma is used rather than a period for
1042 // the decimal and the i8n settings will cause the vsnprintf
1043 // that ultimately gets called by charstring::parseNumber above
1044 // to use a comma as the separator. Databases don't like
1045 // commas in their numbers. Convert commas to periods here.
1046 for (char *ptr=dbuf; *ptr; ptr++) {
1047 if (*ptr==',') {
1048 *ptr='.';
1049 }
1050 }
1051 buffer->append(dbuf);
1052 delete[] dbuf;
1053 } else if (pvt->_inbindvars[index].type==
1054 SQLRSERVERBINDVARTYPE_DATE) {
1055 char buf[64];
1056 dateToString(buf,sizeof(buf),
1057 pvt->_inbindvars[index].value.dateval.year,
1058 pvt->_inbindvars[index].value.dateval.month,
1059 pvt->_inbindvars[index].value.dateval.day,
1060 pvt->_inbindvars[index].value.dateval.hour,
1061 pvt->_inbindvars[index].value.dateval.minute,
1062 pvt->_inbindvars[index].value.dateval.second,
1063 pvt->_inbindvars[index].value.dateval.microsecond,
1064 pvt->_inbindvars[index].value.dateval.tz,
1065 pvt->_inbindvars[index].value.dateval.isnegative);
1066 buffer->append("'")->append(buf)->append("'");
1067 } else if (pvt->_inbindvars[index].type==
1068 SQLRSERVERBINDVARTYPE_NULL) {
1069 buffer->append("NULL");
1070 }
1071 }
1072
encodeBlob(stringbuffer * buffer,const char * data,uint32_t datasize)1073 void sqlrservercursor::encodeBlob(stringbuffer *buffer,
1074 const char *data, uint32_t datasize) {
1075
1076 // by default, follow the SQL Standard:
1077 // X'...' where ... is the blob data and each byte of blob data is
1078 // converted to two hex characters..
1079 // eg: hello -> X'68656C6C6F'
1080
1081 buffer->append("X\'");
1082 for (uint32_t i=0; i<datasize; i++) {
1083 buffer->append(conn->cont->asciiToHex(data[i]));
1084 }
1085 buffer->append('\'');
1086 }
1087
getBindPool()1088 memorypool *sqlrservercursor::getBindPool() {
1089 return &pvt->_bindpool;
1090 }
1091
getBindMappings()1092 namevaluepairs *sqlrservercursor::getBindMappings() {
1093 return pvt->_bindmappings;
1094 }
1095
getBindMappingsPool()1096 memorypool *sqlrservercursor::getBindMappingsPool() {
1097 return &pvt->_bindmappingspool;
1098 }
1099
setInputBindCount(uint16_t inbindcount)1100 void sqlrservercursor::setInputBindCount(uint16_t inbindcount) {
1101 pvt->_inbindcount=inbindcount;
1102 }
1103
getInputBindCount()1104 uint16_t sqlrservercursor::getInputBindCount() {
1105 return pvt->_inbindcount;
1106 }
1107
getInputBinds()1108 sqlrserverbindvar *sqlrservercursor::getInputBinds() {
1109 return pvt->_inbindvars;
1110 }
1111
setOutputBindCount(uint16_t outbindcount)1112 void sqlrservercursor::setOutputBindCount(uint16_t outbindcount) {
1113 pvt->_outbindcount=outbindcount;
1114 }
1115
getOutputBindCount()1116 uint16_t sqlrservercursor::getOutputBindCount() {
1117 return pvt->_outbindcount;
1118 }
1119
getOutputBinds()1120 sqlrserverbindvar *sqlrservercursor::getOutputBinds() {
1121 return pvt->_outbindvars;
1122 }
1123
setInputOutputBindCount(uint16_t inoutbindcount)1124 void sqlrservercursor::setInputOutputBindCount(uint16_t inoutbindcount) {
1125 pvt->_inoutbindcount=inoutbindcount;
1126 }
1127
getInputOutputBindCount()1128 uint16_t sqlrservercursor::getInputOutputBindCount() {
1129 return pvt->_inoutbindcount;
1130 }
1131
getInputOutputBinds()1132 sqlrserverbindvar *sqlrservercursor::getInputOutputBinds() {
1133 return pvt->_inoutbindvars;
1134 }
1135
abort()1136 void sqlrservercursor::abort() {
1137 // I was once concerned that calling this here would prevent suspended
1138 // result sets from being able to return column data upon resume if the
1139 // entire result set had already been sent, but I don't think that's an
1140 // issue any more.
1141 closeResultSet();
1142 setState(SQLRCURSORSTATE_AVAILABLE);
1143 clearCustomQueryCursor();
1144 }
1145
getQueryBuffer()1146 char *sqlrservercursor::getQueryBuffer() {
1147 return pvt->_querybuffer;
1148 }
1149
getQueryLength()1150 uint32_t sqlrservercursor::getQueryLength() {
1151 return pvt->_querylength;
1152 }
1153
setQueryLength(uint32_t querylength)1154 void sqlrservercursor::setQueryLength(uint32_t querylength) {
1155 pvt->_querylength=querylength;
1156 }
1157
setQueryStatus(sqlrquerystatus_t status)1158 void sqlrservercursor::setQueryStatus(sqlrquerystatus_t status) {
1159 pvt->_querystatus=status;
1160 }
1161
getQueryStatus()1162 sqlrquerystatus_t sqlrservercursor::getQueryStatus() {
1163 return pvt->_querystatus;
1164 }
1165
setQueryTree(xmldom * tree)1166 void sqlrservercursor::setQueryTree(xmldom *tree) {
1167 pvt->_querytree=tree;
1168 }
1169
getQueryTree()1170 xmldom *sqlrservercursor::getQueryTree() {
1171 return pvt->_querytree;
1172 }
1173
clearQueryTree()1174 void sqlrservercursor::clearQueryTree() {
1175 delete pvt->_querytree;
1176 pvt->_querytree=NULL;
1177 }
1178
getTranslatedQueryBuffer()1179 stringbuffer *sqlrservercursor::getTranslatedQueryBuffer() {
1180 return &(pvt->_translatedquery);
1181 }
1182
setCommandStart(uint64_t sec,uint64_t usec)1183 void sqlrservercursor::setCommandStart(uint64_t sec, uint64_t usec) {
1184 pvt->_commandstartsec=sec;
1185 pvt->_commandstartusec=usec;
1186 }
1187
getCommandStartSec()1188 uint64_t sqlrservercursor::getCommandStartSec() {
1189 return pvt->_commandstartsec;
1190 }
1191
getCommandStartUSec()1192 uint64_t sqlrservercursor::getCommandStartUSec() {
1193 return pvt->_commandstartusec;
1194 }
1195
1196
setCommandEnd(uint64_t sec,uint64_t usec)1197 void sqlrservercursor::setCommandEnd(uint64_t sec, uint64_t usec) {
1198 pvt->_commandendsec=sec;
1199 pvt->_commandendusec=usec;
1200 }
1201
getCommandEndSec()1202 uint64_t sqlrservercursor::getCommandEndSec() {
1203 return pvt->_commandendsec;
1204 }
1205
getCommandEndUSec()1206 uint64_t sqlrservercursor::getCommandEndUSec() {
1207 return pvt->_commandendusec;
1208 }
1209
1210
setQueryStart(uint64_t sec,uint64_t usec)1211 void sqlrservercursor::setQueryStart(uint64_t sec, uint64_t usec) {
1212 pvt->_querystartsec=sec;
1213 pvt->_querystartusec=usec;
1214 }
1215
getQueryStartSec()1216 uint64_t sqlrservercursor::getQueryStartSec() {
1217 return pvt->_querystartsec;
1218 }
1219
getQueryStartUSec()1220 uint64_t sqlrservercursor::getQueryStartUSec() {
1221 return pvt->_querystartusec;
1222 }
1223
1224
setQueryEnd(uint64_t sec,uint64_t usec)1225 void sqlrservercursor::setQueryEnd(uint64_t sec, uint64_t usec) {
1226 pvt->_queryendsec=sec;
1227 pvt->_queryendusec=usec;
1228 }
1229
getQueryEndSec()1230 uint64_t sqlrservercursor::getQueryEndSec() {
1231 return pvt->_queryendsec;
1232 }
1233
getQueryEndUSec()1234 uint64_t sqlrservercursor::getQueryEndUSec() {
1235 return pvt->_queryendusec;
1236 }
1237
setFetchStart(uint64_t sec,uint64_t usec)1238 void sqlrservercursor::setFetchStart(uint64_t sec, uint64_t usec) {
1239 pvt->_fetchstartsec=sec;
1240 pvt->_fetchstartusec=usec;
1241 }
1242
getFetchStartSec()1243 uint64_t sqlrservercursor::getFetchStartSec() {
1244 return pvt->_fetchstartsec;
1245 }
1246
getFetchStartUSec()1247 uint64_t sqlrservercursor::getFetchStartUSec() {
1248 return pvt->_fetchstartusec;
1249 }
1250
1251
setFetchEnd(uint64_t sec,uint64_t usec)1252 void sqlrservercursor::setFetchEnd(uint64_t sec, uint64_t usec) {
1253 pvt->_fetchendsec=sec;
1254 pvt->_fetchendusec=usec;
1255 }
1256
getFetchEndSec()1257 uint64_t sqlrservercursor::getFetchEndSec() {
1258 return pvt->_fetchendsec;
1259 }
1260
getFetchEndUSec()1261 uint64_t sqlrservercursor::getFetchEndUSec() {
1262 return pvt->_fetchendusec;
1263 }
1264
resetFetchTime()1265 void sqlrservercursor::resetFetchTime() {
1266 pvt->_fetchusec=0;
1267 }
1268
tallyFetchTime()1269 void sqlrservercursor::tallyFetchTime() {
1270 pvt->_fetchusec+=((pvt->_fetchendsec-pvt->_fetchstartsec)*1000000)+
1271 pvt->_fetchendusec-pvt->_fetchstartusec;
1272 }
1273
getFetchUSec()1274 uint64_t sqlrservercursor::getFetchUSec() {
1275 return pvt->_fetchusec;
1276 }
1277
setState(sqlrcursorstate_t state)1278 void sqlrservercursor::setState(sqlrcursorstate_t state) {
1279 pvt->_state=state;
1280 }
1281
getState()1282 sqlrcursorstate_t sqlrservercursor::getState() {
1283 return pvt->_state;
1284 }
1285
setCustomQueryCursor(sqlrquerycursor * cur)1286 void sqlrservercursor::setCustomQueryCursor(sqlrquerycursor *cur) {
1287 pvt->_customquerycursor=cur;
1288 }
1289
getCustomQueryCursor()1290 sqlrquerycursor *sqlrservercursor::getCustomQueryCursor() {
1291 return pvt->_customquerycursor;
1292 }
1293
clearCustomQueryCursor()1294 void sqlrservercursor::clearCustomQueryCursor() {
1295 delete pvt->_customquerycursor;
1296 pvt->_customquerycursor=NULL;
1297 }
1298
clearTotalRowsFetched()1299 void sqlrservercursor::clearTotalRowsFetched() {
1300 pvt->_totalrowsfetched=0;
1301 }
1302
getTotalRowsFetched()1303 uint64_t sqlrservercursor::getTotalRowsFetched() {
1304 return pvt->_totalrowsfetched;
1305 }
1306
incrementTotalRowsFetched()1307 void sqlrservercursor::incrementTotalRowsFetched() {
1308 pvt->_totalrowsfetched++;
1309 }
1310
setCurrentRowReformatted(bool crr)1311 void sqlrservercursor::setCurrentRowReformatted(bool crr) {
1312 pvt->_currentrowreformatted=crr;
1313 }
1314
getCurrentRowReformatted()1315 bool sqlrservercursor::getCurrentRowReformatted() {
1316 return pvt->_currentrowreformatted;
1317 }
1318
getErrorBuffer()1319 char *sqlrservercursor::getErrorBuffer() {
1320 return pvt->_error;
1321 }
1322
getErrorLength()1323 uint32_t sqlrservercursor::getErrorLength() {
1324 return pvt->_errorlength;
1325 }
1326
setErrorLength(uint32_t errorlength)1327 void sqlrservercursor::setErrorLength(uint32_t errorlength) {
1328 pvt->_errorlength=errorlength;
1329 }
1330
getErrorNumber()1331 uint32_t sqlrservercursor::getErrorNumber() {
1332 return pvt->_errnum;
1333 }
1334
setErrorNumber(uint32_t errnum)1335 void sqlrservercursor::setErrorNumber(uint32_t errnum) {
1336 pvt->_errnum=errnum;
1337 }
1338
getLiveConnection()1339 bool sqlrservercursor::getLiveConnection() {
1340 return pvt->_liveconnection;
1341 }
1342
setLiveConnection(bool liveconnection)1343 void sqlrservercursor::setLiveConnection(bool liveconnection) {
1344 pvt->_liveconnection=liveconnection;
1345 }
1346
setCreateTempTablePattern(const char * createtemp)1347 void sqlrservercursor::setCreateTempTablePattern(const char *createtemp) {
1348 pvt->_createtemp.setPattern(createtemp);
1349 pvt->_createtemp.study();
1350 }
1351
skipCreateTempTableClause(const char * query)1352 const char *sqlrservercursor::skipCreateTempTableClause(const char *query) {
1353 const char *ptr=conn->cont->skipWhitespaceAndComments(query);
1354 if (!charstring::isNullOrEmpty(ptr) && pvt->_createtemp.match(ptr)) {
1355 return pvt->_createtemp.getSubstringEnd(0);
1356 }
1357 return NULL;
1358 }
1359
columnInfoIsValidAfterPrepare()1360 bool sqlrservercursor::columnInfoIsValidAfterPrepare() {
1361 return false;
1362 }
1363
setColumnInfoIsValid(bool valid)1364 void sqlrservercursor::setColumnInfoIsValid(bool valid) {
1365 pvt->_columninfoisvalid=valid;
1366 }
1367
getColumnInfoIsValid()1368 bool sqlrservercursor::getColumnInfoIsValid() {
1369 return pvt->_columninfoisvalid;
1370 }
1371
setQueryHasBeenPreProcessed(bool preprocessed)1372 void sqlrservercursor::setQueryHasBeenPreProcessed(bool preprocessed) {
1373 pvt->_queryhasbeenpreprocessed=preprocessed;
1374 }
1375
getQueryHasBeenPreProcessed()1376 bool sqlrservercursor::getQueryHasBeenPreProcessed() {
1377 return pvt->_queryhasbeenpreprocessed;
1378 }
1379
setQueryHasBeenPrepared(bool prepared)1380 void sqlrservercursor::setQueryHasBeenPrepared(bool prepared) {
1381 pvt->_queryhasbeenprepared=prepared;
1382 }
1383
getQueryHasBeenPrepared()1384 bool sqlrservercursor::getQueryHasBeenPrepared() {
1385 return pvt->_queryhasbeenprepared;
1386 }
1387
setQueryHasBeenExecuted(bool executed)1388 void sqlrservercursor::setQueryHasBeenExecuted(bool executed) {
1389 pvt->_queryhasbeenexecuted=executed;
1390 }
1391
getQueryHasBeenExecuted()1392 bool sqlrservercursor::getQueryHasBeenExecuted() {
1393 return pvt->_queryhasbeenexecuted;
1394 }
1395
setQueryNeedsIntercept(bool intercept)1396 void sqlrservercursor::setQueryNeedsIntercept(bool intercept) {
1397 pvt->_queryneedsintercept=intercept;
1398 }
1399
getQueryNeedsIntercept()1400 bool sqlrservercursor::getQueryNeedsIntercept() {
1401 return pvt->_queryneedsintercept;
1402 }
1403
setQueryWasIntercepted(bool intercepted)1404 void sqlrservercursor::setQueryWasIntercepted(bool intercepted) {
1405 pvt->_querywasintercepted=intercepted;
1406 }
1407
getQueryWasIntercepted()1408 bool sqlrservercursor::getQueryWasIntercepted() {
1409 return pvt->_querywasintercepted;
1410 }
1411
setBindsWereFaked(bool faked)1412 void sqlrservercursor::setBindsWereFaked(bool faked) {
1413 pvt->_bindswerefaked=faked;
1414 }
1415
getBindsWereFaked()1416 bool sqlrservercursor::getBindsWereFaked() {
1417 return pvt->_bindswerefaked;
1418 }
1419
setFakeInputBindsForThisQuery(bool fake)1420 void sqlrservercursor::setFakeInputBindsForThisQuery(bool fake) {
1421 pvt->_fakeinputbindsforthisquery=fake;
1422 }
1423
getFakeInputBindsForThisQuery()1424 bool sqlrservercursor::getFakeInputBindsForThisQuery() {
1425 return pvt->_fakeinputbindsforthisquery;
1426 }
1427
setQueryType(sqlrquerytype_t querytype)1428 void sqlrservercursor::setQueryType(sqlrquerytype_t querytype) {
1429 pvt->_querytype=querytype;
1430 }
1431
getQueryType()1432 sqlrquerytype_t sqlrservercursor::getQueryType() {
1433 return pvt->_querytype;
1434 }
1435
getQueryWithFakeInputBindsBuffer()1436 stringbuffer *sqlrservercursor::getQueryWithFakeInputBindsBuffer() {
1437 return &(pvt->_querywithfakeinputbinds);
1438 }
1439
allocateColumnPointers(uint32_t colcount)1440 void sqlrservercursor::allocateColumnPointers(uint32_t colcount) {
1441 pvt->_columnnames=new const char *[colcount];
1442 pvt->_columnnamelengths=new uint16_t[colcount];
1443 pvt->_columntypes=new uint16_t[colcount];
1444 pvt->_columntypenames=new const char *[colcount];
1445 pvt->_columntypenamelengths=new uint16_t[colcount];
1446 pvt->_columnlengths=new uint32_t[colcount];
1447 pvt->_columnprecisions=new uint32_t[colcount];
1448 pvt->_columnscales=new uint32_t[colcount];
1449 pvt->_columnisnullables=new uint16_t[colcount];
1450 pvt->_columnisprimarykeys=new uint16_t[colcount];
1451 pvt->_columnisuniques=new uint16_t[colcount];
1452 pvt->_columnispartofkeys=new uint16_t[colcount];
1453 pvt->_columnisunsigneds=new uint16_t[colcount];
1454 pvt->_columniszerofilleds=new uint16_t[colcount];
1455 pvt->_columnisbinarys=new uint16_t[colcount];
1456 pvt->_columnisautoincrements=new uint16_t[colcount];
1457 pvt->_columntables=new const char *[colcount];
1458 pvt->_columntablelengths=new uint16_t[colcount];
1459 }
1460
deallocateColumnPointers()1461 void sqlrservercursor::deallocateColumnPointers() {
1462 delete[] pvt->_columnnames;
1463 delete[] pvt->_columnnamelengths;
1464 delete[] pvt->_columntypes;
1465 delete[] pvt->_columntypenames;
1466 delete[] pvt->_columntypenamelengths;
1467 delete[] pvt->_columnlengths;
1468 delete[] pvt->_columnprecisions;
1469 delete[] pvt->_columnscales;
1470 delete[] pvt->_columnisnullables;
1471 delete[] pvt->_columnisprimarykeys;
1472 delete[] pvt->_columnisuniques;
1473 delete[] pvt->_columnispartofkeys;
1474 delete[] pvt->_columnisunsigneds;
1475 delete[] pvt->_columniszerofilleds;
1476 delete[] pvt->_columnisbinarys;
1477 delete[] pvt->_columnisautoincrements;
1478 delete[] pvt->_columntables;
1479 delete[] pvt->_columntablelengths;
1480 }
1481
getColumnPointers(const char *** columnnames,uint16_t ** columnnamelengths,uint16_t ** columntypes,const char *** columntypenames,uint16_t ** columntypenamelengths,uint32_t ** columnlengths,uint32_t ** columnprecisions,uint32_t ** columnscales,uint16_t ** columnisnullables,uint16_t ** columnisprimarykeys,uint16_t ** columnisuniques,uint16_t ** columnispartofkeys,uint16_t ** columnisunsigneds,uint16_t ** columniszerofilleds,uint16_t ** columnisbinarys,uint16_t ** columnisautoincrements,const char *** columntables,uint16_t ** columntablelengths)1482 void sqlrservercursor::getColumnPointers(const char ***columnnames,
1483 uint16_t **columnnamelengths,
1484 uint16_t **columntypes,
1485 const char ***columntypenames,
1486 uint16_t **columntypenamelengths,
1487 uint32_t **columnlengths,
1488 uint32_t **columnprecisions,
1489 uint32_t **columnscales,
1490 uint16_t **columnisnullables,
1491 uint16_t **columnisprimarykeys,
1492 uint16_t **columnisuniques,
1493 uint16_t **columnispartofkeys,
1494 uint16_t **columnisunsigneds,
1495 uint16_t **columniszerofilleds,
1496 uint16_t **columnisbinarys,
1497 uint16_t **columnisautoincrements,
1498 const char ***columntables,
1499 uint16_t **columntablelengths) {
1500
1501 // get the max column count
1502 uint32_t colcount=conn->cont->getMaxColumnCount();
1503
1504 // decide if we need to allocate field pointers here,
1505 // and if so, how many columns
1506 bool allocate=false;
1507 if (!colcount) {
1508 colcount=colCount();
1509 allocate=true;
1510 }
1511
1512 // allocate the field pointers, if necessary
1513 if (allocate) {
1514 deallocateColumnPointers();
1515 allocateColumnPointers(colcount);
1516 }
1517
1518 // return the column pointers
1519 *columnnames=pvt->_columnnames;
1520 *columnnamelengths=pvt->_columnnamelengths;
1521 *columntypes=pvt->_columntypes;
1522 *columntypenames=pvt->_columntypenames;
1523 *columntypenamelengths=pvt->_columntypenamelengths;
1524 *columnlengths=pvt->_columnlengths;
1525 *columnprecisions=pvt->_columnprecisions;
1526 *columnscales=pvt->_columnscales;
1527 *columnisnullables=pvt->_columnisnullables;
1528 *columnisprimarykeys=pvt->_columnisprimarykeys;
1529 *columnisuniques=pvt->_columnisuniques;
1530 *columnispartofkeys=pvt->_columnispartofkeys;
1531 *columnisunsigneds=pvt->_columnisunsigneds;
1532 *columniszerofilleds=pvt->_columniszerofilleds;
1533 *columnisbinarys=pvt->_columnisbinarys;
1534 *columnisautoincrements=pvt->_columnisautoincrements;
1535 *columntables=pvt->_columntables;
1536 *columntablelengths=pvt->_columntablelengths;
1537 }
1538
getColumnNameFromBuffer(uint32_t col)1539 const char *sqlrservercursor::getColumnNameFromBuffer(uint32_t col) {
1540 return pvt->_columnnames[col];
1541 }
1542
getColumnNameLengthFromBuffer(uint32_t col)1543 uint16_t sqlrservercursor::getColumnNameLengthFromBuffer(uint32_t col) {
1544 return pvt->_columnnamelengths[col];
1545 }
1546
getColumnTypeFromBuffer(uint32_t col)1547 uint16_t sqlrservercursor::getColumnTypeFromBuffer(uint32_t col) {
1548 return pvt->_columntypes[col];
1549 }
1550
getColumnTypeNameFromBuffer(uint32_t col)1551 const char *sqlrservercursor::getColumnTypeNameFromBuffer(uint32_t col) {
1552 return pvt->_columntypenames[col];
1553 }
1554
getColumnTypeNameLengthFromBuffer(uint32_t col)1555 uint16_t sqlrservercursor::getColumnTypeNameLengthFromBuffer(uint32_t col) {
1556 return pvt->_columntypenamelengths[col];
1557 }
1558
getColumnLengthFromBuffer(uint32_t col)1559 uint32_t sqlrservercursor::getColumnLengthFromBuffer(uint32_t col) {
1560 return pvt->_columnlengths[col];
1561 }
1562
getColumnPrecisionFromBuffer(uint32_t col)1563 uint32_t sqlrservercursor::getColumnPrecisionFromBuffer(uint32_t col) {
1564 return pvt->_columnprecisions[col];
1565 }
1566
getColumnScaleFromBuffer(uint32_t col)1567 uint32_t sqlrservercursor::getColumnScaleFromBuffer(uint32_t col) {
1568 return pvt->_columnscales[col];
1569 }
1570
getColumnIsNullableFromBuffer(uint32_t col)1571 uint16_t sqlrservercursor::getColumnIsNullableFromBuffer(uint32_t col) {
1572 return pvt->_columnisnullables[col];
1573 }
1574
getColumnIsPrimaryKeyFromBuffer(uint32_t col)1575 uint16_t sqlrservercursor::getColumnIsPrimaryKeyFromBuffer(uint32_t col) {
1576 return pvt->_columnisprimarykeys[col];
1577 }
1578
getColumnIsUniqueFromBuffer(uint32_t col)1579 uint16_t sqlrservercursor::getColumnIsUniqueFromBuffer(uint32_t col) {
1580 return pvt->_columnisuniques[col];
1581 }
1582
getColumnIsPartOfKeyFromBuffer(uint32_t col)1583 uint16_t sqlrservercursor::getColumnIsPartOfKeyFromBuffer(uint32_t col) {
1584 return pvt->_columnispartofkeys[col];
1585 }
1586
getColumnIsUnsignedFromBuffer(uint32_t col)1587 uint16_t sqlrservercursor::getColumnIsUnsignedFromBuffer(uint32_t col) {
1588 return pvt->_columnisunsigneds[col];
1589 }
1590
getColumnIsZeroFilledFromBuffer(uint32_t col)1591 uint16_t sqlrservercursor::getColumnIsZeroFilledFromBuffer(uint32_t col) {
1592 return pvt->_columniszerofilleds[col];
1593 }
1594
getColumnIsBinaryFromBuffer(uint32_t col)1595 uint16_t sqlrservercursor::getColumnIsBinaryFromBuffer(uint32_t col) {
1596 return pvt->_columnisbinarys[col];
1597 }
1598
getColumnIsAutoIncrementFromBuffer(uint32_t col)1599 uint16_t sqlrservercursor::getColumnIsAutoIncrementFromBuffer(uint32_t col) {
1600 return pvt->_columnisautoincrements[col];
1601 }
1602
getColumnTableFromBuffer(uint32_t col)1603 const char *sqlrservercursor::getColumnTableFromBuffer(uint32_t col) {
1604 return pvt->_columntables[col];
1605 }
1606
getColumnTableLengthFromBuffer(uint32_t col)1607 uint16_t sqlrservercursor::getColumnTableLengthFromBuffer(uint32_t col) {
1608 return pvt->_columntablelengths[col];
1609 }
1610
allocateFieldPointers(uint32_t colcount)1611 void sqlrservercursor::allocateFieldPointers(uint32_t colcount) {
1612 pvt->_fieldnames=new const char *[colcount];
1613 pvt->_fields=new const char *[colcount];
1614 pvt->_fieldlengths=new uint64_t[colcount];
1615 pvt->_blobs=new bool[colcount];
1616 pvt->_nulls=new bool[colcount];
1617 }
1618
deallocateFieldPointers()1619 void sqlrservercursor::deallocateFieldPointers() {
1620 delete[] pvt->_fieldnames;
1621 delete[] pvt->_fields;
1622 delete[] pvt->_fieldlengths;
1623 delete[] pvt->_blobs;
1624 delete[] pvt->_nulls;
1625 }
1626
getFieldPointers(const char *** fieldnames,const char *** fields,uint64_t ** fieldlengths,bool ** blobs,bool ** nulls)1627 void sqlrservercursor::getFieldPointers(const char ***fieldnames,
1628 const char ***fields,
1629 uint64_t **fieldlengths,
1630 bool **blobs,
1631 bool **nulls) {
1632
1633 // get the max column count
1634 uint32_t colcount=conn->cont->getMaxColumnCount();
1635
1636 // decide if we need to allocate field pointers here,
1637 // and if so, how many columns
1638 bool allocate=false;
1639 if (!colcount) {
1640 colcount=colCount();
1641 allocate=true;
1642 }
1643
1644 // allocate the field pointers, if necessary
1645 if (allocate) {
1646 deallocateFieldPointers();
1647 allocateFieldPointers(colcount);
1648 }
1649
1650 // return the field pointers
1651 *fieldnames=pvt->_fieldnames;
1652 *fields=pvt->_fields;
1653 *fieldlengths=pvt->_fieldlengths;
1654 *blobs=pvt->_blobs;
1655 *nulls=pvt->_nulls;
1656 }
1657
setQueryTimeout(uint64_t querytimeout)1658 void sqlrservercursor::setQueryTimeout(uint64_t querytimeout) {
1659 pvt->_querytimeout=querytimeout;
1660 }
1661
getQueryTimeout()1662 uint64_t sqlrservercursor::getQueryTimeout() {
1663 return pvt->_querytimeout;
1664 }
1665
setExecuteDirect(bool executedirect)1666 void sqlrservercursor::setExecuteDirect(bool executedirect) {
1667 pvt->_executedirect=executedirect;
1668 }
1669
getExecuteDirect()1670 bool sqlrservercursor::getExecuteDirect() {
1671 return pvt->_executedirect;
1672 }
1673
setExecuteRpc(bool executerpc)1674 void sqlrservercursor::setExecuteRpc(bool executerpc) {
1675 pvt->_executerpc=executerpc;
1676 }
1677
getExecuteRpc()1678 bool sqlrservercursor::getExecuteRpc() {
1679 return pvt->_executerpc;
1680 }
1681
setResultSetHeaderHasBeenHandled(bool resultsetheaderhasbeenhandled)1682 void sqlrservercursor::setResultSetHeaderHasBeenHandled(
1683 bool resultsetheaderhasbeenhandled) {
1684 pvt->_resultsetheaderhasbeenhandled=resultsetheaderhasbeenhandled;
1685 }
1686
getResultSetHeaderHasBeenHandled()1687 bool sqlrservercursor::getResultSetHeaderHasBeenHandled() {
1688 return pvt->_resultsetheaderhasbeenhandled;
1689 }
1690
getModuleData()1691 unsigned char *sqlrservercursor::getModuleData() {
1692 return pvt->_moduledata;
1693 }
1694