2 /* # line 3 "myingres.sc" */
7 extern IISQLCA sqlca; /* SQL Communications Area */
14 * ---Implementations---
18 return (sqlca.sqlcode < 0) ? sqlca.sqlcode : 0;
20 short INGgetCols(B_DB *mdb, const char *query)
22 bool stmt_free = false;
23 /* # line 24 "myingres.sc" */
26 /* # line 26 "myingres.sc" */
30 sqlda = (IISQLDA *)malloc(IISQDA_HEAD_SIZE + (number * IISQDA_VAR_SIZE));
31 memset(sqlda, 0, (IISQDA_HEAD_SIZE + (number * IISQDA_VAR_SIZE)));
34 * See if we need to run this through the limit_filter.
36 if (strstr(query, "LIMIT") != NULL) {
37 stmt = mdb->limit_filter->replace(query);
39 stmt = bstrdup(query);
42 /* # line 46 "myingres.sc" */ /* prepare */
45 IIsqPrepare(0,(char *)"s1",(char *)0,0,stmt);
47 /* # line 47 "myingres.sc" */ /* host code */
52 /* # line 52 "myingres.sc" */ /* describe */
55 IIsqDescribe(0,(char *)"s1",sqlda,0);
57 /* # line 53 "myingres.sc" */ /* host code */
70 static inline IISQLDA *INGgetDescriptor(B_DB *mdb, short numCols, const char *query)
72 bool stmt_free = false;
73 /* # line 71 "myingres.sc" */
76 /* # line 73 "myingres.sc" */
80 sqlda = (IISQLDA *)malloc(IISQDA_HEAD_SIZE + (numCols * IISQDA_VAR_SIZE));
81 memset(sqlda, 0, (IISQDA_HEAD_SIZE + (numCols * IISQDA_VAR_SIZE)));
82 sqlda->sqln = numCols;
84 * See if we need to run this through the limit_filter.
86 if (strstr(query, "LIMIT") != NULL) {
87 stmt = mdb->limit_filter->replace(query);
89 stmt = bstrdup(query);
92 /* # line 93 "myingres.sc" */ /* prepare */
95 IIsqPrepare(0,(char *)"s2",sqlda,0,stmt);
97 /* # line 95 "myingres.sc" */ /* host code */
101 for (i = 0; i < sqlda->sqld; ++i) {
103 * Negative type indicates nullable coulumns, so an indicator
104 * is allocated, otherwise it's null
106 if (sqlda->sqlvar[i].sqltype > 0) {
107 sqlda->sqlvar[i].sqlind = NULL;
109 sqlda->sqlvar[i].sqlind = (short *)malloc(sizeof(short));
112 * Alloc space for variable like indicated in sqllen
113 * for date types sqllen is always 0 -> allocate by type
115 switch (abs(sqlda->sqlvar[i].sqltype)) {
117 sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSW_LEN);
120 sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSWO_LEN);
122 case IISQ_TSTMP_TYPE:
123 sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN);
127 * plus one to avoid zero mem allocs
129 sqlda->sqlvar[i].sqldata = (char *)malloc(sqlda->sqlvar[i].sqllen+1);
135 static void INGfreeDescriptor(IISQLDA *sqlda)
141 for (i = 0; i < sqlda->sqld; ++i) {
142 if (sqlda->sqlvar[i].sqldata) {
143 free(sqlda->sqlvar[i].sqldata);
145 if (sqlda->sqlvar[i].sqlind) {
146 free(sqlda->sqlvar[i].sqlind);
152 static inline int INGgetTypeSize(IISQLVAR *ingvar)
156 * TODO: add date types (at least TSTMP,TSW TSWO)
158 switch (ingvar->sqltype) {
166 inglength = ingvar->sqllen;
171 static inline INGresult *INGgetINGresult(IISQLDA *sqlda)
174 INGresult *result = NULL;
178 result = (INGresult *)malloc(sizeof(INGresult));
179 memset(result, 0, sizeof(INGresult));
180 result->sqlda = sqlda;
181 result->num_fields = sqlda->sqld;
182 result->num_rows = 0;
183 result->first_row = NULL;
184 result->status = ING_EMPTY_RESULT;
185 result->act_row = NULL;
186 memset(result->numrowstring, 0, sizeof(result->numrowstring));
187 if (result->num_fields) {
188 result->fields = (INGRES_FIELD *)malloc(sizeof(INGRES_FIELD) * result->num_fields);
189 memset(result->fields, 0, sizeof(INGRES_FIELD) * result->num_fields);
190 for (i = 0; i < result->num_fields; ++i) {
191 memset(result->fields[i].name, 0, 34);
192 bstrncpy(result->fields[i].name, sqlda->sqlvar[i].sqlname.sqlnamec, sqlda->sqlvar[i].sqlname.sqlnamel);
193 result->fields[i].max_length = INGgetTypeSize(&sqlda->sqlvar[i]);
194 result->fields[i].type = abs(sqlda->sqlvar[i].sqltype);
195 result->fields[i].flags = (sqlda->sqlvar[i].sqltype < 0) ? 1 : 0;
200 static void INGfreeINGresult(INGresult *ing_res)
208 * Free all rows and fields, then res, not descriptor!
210 * Use of rows is a nasty workaround til I find the reason,
211 * why aggregates like max() don't work
213 rows = ing_res->num_rows;
214 ing_res->act_row = ing_res->first_row;
215 while (ing_res->act_row != NULL && rows > 0) {
216 rowtemp = ing_res->act_row->next;
217 INGfreeRowSpace(ing_res->act_row, ing_res->sqlda);
218 ing_res->act_row = rowtemp;
221 if (ing_res->fields) {
222 free(ing_res->fields);
227 static inline ING_ROW *INGgetRowSpace(INGresult *ing_res)
230 unsigned short len; /* used for VARCHAR type length */
231 IISQLDA *sqlda = ing_res->sqlda;
233 IISQLVAR *vars = NULL;
234 row = (ING_ROW *)malloc(sizeof(ING_ROW));
235 memset(row, 0, sizeof(ING_ROW));
236 vars = (IISQLVAR *)malloc(sizeof(IISQLVAR) * sqlda->sqld);
237 memset(vars, 0, sizeof(IISQLVAR) * sqlda->sqld);
240 for (i = 0; i < sqlda->sqld; ++i) {
242 * Make strings out of the data, then the space and assign
243 * (why string? at least it seems that way, looking into the sources)
245 vars[i].sqlind = (short *)malloc(sizeof(short));
246 if (sqlda->sqlvar[i].sqlind) {
247 memcpy(vars[i].sqlind,sqlda->sqlvar[i].sqlind,sizeof(short));
249 *vars[i].sqlind = NULL;
252 * if sqlind pointer exists AND points to -1 -> column is 'null'
254 if ( *vars[i].sqlind && (*vars[i].sqlind == -1)) {
255 vars[i].sqldata = NULL;
257 switch (ing_res->fields[i].type) {
259 len = ((ING_VARCHAR *)sqlda->sqlvar[i].sqldata)->len;
260 vars[i].sqldata = (char *)malloc(len+1);
261 memcpy(vars[i].sqldata,sqlda->sqlvar[i].sqldata+2,len);
262 vars[i].sqldata[len] = '\0';
265 vars[i].sqldata = (char *)malloc(ing_res->fields[i].max_length+1);
266 memcpy(vars[i].sqldata,sqlda->sqlvar[i].sqldata,sqlda->sqlvar[i].sqllen);
267 vars[i].sqldata[ing_res->fields[i].max_length] = '\0';
270 vars[i].sqldata = (char *)malloc(20);
271 memset(vars[i].sqldata, 0, 20);
272 switch (sqlda->sqlvar[i].sqllen) {
274 bsnprintf(vars[i].sqldata, 20, "%d",*(short*)sqlda->sqlvar[i].sqldata);
277 bsnprintf(vars[i].sqldata, 20, "%ld",*(int*)sqlda->sqlvar[i].sqldata);
280 bsnprintf(vars[i].sqldata, 20, "%lld",*(long*)sqlda->sqlvar[i].sqldata);
284 case IISQ_TSTMP_TYPE:
285 vars[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN+1);
286 vars[i].sqldata[IISQ_TSTMP_LEN] = '\0';
289 vars[i].sqldata = (char *)malloc(IISQ_TSWO_LEN+1);
290 vars[i].sqldata[IISQ_TSWO_LEN] = '\0';
293 vars[i].sqldata = (char *)malloc(IISQ_TSW_LEN+1);
294 vars[i].sqldata[IISQ_TSW_LEN] = '\0';
301 static inline void INGfreeRowSpace(ING_ROW *row, IISQLDA *sqlda)
304 if (row == NULL || sqlda == NULL) {
307 for (i = 0; i < sqlda->sqld; ++i) {
308 if (row->sqlvar[i].sqldata) {
309 free(row->sqlvar[i].sqldata);
311 if (row->sqlvar[i].sqlind) {
312 free(row->sqlvar[i].sqlind);
318 static inline int INGfetchAll(const char *query, INGresult *ing_res)
324 desc = ing_res->sqlda;
325 /* # line 352 "myingres.sc" */ /* host code */
326 if ((check = INGcheck()) < 0) {
329 /* # line 356 "myingres.sc" */ /* open */
332 IIcsOpen((char *)"c2",9209,14491);
333 IIwritio(0,(short *)0,1,32,0,(char *)"s2");
334 IIcsQuery((char *)"c2",9209,14491);
336 /* # line 357 "myingres.sc" */ /* host code */
337 if ((check = INGcheck()) < 0) {
340 /* for (linecount = 0; sqlca.sqlcode == 0; ++linecount) */
342 /* # line 363 "myingres.sc" */ /* fetch */
345 if (IIcsRetScroll((char *)"c2",9209,14491,-1,-1) != 0) {
350 /* # line 365 "myingres.sc" */ /* host code */
351 if ( (sqlca.sqlcode == 0) || (sqlca.sqlcode == -40202) ) {
352 row = INGgetRowSpace(ing_res); /* alloc space for fetched row */
354 * Initialize list when encountered first time
356 if (ing_res->first_row == 0) {
357 ing_res->first_row = row; /* head of the list */
358 ing_res->first_row->next = NULL;
359 ing_res->act_row = ing_res->first_row;
361 ing_res->act_row->next = row; /* append row to old act_row */
362 ing_res->act_row = row; /* set row as act_row */
363 row->row_number = linecount;
366 } while ( (sqlca.sqlcode == 0) || (sqlca.sqlcode == -40202) );
367 /* # line 383 "myingres.sc" */ /* close */
370 IIcsClose((char *)"c2",9209,14491);
372 /* # line 385 "myingres.sc" */ /* host code */
373 ing_res->status = ING_COMMAND_OK;
374 ing_res->num_rows = linecount;
377 static inline ING_STATUS INGresultStatus(INGresult *res)
380 return ING_NO_RESULT;
385 static void INGrowSeek(INGresult *res, int row_number)
387 ING_ROW *trow = NULL;
388 if (res->act_row->row_number == row_number) {
392 * TODO: real error handling
394 if (row_number<0 || row_number>res->num_rows) {
397 for (trow = res->first_row; trow->row_number != row_number; trow = trow->next) ;
400 * Note - can be null - if row_number not found, right?
403 char *INGgetvalue(INGresult *res, int row_number, int column_number)
405 if (row_number != res->act_row->row_number) {
406 INGrowSeek(res, row_number);
408 return res->act_row->sqlvar[column_number].sqldata;
410 int INGgetisnull(INGresult *res, int row_number, int column_number)
412 if (row_number != res->act_row->row_number) {
413 INGrowSeek(res, row_number);
415 return (*res->act_row->sqlvar[column_number].sqlind == -1) 1 : 0;
417 int INGntuples(const INGresult *res)
419 return res->num_rows;
421 int INGnfields(const INGresult *res)
423 return res->num_fields;
425 char *INGfname(const INGresult *res, int column_number)
427 if ((column_number > res->num_fields) || (column_number < 0)) {
430 return res->fields[column_number].name;
433 short INGftype(const INGresult *res, int column_number)
435 return res->fields[column_number].type;
437 int INGexec(B_DB *mdb, INGconn *conn, const char *query)
439 bool stmt_free = false;
441 /* # line 467 "myingres.sc" */
445 /* # line 470 "myingres.sc" */
448 * See if we need to run this through the limit_filter.
450 if (strstr(query, "LIMIT") != NULL) {
451 stmt = mdb->limit_filter->replace(query);
453 stmt = bstrdup(query);
457 /* # line 483 "myingres.sc" */ /* execute */
461 IIsyncup((char *)0,0);
463 /* # line 485 "myingres.sc" */ /* host code */
467 if ((check = INGcheck()) < 0) {
470 /* # line 493 "myingres.sc" */ /* inquire_ingres */
472 IILQisInqSqlio((short *)0,1,30,sizeof(rowcount),&rowcount,8);
474 /* # line 494 "myingres.sc" */ /* host code */
475 if ((check = INGcheck()) < 0) {
480 INGresult *INGquery(B_DB *mdb, INGconn *conn, const char *query)
483 * TODO: error handling
485 IISQLDA *desc = NULL;
486 INGresult *res = NULL;
488 int cols = INGgetCols(mdb, query);
489 desc = INGgetDescriptor(cols, query);
493 res = INGgetINGresult(desc);
497 rows = INGfetchAll(query, res);
499 INGfreeINGresult(res);
500 INGfreeDescriptor(desc);
505 void INGclear(INGresult *res)
510 INGfreeINGresult(res);
511 INGfreeDescriptor(res->sqlda);
513 INGconn *INGconnectDB(char *dbname, char *user, char *passwd)
516 if (dbname == NULL || strlen(dbname) == 0) {
519 dbconn = (INGconn *)malloc(sizeof(INGconn));
520 memset(dbconn, 0, sizeof(INGconn));
521 /* # line 550 "myingres.sc" */
528 /* # line 556 "myingres.sc" */
530 bstrncpy(ingdbname, dbname, sizeof(ingdbname));
532 bstrncpy(ingdbuser, user, sizeof(ingdbuser));
533 if (passwd != NULL) {
534 bstrncpy(ingdbpasw, passwd, sizeof(ingdbpasw));
536 memset(ingdbpasw, 0, sizeof(ingdbpasw));
538 /* # line 567 "myingres.sc" */ /* connect */
542 IIsqConnect(0,ingdbname,(char *)"-dbms_password",ingdbpasw,(char *)0,
543 (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0,
544 (char *)0, (char *)0, (char *)0, (char *)0);
546 /* # line 571 "myingres.sc" */ /* host code */
548 /* # line 572 "myingres.sc" */ /* connect */
551 IIsqConnect(0,ingdbname,(char *)0, (char *)0, (char *)0, (char *)0,
552 (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0,
553 (char *)0, (char *)0, (char *)0);
555 /* # line 573 "myingres.sc" */ /* host code */
557 /* # line 575 "myingres.sc" */ /* inquire_sql */
559 IILQisInqSqlio((short *)0,1,32,31,conn_name,13);
561 /* # line 576 "myingres.sc" */ /* inquire_sql */
563 IILQisInqSqlio((short *)0,1,30,sizeof(sess_id),&sess_id,11);
565 /* # line 578 "myingres.sc" */ /* host code */
566 bstrncpy(dbconn->dbname, ingdbname, sizeof(dbconn->dbname));
567 bstrncpy(dbconn->user, ingdbuser, sizeof(dbconn->user));
568 bstrncpy(dbconn->password, ingdbpasw, sizeof(dbconn->password));
569 bstrncpy(dbconn->connection_name, conn_name, sizeof(dbconn->connection_name));
570 dbconn->session_id = sess_id;
571 dbconn->msg = (char*)malloc(257);
572 memset(dbconn->msg, 0, 257);
575 void INGdisconnectDB(INGconn *dbconn)
578 * TODO: check for any real use of dbconn: maybe whenn multithreaded?
580 /* # line 594 "myingres.sc" */ /* disconnect */
585 /* # line 595 "myingres.sc" */ /* host code */
586 if (dbconn != NULL) {
591 char *INGerrorMessage(const INGconn *conn)
593 /* # line 603 "myingres.sc" */
596 /* # line 605 "myingres.sc" */
598 /* # line 607 "myingres.sc" */ /* inquire_ingres */
600 IILQisInqSqlio((short *)0,1,32,255,errbuf,63);
602 /* # line 608 "myingres.sc" */ /* host code */
603 memcpy(conn->msg, &errbuf, 256);
606 char *INGcmdTuples(INGresult *res)
608 return res->numrowstring;
611 int INGputCopyEnd(INGconn *conn, const char *errormsg);
612 int INGputCopyData(INGconn *conn, const char *buffer, int nbytes);
614 /* # line 622 "myingres.sc" */