]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/myingres.c
Tweak version date
[bacula/bacula] / bacula / src / cats / myingres.c
1 /*
2    Bacula® - The Network Backup Solution
3    Copyright (C) 2009-2010 Free Software Foundation Europe e.V.
4    The main author of Bacula is Kern Sibbald, with contributions from
5    many others, a complete list can be found in the file AUTHORS.
6    This program is Free Software; you can redistribute it and/or
7    modify it under the terms of version three of the GNU Affero General Public
8    License as published by the Free Software Foundation and included
9    in the file LICENSE.
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    General Public License for more details.
14    You should have received a copy of the GNU Affero General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17    02110-1301, USA.
18    Bacula® is a registered trademark of Kern Sibbald.
19    The licensor of Bacula is the Free Software Foundation Europe
20    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
21    Switzerland, email:ftf@fsfeurope.org.
22 */
23 /*
24  * Bacula Catalog Database routines specific to Ingres
25  *   These are Ingres specific routines
26  *
27  *    Stefan Reddig, June 2009 with help of Marco van Wieringen April 2010
28  */
29 #include "bacula.h"
30 /* # line 37 "myingres.sc" */   
31 #ifdef HAVE_INGRES
32 #include <eqpname.h>
33 #include <eqdefcc.h>
34 #include <eqsqlca.h>
35 #include <eqsqlda.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include "myingres.h"
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 IISQLCA *IIsqlca();
45 #ifdef __cplusplus
46 }
47 #endif
48 #define sqlca (*(IIsqlca()))
49
50 /*
51  * ---Implementations---
52  */
53 int INGgetCols(INGconn *dbconn, const char *query, bool explicit_commit)
54 {
55 /* # line 52 "myingres.sc" */   
56   
57   int sess_id;
58   char *stmt;
59 /* # line 55 "myingres.sc" */   
60   
61    IISQLDA *sqlda;
62    int number = -1;
63    sqlda = (IISQLDA *)malloc(IISQDA_HEAD_SIZE + IISQDA_VAR_SIZE);
64    memset(sqlda, 0, (IISQDA_HEAD_SIZE + IISQDA_VAR_SIZE));
65    sqlda->sqln = number;
66    stmt = bstrdup(query);
67 /* # line 68 "myingres.sc" */   /* host code */
68    /*
69     * Switch to the correct default session for this thread.
70     */
71    sess_id = dbconn->session_id;
72 /* # line 72 "myingres.sc" */   /* set_sql */
73   {
74     IILQssSetSqlio(11,(short *)0,1,30,sizeof(sess_id),&sess_id);
75   }
76 /* # line 74 "myingres.sc" */   /* prepare */
77   {
78     IIsqInit(&sqlca);
79     IIsqPrepare(0,(char *)"s1",sqlda,0,stmt);
80     if (sqlca.sqlcode < 0) 
81       goto bail_out;
82   }
83 /* # line 78 "myingres.sc" */   /* host code */
84    number = sqlda->sqld;
85 bail_out:
86    /*
87     * If explicit_commit is set we commit our work now.
88     */
89    if (explicit_commit) {
90 /* # line 85 "myingres.sc" */   /* commit */
91   {
92     IIsqInit(&sqlca);
93     IIxact(3);
94   }
95 /* # line 86 "myingres.sc" */   /* host code */
96    }
97    /*
98     * Switch to no default session for this thread.
99     */
100 /* # line 91 "myingres.sc" */   /* set_sql */
101   {
102     IILQssSetSqlio(11,(short *)0,1,30,sizeof(-97),(void *)IILQint(-97));
103   }
104 /* # line 92 "myingres.sc" */   /* host code */
105    free(stmt);
106    free(sqlda);
107    return number;
108 }
109 static inline IISQLDA *INGgetDescriptor(int numCols, const char *query)
110 {
111 /* # line 99 "myingres.sc" */   
112   
113   char *stmt;
114 /* # line 101 "myingres.sc" */  
115   
116    int i;
117    IISQLDA *sqlda;
118    sqlda = (IISQLDA *)malloc(IISQDA_HEAD_SIZE + (numCols * IISQDA_VAR_SIZE));
119    memset(sqlda, 0, (IISQDA_HEAD_SIZE + (numCols * IISQDA_VAR_SIZE)));
120    sqlda->sqln = numCols;
121    stmt = bstrdup(query);
122 /* # line 112 "myingres.sc" */  /* prepare */
123   {
124     IIsqInit(&sqlca);
125     IIsqPrepare(0,(char *)"s2",sqlda,0,stmt);
126   }
127 /* # line 114 "myingres.sc" */  /* host code */
128    for (i = 0; i < sqlda->sqld; ++i) {
129       /*
130        * Negative type indicates nullable columns, so an indicator
131        * is allocated, otherwise it's null
132        */
133       if (sqlda->sqlvar[i].sqltype > 0) {
134          sqlda->sqlvar[i].sqlind = NULL;
135       } else {
136          sqlda->sqlvar[i].sqlind = (short *)malloc(sizeof(short));
137       }
138       /*
139        * Alloc space for variable like indicated in sqllen
140        * for date types sqllen is always 0 -> allocate by type
141        */
142       switch (abs(sqlda->sqlvar[i].sqltype)) {
143       case IISQ_TSW_TYPE:
144          sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSW_LEN);
145          break;
146       case IISQ_TSWO_TYPE:
147          sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSWO_LEN);
148          break;
149       case IISQ_TSTMP_TYPE:
150          sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN);
151          break;
152       default:
153          /*
154           * plus one to avoid zero mem allocs
155           */
156          sqlda->sqlvar[i].sqldata = (char *)malloc(sqlda->sqlvar[i].sqllen + 1);
157          break;
158       }
159    }
160    free(stmt);
161    return sqlda;
162 }
163 static void INGfreeDescriptor(IISQLDA *sqlda)
164 {
165    int i;
166    if (!sqlda) {
167       return;
168    }
169    for (i = 0; i < sqlda->sqld; ++i) {
170       if (sqlda->sqlvar[i].sqldata) {
171          free(sqlda->sqlvar[i].sqldata);
172       }
173       if (sqlda->sqlvar[i].sqlind) {
174          free(sqlda->sqlvar[i].sqlind);
175       }
176    }
177    free(sqlda);
178 }
179 static inline int INGgetTypeSize(IISQLVAR *ingvar)
180 {
181    int inglength = 0;
182    switch (ingvar->sqltype) {
183    case IISQ_TSWO_TYPE:
184       inglength = 20;
185       break;
186    case IISQ_TSW_TYPE:
187       inglength = 20;
188       break;
189    case IISQ_DTE_TYPE:
190       inglength = 25;
191       break;
192    case IISQ_MNY_TYPE:
193       inglength = 8;
194       break;
195    default:
196       inglength = ingvar->sqllen;
197       break;
198    }
199    return inglength;
200 }
201 static inline INGresult *INGgetINGresult(int numCols, const char *query)
202 {
203    int i;
204    INGresult *ing_res;
205    ing_res = (INGresult *)malloc(sizeof(INGresult));
206    memset(ing_res, 0, sizeof(INGresult));
207    if ((ing_res->sqlda = INGgetDescriptor(numCols, query)) == NULL) {
208       return NULL;
209    }
210    ing_res->num_fields = ing_res->sqlda->sqld;
211    ing_res->num_rows = 0;
212    ing_res->first_row = NULL;
213    ing_res->status = ING_EMPTY_RESULT;
214    ing_res->act_row = NULL;
215    if (ing_res->num_fields) {
216       ing_res->fields = (INGRES_FIELD *)malloc(sizeof(INGRES_FIELD) * ing_res->num_fields);
217       memset(ing_res->fields, 0, sizeof(INGRES_FIELD) * ing_res->num_fields);
218       for (i = 0; i < ing_res->num_fields; ++i) {
219          ing_res->fields[i].name = (char *)malloc(ing_res->sqlda->sqlvar[i].sqlname.sqlnamel + 1);
220          bstrncpy(ing_res->fields[i].name, ing_res->sqlda->sqlvar[i].sqlname.sqlnamec, ing_res->sqlda->sqlvar[i].sqlname.sqlnamel + 1);
221          ing_res->fields[i].name[ing_res->sqlda->sqlvar[i].sqlname.sqlnamel] = '\0';
222          ing_res->fields[i].max_length = INGgetTypeSize(&ing_res->sqlda->sqlvar[i]);
223          ing_res->fields[i].type = abs(ing_res->sqlda->sqlvar[i].sqltype);
224          ing_res->fields[i].flags = (ing_res->sqlda->sqlvar[i].sqltype < 0) ? 1 : 0;
225       }
226    }
227    return ing_res;
228 }
229 static inline void INGfreeRowSpace(ING_ROW *row, IISQLDA *sqlda)
230 {
231    int i;
232    if (row == NULL || sqlda == NULL) {
233       return;
234    }
235    for (i = 0; i < sqlda->sqld; ++i) {
236       if (row->sqlvar[i].sqldata) {
237          free(row->sqlvar[i].sqldata);
238       }
239       if (row->sqlvar[i].sqlind) {
240          free(row->sqlvar[i].sqlind);
241       }
242    }
243    free(row->sqlvar);
244    free(row);
245 }
246 static void INGfreeINGresult(INGresult *ing_res)
247 {
248    int i;
249    int rows;
250    ING_ROW *rowtemp;
251    if (!ing_res) {
252       return;
253    }
254    /*
255     * Use of rows is a nasty workaround til I find the reason,
256     * why aggregates like max() don't work
257     */
258    rows = ing_res->num_rows;
259    ing_res->act_row = ing_res->first_row;
260    while (ing_res->act_row != NULL && rows > 0) {
261       rowtemp = ing_res->act_row->next;
262       INGfreeRowSpace(ing_res->act_row, ing_res->sqlda);
263       ing_res->act_row = rowtemp;
264       --rows;
265    }
266    if (ing_res->fields) {
267       for (i = 0; i < ing_res->num_fields; ++i) {
268          free(ing_res->fields[i].name);
269       }
270       free(ing_res->fields);
271    }
272    INGfreeDescriptor(ing_res->sqlda);
273    free(ing_res);
274 }
275 static inline ING_ROW *INGgetRowSpace(INGresult *ing_res)
276 {
277    int i;
278    unsigned short len; /* used for VARCHAR type length */
279    unsigned short th, tm, ts;
280    IISQLDA *sqlda;
281    ING_ROW *row = NULL;
282    ING_TIMESTAMP *tsp;
283    IISQLVAR *vars = NULL;
284    row = (ING_ROW *)malloc(sizeof(ING_ROW));
285    memset(row, 0, sizeof(ING_ROW));
286    sqlda = ing_res->sqlda;
287    vars = (IISQLVAR *)malloc(sizeof(IISQLVAR) * sqlda->sqld);
288    memset(vars, 0, sizeof(IISQLVAR) * sqlda->sqld);
289    row->sqlvar = vars;
290    row->next = NULL;
291    for (i = 0; i < sqlda->sqld; ++i) {
292       /*
293        * Make strings out of the data, then the space and assign 
294        * (why string? at least it seems that way, looking into the sources)
295        */
296       vars[i].sqlind = (short *)malloc(sizeof(short));
297       if (sqlda->sqlvar[i].sqlind) {
298          memcpy(vars[i].sqlind,sqlda->sqlvar[i].sqlind,sizeof(short));
299       } else {
300          *vars[i].sqlind = NULL;
301       }
302       /*
303        * if sqlind pointer exists AND points to -1 -> column is 'null'
304        */
305       if ( *vars[i].sqlind && (*vars[i].sqlind == -1)) {
306          vars[i].sqldata = NULL;
307       } else {
308          switch (ing_res->fields[i].type) {
309          case IISQ_VCH_TYPE:
310          case IISQ_LVCH_TYPE:
311          case IISQ_VBYTE_TYPE:
312          case IISQ_LBYTE_TYPE:
313          case IISQ_NVCHR_TYPE:
314          case IISQ_LNVCHR_TYPE:
315             len = ((ING_VARCHAR *)sqlda->sqlvar[i].sqldata)->len;
316             vars[i].sqldata = (char *)malloc(len + 1);
317             memcpy(vars[i].sqldata,sqlda->sqlvar[i].sqldata + 2,len);
318             vars[i].sqldata[len] = '\0';
319             break;
320          case IISQ_CHA_TYPE:
321          case IISQ_BYTE_TYPE:
322          case IISQ_NCHR_TYPE:
323             vars[i].sqldata = (char *)malloc(ing_res->fields[i].max_length + 1);
324             memcpy(vars[i].sqldata,sqlda->sqlvar[i].sqldata,sqlda->sqlvar[i].sqllen);
325             vars[i].sqldata[ing_res->fields[i].max_length] = '\0';
326             break;
327          case IISQ_INT_TYPE:
328             switch (sqlda->sqlvar[i].sqllen) {
329             case 2:
330                vars[i].sqldata = (char *)malloc(6);
331                memset(vars[i].sqldata, 0, 6);
332                bsnprintf(vars[i].sqldata, 6, "%d",*(int16_t *)sqlda->sqlvar[i].sqldata);
333                break;
334             case 4:
335                vars[i].sqldata = (char *)malloc(11);
336                memset(vars[i].sqldata, 0, 11);
337                bsnprintf(vars[i].sqldata, 11, "%ld",*(int32_t *)sqlda->sqlvar[i].sqldata);
338                break;
339             case 8:
340                vars[i].sqldata = (char *)malloc(20);
341                memset(vars[i].sqldata, 0, 20);
342                bsnprintf(vars[i].sqldata, 20, "%lld",*(int64_t *)sqlda->sqlvar[i].sqldata);
343                break;
344             }
345             break;
346          case IISQ_TSTMP_TYPE:
347             vars[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN + 1);
348             vars[i].sqldata[IISQ_TSTMP_LEN] = '\0';
349             break;
350          case IISQ_TSWO_TYPE:
351             tsp = (ING_TIMESTAMP *)sqlda->sqlvar[i].sqldata;
352             th = tsp->secs / 3600; /* hours */
353             tm = tsp->secs % 3600; /* remaining seconds */
354             tm = tm / 60; /* minutes */
355             ts = tsp->secs - (th * 3600) - (tm * 60); /* seconds */
356             vars[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN + 1);
357             bsnprintf(vars[i].sqldata, IISQ_TSWO_LEN + 1,
358                       "%04u-%02u-%02u %02u:%02u:%02u",
359                       tsp->year, tsp->month, tsp->day, th, tm, ts);
360             break;
361          case IISQ_TSW_TYPE:
362             tsp = (ING_TIMESTAMP *)sqlda->sqlvar[i].sqldata;
363             th = tsp->secs / 3600; /* hours */
364             tm = tsp->secs % 3600; /* remaining seconds */
365             tm = tm / 60; /* minutes */
366             ts = tsp->secs - (th * 3600) - (tm * 60); /* seconds */
367             vars[i].sqldata = (char *)malloc(IISQ_TSW_LEN + 1);
368             bsnprintf(vars[i].sqldata, IISQ_TSW_LEN + 1,
369                       "%04u-%02u-%02u %02u:%02u:%02u",
370                       tsp->year, tsp->month, tsp->day, th, tm, ts);
371             break;
372          default:
373             Jmsg(NULL, M_FATAL, 0,
374                  "INGgetRowSpace: encountered unhandled database datatype %d please report this as a bug\n",
375                  ing_res->fields[i].type);
376             break;
377          }
378       }
379    }
380    return row;
381 }
382 static inline int INGfetchAll(INGresult *ing_res)
383 {
384    ING_ROW *row;
385    IISQLDA *desc;
386    int linecount = -1;
387    desc = ing_res->sqlda;
388 /* # line 409 "myingres.sc" */  /* open */
389   {
390     IIsqInit(&sqlca);
391     IIcsOpen((char *)"c2",20273,8927);
392     IIwritio(0,(short *)0,1,32,0,(char *)"s2");
393     IIcsQuery((char *)"c2",20273,8927);
394     if (sqlca.sqlcode < 0) 
395       goto bail_out;
396   }
397 /* # line 413 "myingres.sc" */  /* host code */
398    linecount = 0;
399    do {
400 /* # line 415 "myingres.sc" */  /* fetch */
401   {
402     IIsqInit(&sqlca);
403     if (IIcsRetScroll((char *)"c2",20273,8927,-1,-1) != 0) {
404       IIcsDaGet(0,desc);
405       IIcsERetrieve();
406     } /* IIcsRetrieve */
407   }
408 /* # line 417 "myingres.sc" */  /* host code */
409       if (sqlca.sqlcode == 0 || sqlca.sqlcode == -40202) {
410          /*
411           * Allocate space for fetched row
412           */
413          row = INGgetRowSpace(ing_res);
414          /*
415           * Initialize list when encountered first time
416           */
417          if (ing_res->first_row == 0) {
418             ing_res->first_row = row; /* head of the list */
419             ing_res->first_row->next = NULL;
420             ing_res->act_row = ing_res->first_row;
421          }      
422          ing_res->act_row->next = row; /* append row to old act_row */
423          ing_res->act_row = row; /* set row as act_row */
424          row->row_number = linecount++;
425       }
426    } while ( (sqlca.sqlcode == 0) || (sqlca.sqlcode == -40202) );
427 /* # line 438 "myingres.sc" */  /* close */
428   {
429     IIsqInit(&sqlca);
430     IIcsClose((char *)"c2",20273,8927);
431   }
432 /* # line 440 "myingres.sc" */  /* host code */
433    ing_res->status = ING_COMMAND_OK;
434    ing_res->num_rows = linecount;
435 bail_out:
436    return linecount;
437 }
438 static inline ING_STATUS INGresultStatus(INGresult *ing_res)
439 {
440    if (ing_res == NULL) {
441       return ING_NO_RESULT;
442    } else {
443       return ing_res->status;
444    }
445 }
446 static void INGrowSeek(INGresult *ing_res, int row_number)
447 {
448    ING_ROW *trow = NULL;
449    if (ing_res->act_row->row_number == row_number) {
450       return;
451    }
452    /*
453     * TODO: real error handling
454     */
455    if (row_number < 0 || row_number > ing_res->num_rows) {
456       return;
457    }
458    for (trow = ing_res->first_row; trow->row_number != row_number; trow = trow->next) ;
459    ing_res->act_row = trow;
460    /*
461     * Note - can be null - if row_number not found, right?
462     */
463 }
464 char *INGgetvalue(INGresult *ing_res, int row_number, int column_number)
465 {
466    if (row_number != ing_res->act_row->row_number) {
467       INGrowSeek(ing_res, row_number);
468    }
469    return ing_res->act_row->sqlvar[column_number].sqldata;
470 }
471 bool INGgetisnull(INGresult *ing_res, int row_number, int column_number)
472 {
473    if (row_number != ing_res->act_row->row_number) {
474       INGrowSeek(ing_res, row_number);
475    }
476    return (*ing_res->act_row->sqlvar[column_number].sqlind == -1) ? true : false;
477 }
478 int INGntuples(const INGresult *ing_res)
479 {
480    return ing_res->num_rows;
481 }
482 int INGnfields(const INGresult *ing_res)
483 {
484    return ing_res->num_fields;
485 }
486 char *INGfname(const INGresult *ing_res, int column_number)
487 {
488    if ((column_number > ing_res->num_fields) || (column_number < 0)) {
489       return NULL;
490    } else {
491       return ing_res->fields[column_number].name;
492    }
493 }
494 short INGftype(const INGresult *ing_res, int column_number)
495 {
496    return ing_res->fields[column_number].type;
497 }
498 int INGexec(INGconn *dbconn, const char *query, bool explicit_commit)
499 {
500 /* # line 522 "myingres.sc" */  
501   
502   int sess_id;
503   int rowcount;
504   int errors;
505   char *stmt;
506 /* # line 527 "myingres.sc" */  
507   
508    rowcount = -1;
509    stmt = bstrdup(query);
510 /* # line 534 "myingres.sc" */  /* host code */
511    /*
512     * Switch to the correct default session for this thread.
513     */
514    sess_id = dbconn->session_id;
515 /* # line 538 "myingres.sc" */  /* set_sql */
516   {
517     IILQssSetSqlio(11,(short *)0,1,30,sizeof(sess_id),&sess_id);
518   }
519 /* # line 540 "myingres.sc" */  /* execute */
520   {
521     IIsqInit(&sqlca);
522     IIsqExImmed(stmt);
523     IIsyncup((char *)0,0);
524     if (sqlca.sqlcode < 0) 
525       goto bail_out;
526   }
527 /* # line 541 "myingres.sc" */  /* inquire_ingres */
528   {
529     IILQisInqSqlio((short *)0,1,30,sizeof(rowcount),&rowcount,8);
530   }
531 /* # line 543 "myingres.sc" */  /* host code */
532    /*
533     * See if the negative rowcount is due to errors.
534     */
535    if (rowcount < 0) {
536 /* # line 547 "myingres.sc" */  /* inquire_ingres */
537   {
538     IILQisInqSqlio((short *)0,1,30,sizeof(errors),&errors,0);
539   }
540 /* # line 549 "myingres.sc" */  /* host code */
541       /*
542        * If the number of errors is 0 we got a negative rowcount
543        * because the statement we executed doesn't give a rowcount back.
544        * Lets pretend we have a rowcount of 1 then.
545        */
546       if (errors == 0) {
547          rowcount = 1;
548       }
549    }
550 /* # line 561 "myingres.sc" */  /* host code */
551 bail_out:
552    /*
553     * If explicit_commit is set we commit our work now.
554     */
555    if (explicit_commit) {
556 /* # line 566 "myingres.sc" */  /* commit */
557   {
558     IIsqInit(&sqlca);
559     IIxact(3);
560   }
561 /* # line 567 "myingres.sc" */  /* host code */
562    }
563    /*
564     * Switch to no default session for this thread.
565     */
566 /* # line 572 "myingres.sc" */  /* set_sql */
567   {
568     IILQssSetSqlio(11,(short *)0,1,30,sizeof(-97),(void *)IILQint(-97));
569   }
570 /* # line 573 "myingres.sc" */  /* host code */
571    free(stmt);
572    return rowcount;
573 }
574 INGresult *INGquery(INGconn *dbconn, const char *query, bool explicit_commit)
575 {
576    /*
577     * TODO: error handling
578     */
579    INGresult *ing_res = NULL;
580    int rows;
581    int cols;
582 /* # line 585 "myingres.sc" */  
583   
584   int sess_id;
585 /* # line 587 "myingres.sc" */  
586   
587    cols = INGgetCols(dbconn, query, explicit_commit);
588    /*
589     * Switch to the correct default session for this thread.
590     */
591    sess_id = dbconn->session_id;
592 /* # line 595 "myingres.sc" */  /* set_sql */
593   {
594     IILQssSetSqlio(11,(short *)0,1,30,sizeof(sess_id),&sess_id);
595   }
596 /* # line 597 "myingres.sc" */  /* host code */
597    ing_res = INGgetINGresult(cols, query);
598    if (!ing_res) {
599       goto bail_out;
600    }
601    rows = INGfetchAll(ing_res);
602    if (rows < 0) {
603       INGfreeINGresult(ing_res);
604       ing_res = NULL;
605       goto bail_out;
606    }
607 bail_out:
608    /*
609     * If explicit_commit is set we commit our work now.
610     */
611    if (explicit_commit) {
612 /* # line 615 "myingres.sc" */  /* commit */
613   {
614     IIsqInit(&sqlca);
615     IIxact(3);
616   }
617 /* # line 616 "myingres.sc" */  /* host code */
618    }
619    /*
620     * Switch to no default session for this thread.
621     */
622 /* # line 621 "myingres.sc" */  /* set_sql */
623   {
624     IILQssSetSqlio(11,(short *)0,1,30,sizeof(-97),(void *)IILQint(-97));
625   }
626 /* # line 622 "myingres.sc" */  /* host code */
627    return ing_res;
628 }
629 void INGclear(INGresult *ing_res)
630 {
631    if (ing_res == NULL) {
632       return;
633    }
634    INGfreeINGresult(ing_res);
635 }
636 void INGcommit(const INGconn *dbconn)
637 {
638 /* # line 636 "myingres.sc" */  
639   
640   int sess_id;
641 /* # line 638 "myingres.sc" */  
642   
643    if (dbconn != NULL) {
644       /*
645        * Switch to the correct default session for this thread.
646        */
647       sess_id = dbconn->session_id;
648 /* # line 645 "myingres.sc" */  /* set_sql */
649   {
650     IILQssSetSqlio(11,(short *)0,1,30,sizeof(sess_id),&sess_id);
651   }
652 /* # line 647 "myingres.sc" */  /* host code */
653       /*
654        * Commit our work.
655        */
656 /* # line 650 "myingres.sc" */  /* commit */
657   {
658     IIsqInit(&sqlca);
659     IIxact(3);
660   }
661 /* # line 652 "myingres.sc" */  /* host code */
662       /*
663        * Switch to no default session for this thread.
664        */
665 /* # line 655 "myingres.sc" */  /* set_sql */
666   {
667     IILQssSetSqlio(11,(short *)0,1,30,sizeof(-97),(void *)IILQint(-97));
668   }
669 /* # line 656 "myingres.sc" */  /* host code */
670    }
671 }
672 INGconn *INGconnectDB(char *dbname, char *user, char *passwd, int session_id)
673 {
674 /* # line 661 "myingres.sc" */  
675   
676   char *ingdbname;
677   char *ingdbuser = NULL;
678   char *ingdbpasswd = NULL;
679   int sess_id;
680 /* # line 666 "myingres.sc" */  
681   
682    INGconn *dbconn = NULL;
683    if (dbname == NULL || strlen(dbname) == 0) {
684       return NULL;
685    }
686    sess_id = session_id;
687    ingdbname = dbname;
688 /* # line 678 "myingres.sc" */  /* host code */
689    if (user != NULL) {
690       ingdbuser = user;
691       if (passwd != NULL) {
692          ingdbpasswd = passwd;
693 /* # line 682 "myingres.sc" */  /* connect */
694   {
695     IIsqInit(&sqlca);
696     IILQsidSessID(sess_id);
697     IIsqUser(ingdbuser);
698     IIsqConnect(0,ingdbname,(char *)"-dbms_password",ingdbpasswd,(char *)0, 
699     (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, 
700     (char *)0, (char *)0, (char *)0, (char *)0);
701     if (sqlca.sqlcode < 0) 
702       goto bail_out;
703   }
704 /* # line 687 "myingres.sc" */  /* host code */
705       } else {
706 /* # line 688 "myingres.sc" */  /* connect */
707   {
708     IIsqInit(&sqlca);
709     IILQsidSessID(sess_id);
710     IIsqUser(ingdbuser);
711     IIsqConnect(0,ingdbname,(char *)0, (char *)0, (char *)0, (char *)0, 
712     (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, 
713     (char *)0, (char *)0, (char *)0);
714     if (sqlca.sqlcode < 0) 
715       goto bail_out;
716   }
717 /* # line 692 "myingres.sc" */  /* host code */
718       }
719    } else {
720 /* # line 694 "myingres.sc" */  /* connect */
721   {
722     IIsqInit(&sqlca);
723     IILQsidSessID(sess_id);
724     IIsqConnect(0,ingdbname,(char *)0, (char *)0, (char *)0, (char *)0, 
725     (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, 
726     (char *)0, (char *)0, (char *)0);
727     if (sqlca.sqlcode < 0) 
728       goto bail_out;
729   }
730 /* # line 697 "myingres.sc" */  /* host code */
731    }   
732 /* # line 701 "myingres.sc" */  /* host code */
733    dbconn = (INGconn *)malloc(sizeof(INGconn));
734    memset(dbconn, 0, sizeof(INGconn));
735    dbconn->dbname = bstrdup(ingdbname);
736    if (user != NULL) {
737       dbconn->user = bstrdup(ingdbuser);
738       dbconn->password = bstrdup(ingdbpasswd);
739    }
740    dbconn->session_id = sess_id;
741    dbconn->msg = (char *)malloc(257);
742    memset(dbconn->msg, 0, 257);
743    /*
744     * Switch to no default session for this thread undo default settings from SQL CONNECT.
745     */
746 /* # line 716 "myingres.sc" */  /* set_sql */
747   {
748     IILQssSetSqlio(11,(short *)0,1,30,sizeof(-97),(void *)IILQint(-97));
749   }
750 /* # line 718 "myingres.sc" */  /* host code */
751 bail_out:
752    return dbconn;
753 }
754 void INGsetDefaultLockingMode(INGconn *dbconn)
755 {
756    /*
757     * Set the default Ingres session locking mode:
758     *
759     * SET LOCKMODE provides four different parameters to govern
760     * the nature of locking in an INGRES session:
761     *
762     * Level: This refers to the level of granularity desired when
763     * the table is accessed. You can specify any of the following
764     * locking levels:
765     *
766     * row     Specifies locking at the level of the row (subject to
767     *         escalation criteria; see below)
768     * page    Specifies locking at the level of the data page (subject to
769     *         escalation criteria; see below)
770     * table   Specifies table-level locking in the database
771     * session Specifies the current default for your INGRES session
772     * system  Specifies that INGRES will start with page-level locking,
773     *         unless it estimates that more than Maxlocks pages will be
774     *         referenced, in which case table-level locking will be used.
775     *
776     * Readlock: This refers to locking in situations where table access
777     *           is required for reading data only (as opposed to updating
778     *           data). You can specify any of the following Readlock modes:
779     *
780     *    nolock     Specifies no locking when reading data
781     *    shared     Specifies the default mode of locking when reading data
782     *    exclusive  Specifies exclusive locking when reading data (useful in
783     *               "select-for-update" processing within a multi-statement
784     *               transaction)
785     *    system     Specifies the general Readlock default for the INGRES system
786     *
787     * Maxlocks: This refers to an escalation factor, or number of locks on
788     *           data pages, at which locking escalates from page-level
789     *           to table-level. The number of locks available to you is
790     *           dependent upon your system configuration. You can specify the
791     *           following Maxlocks escalation factors:
792     *
793     *    n       A specific (integer) number of page locks to allow before
794     *            escalating to table-level locking. The default "n" is 10,
795     *            and "n" must be greater than 0.
796     *    session Specifies the current Maxlocks default for your INGRES
797     *            session
798     *    system  Specifies the general Maxlocks default for the INGRES system
799     *
800     * Note: If you specify page-level locking, and the number of locks granted
801     * during a query exceeds the system-wide lock limit, or if the operating
802     * system's locking resources are depleted, locking escalates to table-level.
803     * This escalation occurs automatically and is independent of the user.
804     *
805     * Timeout: This refers to a time limit, expressed in seconds, for which
806     * a lock request should remain pending. If INGRES cannot grant the lock
807     * request within the specified time, then the query that requested the
808     * lock aborts. You can specify the following timeout characteristics:
809     *
810     *    n       A specific (integer) number of seconds to wait for a lock
811     *            (setting "n" to 0 requires INGRES to wait indefinitely for
812     *            the lock)
813     *    session Specifies the current timeout default for your INGRES
814     *            session (which is also the INGRES default)
815     *    system  Specifies the general timeout default for the INGRES system
816     *
817     */
818 /* # line 786 "myingres.sc" */  
819   
820   int sess_id;
821 /* # line 788 "myingres.sc" */  
822   
823    if (dbconn != NULL) {
824       /*
825        * Switch to the correct default session for this thread.
826        */
827       sess_id = dbconn->session_id;
828 /* # line 795 "myingres.sc" */  /* set_sql */
829   {
830     IILQssSetSqlio(11,(short *)0,1,30,sizeof(sess_id),&sess_id);
831   }
832 /* # line 797 "myingres.sc" */  /* set */
833   {
834     IIsqInit(&sqlca);
835     IIwritio(0,(short *)0,1,32,0,(char *)
836 "set LOCKMODE session where level=row, readlock=nolock");
837     IIsyncup((char *)0,0);
838   }
839 /* # line 799 "myingres.sc" */  /* host code */
840       /*
841        * Switch to no default session for this thread.
842        */
843 /* # line 802 "myingres.sc" */  /* set_sql */
844   {
845     IILQssSetSqlio(11,(short *)0,1,30,sizeof(-97),(void *)IILQint(-97));
846   }
847 /* # line 803 "myingres.sc" */  /* host code */
848    }
849 }
850 void INGdisconnectDB(INGconn *dbconn)
851 {
852 /* # line 808 "myingres.sc" */  
853   
854   int sess_id;
855 /* # line 810 "myingres.sc" */  
856   
857    if (dbconn != NULL) {
858       sess_id = dbconn->session_id;
859 /* # line 814 "myingres.sc" */  /* disconnect */
860   {
861     IIsqInit(&sqlca);
862     IILQsidSessID(sess_id);
863     IIsqDisconnect();
864   }
865 /* # line 816 "myingres.sc" */  /* host code */
866       free(dbconn->dbname);
867       if (dbconn->user) {
868          free(dbconn->user);
869       }
870       if (dbconn->password) {
871          free(dbconn->password);
872       }
873       free(dbconn->msg);
874       free(dbconn);
875    }
876 }
877 char *INGerrorMessage(const INGconn *dbconn)
878 {
879 /* # line 830 "myingres.sc" */  
880   
881   int sess_id;
882   char errbuf[256];
883 /* # line 833 "myingres.sc" */  
884   
885    if (dbconn != NULL) {
886       /*
887        * Switch to the correct default session for this thread.
888        */
889       sess_id = dbconn->session_id;
890 /* # line 840 "myingres.sc" */  /* set_sql */
891   {
892     IILQssSetSqlio(11,(short *)0,1,30,sizeof(sess_id),&sess_id);
893   }
894 /* # line 842 "myingres.sc" */  /* inquire_ingres */
895   {
896     IILQisInqSqlio((short *)0,1,32,255,errbuf,63);
897   }
898 /* # line 843 "myingres.sc" */  /* host code */
899       strncpy(dbconn->msg, errbuf, sizeof(dbconn->msg));
900       /*
901        * Switch to no default session for this thread.
902        */
903 /* # line 848 "myingres.sc" */  /* set_sql */
904   {
905     IILQssSetSqlio(11,(short *)0,1,30,sizeof(-97),(void *)IILQint(-97));
906   }
907 /* # line 849 "myingres.sc" */  /* host code */
908    }
909    return dbconn->msg;
910 }
911 /* # line 854 "myingres.sc" */  
912 #endif