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