]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/myingres.c
Add support for transactions. Normal operations for Ingres is to make things one...
[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 two of the GNU 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 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
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 INGcheck()
54 {
55    return (sqlca.sqlcode < 0) ? sqlca.sqlcode : 0;
56 }
57 short INGgetCols(INGconn *conn, const char *query, bool transaction)
58 {
59 /* # line 57 "myingres.sc" */   
60   
61   int sess_id;
62   char *stmt;
63 /* # line 60 "myingres.sc" */   
64   
65    short number = 1;
66    IISQLDA *sqlda;
67    sqlda = (IISQLDA *)malloc(IISQDA_HEAD_SIZE + (number * IISQDA_VAR_SIZE));
68    memset(sqlda, 0, (IISQDA_HEAD_SIZE + (number * IISQDA_VAR_SIZE)));
69    sqlda->sqln = number;
70    stmt = bstrdup(query);
71    /*
72     * Switch to the correct default session for this thread.
73     */
74    sess_id = conn->session_id;
75 /* # line 76 "myingres.sc" */   /* set_sql */
76   {
77     IILQssSetSqlio(11,(short *)0,1,30,sizeof(sess_id),&sess_id);
78   }
79 /* # line 78 "myingres.sc" */   /* prepare */
80   {
81     IIsqInit(&sqlca);
82     IIsqPrepare(0,(char *)"s1",(char *)0,0,stmt);
83   }
84 /* # line 79 "myingres.sc" */   /* host code */
85    if (INGcheck() < 0) {
86       number = -1;
87       goto bail_out;
88    }
89 /* # line 84 "myingres.sc" */   /* describe */
90   {
91     IIsqInit(&sqlca);
92     IIsqDescribe(0,(char *)"s1",sqlda,0);
93   }
94 /* # line 85 "myingres.sc" */   /* host code */
95    if (INGcheck() < 0) {
96       number = -1;
97       goto bail_out;
98    }
99    number = sqlda->sqld;
100 bail_out:
101    /*
102     * If we are not in a transaction we commit our work now.
103     */
104    if (!transaction) {
105 /* # line 97 "myingres.sc" */   /* commit */
106   {
107     IIsqInit(&sqlca);
108     IIxact(3);
109   }
110 /* # line 98 "myingres.sc" */   /* host code */
111    }
112    /*
113     * Switch to no default session for this thread.
114     */
115 /* # line 102 "myingres.sc" */  /* set_sql */
116   {
117     IILQssSetSqlio(11,(short *)0,1,30,sizeof(-97),(void *)IILQint(-97));
118   }
119 /* # line 103 "myingres.sc" */  /* host code */
120    free(stmt);
121    free(sqlda);
122    return number;
123 }
124 static inline IISQLDA *INGgetDescriptor(short numCols, const char *query)
125 {
126 /* # line 110 "myingres.sc" */  
127   
128   char *stmt;
129 /* # line 112 "myingres.sc" */  
130   
131    int i;
132    IISQLDA *sqlda;
133    sqlda = (IISQLDA *)malloc(IISQDA_HEAD_SIZE + (numCols * IISQDA_VAR_SIZE));
134    memset(sqlda, 0, (IISQDA_HEAD_SIZE + (numCols * IISQDA_VAR_SIZE)));
135    sqlda->sqln = numCols;
136    stmt = bstrdup(query);
137 /* # line 124 "myingres.sc" */  /* prepare */
138   {
139     IIsqInit(&sqlca);
140     IIsqPrepare(0,(char *)"s2",sqlda,0,stmt);
141   }
142 /* # line 126 "myingres.sc" */  /* host code */
143    free(stmt);
144    for (i = 0; i < sqlda->sqld; ++i) {
145       /*
146        * Negative type indicates nullable coulumns, so an indicator
147        * is allocated, otherwise it's null
148        */
149       if (sqlda->sqlvar[i].sqltype > 0) {
150          sqlda->sqlvar[i].sqlind = NULL;
151       } else {
152          sqlda->sqlvar[i].sqlind = (short *)malloc(sizeof(short));
153       }
154       /*
155        * Alloc space for variable like indicated in sqllen
156        * for date types sqllen is always 0 -> allocate by type
157        */
158       switch (abs(sqlda->sqlvar[i].sqltype)) {
159       case IISQ_TSW_TYPE:
160          sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSW_LEN);
161          break;
162       case IISQ_TSWO_TYPE:
163          sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSWO_LEN);
164          break;
165       case IISQ_TSTMP_TYPE:
166          sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN);
167          break;
168       default:
169          /*
170           * plus one to avoid zero mem allocs
171           */
172          sqlda->sqlvar[i].sqldata = (char *)malloc(sqlda->sqlvar[i].sqllen+1);
173          break;
174       }
175    }
176    return sqlda;
177 }
178 static void INGfreeDescriptor(IISQLDA *sqlda)
179 {
180    int i;
181    if (!sqlda) {
182       return;
183    }
184    for (i = 0; i < sqlda->sqld; ++i) {
185       if (sqlda->sqlvar[i].sqldata) {
186          free(sqlda->sqlvar[i].sqldata);
187       }
188       if (sqlda->sqlvar[i].sqlind) {
189          free(sqlda->sqlvar[i].sqlind);
190       }
191    }
192    free(sqlda);
193    sqlda = NULL;
194 }
195 static inline int INGgetTypeSize(IISQLVAR *ingvar)
196 {
197    int inglength = 0;
198    /*
199     * TODO: add date types (at least TSTMP,TSW TSWO)
200     */
201    switch (ingvar->sqltype) {
202    case IISQ_DTE_TYPE:
203       inglength = 25;
204       break;
205    case IISQ_MNY_TYPE:
206       inglength = 8;
207       break;
208    default:
209       inglength = ingvar->sqllen;
210       break;
211    }
212    return inglength;
213 }
214 static inline INGresult *INGgetINGresult(IISQLDA *sqlda)
215 {
216    int i;
217    INGresult *result = NULL;
218    if (!sqlda) {
219       return NULL;
220    }
221    result = (INGresult *)malloc(sizeof(INGresult));
222    memset(result, 0, sizeof(INGresult));
223    result->sqlda = sqlda;
224    result->num_fields = sqlda->sqld;
225    result->num_rows = 0;
226    result->first_row = NULL;
227    result->status = ING_EMPTY_RESULT;
228    result->act_row = NULL;
229    memset(result->numrowstring, 0, sizeof(result->numrowstring));
230    if (result->num_fields) {
231       result->fields = (INGRES_FIELD *)malloc(sizeof(INGRES_FIELD) * result->num_fields);
232       memset(result->fields, 0, sizeof(INGRES_FIELD) * result->num_fields);
233       for (i = 0; i < result->num_fields; ++i) {
234          memset(result->fields[i].name, 0, 34);
235          bstrncpy(result->fields[i].name, sqlda->sqlvar[i].sqlname.sqlnamec, sqlda->sqlvar[i].sqlname.sqlnamel);
236          result->fields[i].max_length = INGgetTypeSize(&sqlda->sqlvar[i]);
237          result->fields[i].type = abs(sqlda->sqlvar[i].sqltype);
238          result->fields[i].flags = (sqlda->sqlvar[i].sqltype < 0) ? 1 : 0;
239       }
240    }
241    return result;
242 }
243 static inline void INGfreeRowSpace(ING_ROW *row, IISQLDA *sqlda)
244 {
245    int i;
246    if (row == NULL || sqlda == NULL) {
247       return;
248    }
249    for (i = 0; i < sqlda->sqld; ++i) {
250       if (row->sqlvar[i].sqldata) {
251          free(row->sqlvar[i].sqldata);
252       }
253       if (row->sqlvar[i].sqlind) {
254          free(row->sqlvar[i].sqlind);
255       }
256    }
257    free(row->sqlvar);
258    free(row);
259 }
260 static void INGfreeINGresult(INGresult *ing_res)
261 {
262    int rows;
263    ING_ROW *rowtemp;
264    if (!ing_res) {
265       return;
266    }
267    /*
268     * Free all rows and fields, then res, not descriptor!
269     *
270     * Use of rows is a nasty workaround til I find the reason,
271     * why aggregates like max() don't work
272     */
273    rows = ing_res->num_rows;
274    ing_res->act_row = ing_res->first_row;
275    while (ing_res->act_row != NULL && rows > 0) {
276       rowtemp = ing_res->act_row->next;
277       INGfreeRowSpace(ing_res->act_row, ing_res->sqlda);
278       ing_res->act_row = rowtemp;
279       --rows;
280    }
281    if (ing_res->fields) {
282       free(ing_res->fields);
283    }
284    free(ing_res);
285 }
286 static inline ING_ROW *INGgetRowSpace(INGresult *ing_res)
287 {
288    int i;
289    unsigned short len; /* used for VARCHAR type length */
290    IISQLDA *sqlda = ing_res->sqlda;
291    ING_ROW *row = NULL;
292    IISQLVAR *vars = NULL;
293    row = (ING_ROW *)malloc(sizeof(ING_ROW));
294    memset(row, 0, sizeof(ING_ROW));
295    vars = (IISQLVAR *)malloc(sizeof(IISQLVAR) * sqlda->sqld);
296    memset(vars, 0, sizeof(IISQLVAR) * sqlda->sqld);
297    row->sqlvar = vars;
298    row->next = NULL;
299    for (i = 0; i < sqlda->sqld; ++i) {
300       /*
301        * Make strings out of the data, then the space and assign 
302        * (why string? at least it seems that way, looking into the sources)
303        */
304       vars[i].sqlind = (short *)malloc(sizeof(short));
305       if (sqlda->sqlvar[i].sqlind) {
306          memcpy(vars[i].sqlind,sqlda->sqlvar[i].sqlind,sizeof(short));
307       } else {
308          *vars[i].sqlind = NULL;
309       }
310       /*
311        * if sqlind pointer exists AND points to -1 -> column is 'null'
312        */
313       if ( *vars[i].sqlind && (*vars[i].sqlind == -1)) {
314          vars[i].sqldata = NULL;
315       } else {
316          switch (ing_res->fields[i].type) {
317          case IISQ_VCH_TYPE:
318             len = ((ING_VARCHAR *)sqlda->sqlvar[i].sqldata)->len;
319             vars[i].sqldata = (char *)malloc(len+1);
320             memcpy(vars[i].sqldata,sqlda->sqlvar[i].sqldata+2,len);
321             vars[i].sqldata[len] = '\0';
322             break;
323          case IISQ_CHA_TYPE:
324             vars[i].sqldata = (char *)malloc(ing_res->fields[i].max_length+1);
325             memcpy(vars[i].sqldata,sqlda->sqlvar[i].sqldata,sqlda->sqlvar[i].sqllen);
326             vars[i].sqldata[ing_res->fields[i].max_length] = '\0';
327             break;
328          case IISQ_INT_TYPE:
329             vars[i].sqldata = (char *)malloc(20);
330             memset(vars[i].sqldata, 0, 20);
331             switch (sqlda->sqlvar[i].sqllen) {
332             case 2:
333                bsnprintf(vars[i].sqldata, 20, "%d",*(short*)sqlda->sqlvar[i].sqldata);
334                break;
335             case 4:
336                bsnprintf(vars[i].sqldata, 20, "%ld",*(int*)sqlda->sqlvar[i].sqldata);
337                break;
338             case 8:
339                bsnprintf(vars[i].sqldata, 20, "%lld",*(long*)sqlda->sqlvar[i].sqldata);
340                break;
341             }
342             break;
343          case IISQ_TSTMP_TYPE:
344             vars[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN+1);
345             vars[i].sqldata[IISQ_TSTMP_LEN] = '\0';
346             break;
347          case IISQ_TSWO_TYPE:
348             vars[i].sqldata = (char *)malloc(IISQ_TSWO_LEN+1);
349             vars[i].sqldata[IISQ_TSWO_LEN] = '\0';
350             break;
351          case IISQ_TSW_TYPE:
352             vars[i].sqldata = (char *)malloc(IISQ_TSW_LEN+1);
353             vars[i].sqldata[IISQ_TSW_LEN] = '\0';
354             break;
355          }
356       }
357    }
358    return row;
359 }
360 static inline int INGfetchAll(const char *query, INGresult *ing_res)
361 {
362    int linecount = 0;
363    ING_ROW *row;
364    IISQLDA *desc;
365    int check = -1;
366    desc = ing_res->sqlda;
367 /* # line 380 "myingres.sc" */  /* host code */
368    if ((check = INGcheck()) < 0) {
369       return check;
370    }
371 /* # line 384 "myingres.sc" */  /* open */
372   {
373     IIsqInit(&sqlca);
374     IIcsOpen((char *)"c2",19193,19709);
375     IIwritio(0,(short *)0,1,32,0,(char *)"s2");
376     IIcsQuery((char *)"c2",19193,19709);
377   }
378 /* # line 385 "myingres.sc" */  /* host code */
379    if ((check = INGcheck()) < 0) {
380       return check;
381    }
382    /* for (linecount = 0; sqlca.sqlcode == 0; ++linecount) */
383    do {
384 /* # line 391 "myingres.sc" */  /* fetch */
385   {
386     IIsqInit(&sqlca);
387     if (IIcsRetScroll((char *)"c2",19193,19709,-1,-1) != 0) {
388       IIcsDaGet(0,desc);
389       IIcsERetrieve();
390     } /* IIcsRetrieve */
391   }
392 /* # line 393 "myingres.sc" */  /* host code */
393       if ( (sqlca.sqlcode == 0) || (sqlca.sqlcode == -40202) ) {
394          row = INGgetRowSpace(ing_res); /* alloc space for fetched row */
395          /*
396           * Initialize list when encountered first time
397           */
398          if (ing_res->first_row == 0) {
399             ing_res->first_row = row; /* head of the list */
400             ing_res->first_row->next = NULL;
401             ing_res->act_row = ing_res->first_row;
402          }      
403          ing_res->act_row->next = row; /* append row to old act_row */
404          ing_res->act_row = row; /* set row as act_row */
405          row->row_number = linecount;
406          ++linecount;
407       }
408    } while ( (sqlca.sqlcode == 0) || (sqlca.sqlcode == -40202) );
409 /* # line 411 "myingres.sc" */  /* close */
410   {
411     IIsqInit(&sqlca);
412     IIcsClose((char *)"c2",19193,19709);
413   }
414 /* # line 413 "myingres.sc" */  /* host code */
415    ing_res->status = ING_COMMAND_OK;
416    ing_res->num_rows = linecount;
417    return linecount;
418 }
419 static inline ING_STATUS INGresultStatus(INGresult *res)
420 {
421    if (res == NULL) {
422       return ING_NO_RESULT;
423    } else {
424       return res->status;
425    }
426 }
427 static void INGrowSeek(INGresult *res, int row_number)
428 {
429    ING_ROW *trow = NULL;
430    if (res->act_row->row_number == row_number) {
431       return;
432    }
433    /*
434     * TODO: real error handling
435     */
436    if (row_number<0 || row_number>res->num_rows) {
437       return;
438    }
439    for (trow = res->first_row; trow->row_number != row_number; trow = trow->next) ;
440    res->act_row = trow;
441    /*
442     * Note - can be null - if row_number not found, right?
443     */
444 }
445 char *INGgetvalue(INGresult *res, int row_number, int column_number)
446 {
447    if (row_number != res->act_row->row_number) {
448       INGrowSeek(res, row_number);
449    }
450    return res->act_row->sqlvar[column_number].sqldata;
451 }
452 bool INGgetisnull(INGresult *res, int row_number, int column_number)
453 {
454    if (row_number != res->act_row->row_number) {
455       INGrowSeek(res, row_number);
456    }
457    return (*res->act_row->sqlvar[column_number].sqlind == -1) ? true : false;
458 }
459 int INGntuples(const INGresult *res)
460 {
461    return res->num_rows;
462 }
463 int INGnfields(const INGresult *res)
464 {
465    return res->num_fields;
466 }
467 char *INGfname(const INGresult *res, int column_number)
468 {
469    if ((column_number > res->num_fields) || (column_number < 0)) {
470       return NULL;
471    } else {
472       return res->fields[column_number].name;
473    }
474 }
475 short INGftype(const INGresult *res, int column_number)
476 {
477    return res->fields[column_number].type;
478 }
479 int INGexec(INGconn *conn, const char *query, bool transaction)
480 {
481    int check;
482 /* # line 494 "myingres.sc" */  
483   
484   int sess_id;
485   int rowcount;
486   char *stmt;
487 /* # line 498 "myingres.sc" */  
488   
489    stmt = bstrdup(query);
490    rowcount = -1;
491    /*
492     * Switch to the correct default session for this thread.
493     */
494    sess_id = conn->session_id;
495 /* # line 507 "myingres.sc" */  /* set_sql */
496   {
497     IILQssSetSqlio(11,(short *)0,1,30,sizeof(sess_id),&sess_id);
498   }
499 /* # line 508 "myingres.sc" */  /* execute */
500   {
501     IIsqInit(&sqlca);
502     IIsqExImmed(stmt);
503     IIsyncup((char *)0,0);
504   }
505 /* # line 510 "myingres.sc" */  /* host code */
506    free(stmt);
507    if ((check = INGcheck()) < 0) {
508       rowcount = check;
509       goto bail_out;
510    }
511 /* # line 517 "myingres.sc" */  /* inquire_ingres */
512   {
513     IILQisInqSqlio((short *)0,1,30,sizeof(rowcount),&rowcount,8);
514   }
515 /* # line 518 "myingres.sc" */  /* host code */
516    if ((check = INGcheck()) < 0) {
517       rowcount = check;
518       goto bail_out;
519    }
520 bail_out:
521    /*
522     * If we are not in a transaction we commit our work now.
523     */
524    if (!transaction) {
525 /* # line 528 "myingres.sc" */  /* commit */
526   {
527     IIsqInit(&sqlca);
528     IIxact(3);
529   }
530 /* # line 529 "myingres.sc" */  /* host code */
531    }
532    /*
533     * Switch to no default session for this thread.
534     */
535 /* # line 533 "myingres.sc" */  /* set_sql */
536   {
537     IILQssSetSqlio(11,(short *)0,1,30,sizeof(-97),(void *)IILQint(-97));
538   }
539 /* # line 534 "myingres.sc" */  /* host code */
540    return rowcount;
541 }
542 INGresult *INGquery(INGconn *conn, const char *query, bool transaction)
543 {
544    /*
545     * TODO: error handling
546     */
547    IISQLDA *desc = NULL;
548    INGresult *res = NULL;
549    int rows = -1;
550    int cols = INGgetCols(conn, query);
551 /* # line 546 "myingres.sc" */  
552   
553   int sess_id;
554 /* # line 548 "myingres.sc" */  
555   
556    /*
557     * Switch to the correct default session for this thread.
558     */
559    sess_id = conn->session_id;
560 /* # line 554 "myingres.sc" */  /* set_sql */
561   {
562     IILQssSetSqlio(11,(short *)0,1,30,sizeof(sess_id),&sess_id);
563   }
564 /* # line 556 "myingres.sc" */  /* host code */
565    desc = INGgetDescriptor(cols, query);
566    if (!desc) {
567       goto bail_out;
568    }
569    res = INGgetINGresult(desc);
570    if (!res) {
571       goto bail_out;
572    }
573    rows = INGfetchAll(query, res);
574    if (rows < 0) {
575       INGfreeDescriptor(desc);
576       INGfreeINGresult(res);
577       res = NULL;
578       goto bail_out;
579    }
580 bail_out:
581    /*
582     * If we are not in a transaction we commit our work now.
583     */
584    if (!transaction) {
585 /* # line 580 "myingres.sc" */  /* commit */
586   {
587     IIsqInit(&sqlca);
588     IIxact(3);
589   }
590 /* # line 581 "myingres.sc" */  /* host code */
591    }
592    /*
593     * Switch to no default session for this thread.
594     */
595 /* # line 585 "myingres.sc" */  /* set_sql */
596   {
597     IILQssSetSqlio(11,(short *)0,1,30,sizeof(-97),(void *)IILQint(-97));
598   }
599 /* # line 586 "myingres.sc" */  /* host code */
600    return res;
601 }
602 void INGclear(INGresult *res)
603 {
604    if (res == NULL) {
605       return;
606    }
607    INGfreeDescriptor(res->sqlda);
608    INGfreeINGresult(res);
609 }
610 void INGcommit(onst INGconn *conn)
611 {
612 /* # line 601 "myingres.sc" */  
613   
614   int sess_id;
615 /* # line 603 "myingres.sc" */  
616   
617    if (dbconn != NULL) {
618       sess_id = dbconn->session_id;
619 /* # line 607 "myingres.sc" */  /* disconnect */
620   {
621     IIsqInit(&sqlca);
622     IILQsidSessID(sess_id);
623     IIsqDisconnect();
624   }
625 /* # line 609 "myingres.sc" */  /* host code */
626       /*
627        * Commit our work.
628        */
629 /* # line 612 "myingres.sc" */  /* commit */
630   {
631     IIsqInit(&sqlca);
632     IIxact(3);
633   }
634 /* # line 614 "myingres.sc" */  /* host code */
635       /*
636        * Switch to no default session for this thread.
637        */
638 /* # line 617 "myingres.sc" */  /* set_sql */
639   {
640     IILQssSetSqlio(11,(short *)0,1,30,sizeof(-97),(void *)IILQint(-97));
641   }
642 /* # line 618 "myingres.sc" */  /* host code */
643    }
644 }
645 INGconn *INGconnectDB(char *dbname, char *user, char *passwd, int session_id)
646 {
647    INGconn *dbconn;
648    if (dbname == NULL || strlen(dbname) == 0) {
649       return NULL;
650    }
651    dbconn = (INGconn *)malloc(sizeof(INGconn));
652    memset(dbconn, 0, sizeof(INGconn));
653 /* # line 632 "myingres.sc" */  
654   
655   char ingdbname[24];
656   char ingdbuser[32];
657   char ingdbpasswd[32];
658   int sess_id;
659 /* # line 637 "myingres.sc" */  
660   
661    sess_id = session_id;
662    bstrncpy(ingdbname, dbname, sizeof(ingdbname));
663    if (user != NULL) {
664       bstrncpy(ingdbuser, user, sizeof(ingdbuser));
665       if (passwd != NULL) {
666          bstrncpy(ingdbpasswd, passwd, sizeof(ingdbpasswd));
667       } else {
668          memset(ingdbpasswd, 0, sizeof(ingdbpasswd));
669       }
670 /* # line 649 "myingres.sc" */  /* connect */
671   {
672     IIsqInit(&sqlca);
673     IILQsidSessID(sess_id);
674     IIsqUser(ingdbuser);
675     IIsqConnect(0,ingdbname,(char *)"-dbms_password",ingdbpasswd,(char *)0, 
676     (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, 
677     (char *)0, (char *)0, (char *)0, (char *)0);
678   }
679 /* # line 654 "myingres.sc" */  /* host code */
680    } else {
681 /* # line 655 "myingres.sc" */  /* connect */
682   {
683     IIsqInit(&sqlca);
684     IILQsidSessID(sess_id);
685     IIsqConnect(0,ingdbname,(char *)0, (char *)0, (char *)0, (char *)0, 
686     (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, 
687     (char *)0, (char *)0, (char *)0);
688   }
689 /* # line 658 "myingres.sc" */  /* host code */
690    }   
691    if (INGcheck() < 0) {
692       return NULL;
693    }
694    bstrncpy(dbconn->dbname, ingdbname, sizeof(dbconn->dbname));
695    bstrncpy(dbconn->user, ingdbuser, sizeof(dbconn->user));
696    bstrncpy(dbconn->password, ingdbpasswd, sizeof(dbconn->password));
697    dbconn->session_id = sess_id;
698    dbconn->msg = (char*)malloc(257);
699    memset(dbconn->msg, 0, 257);
700    /*
701     * Switch to no default session for this thread undo default settings from SQL CONNECT.
702     */
703 /* # line 673 "myingres.sc" */  /* set_sql */
704   {
705     IILQssSetSqlio(11,(short *)0,1,30,sizeof(-97),(void *)IILQint(-97));
706   }
707 /* # line 675 "myingres.sc" */  /* host code */
708    return dbconn;
709 }
710 void INGdisconnectDB(INGconn *dbconn)
711 {
712 /* # line 680 "myingres.sc" */  
713   
714   int sess_id;
715 /* # line 682 "myingres.sc" */  
716   
717    if (dbconn != NULL) {
718       sess_id = dbconn->session_id;
719 /* # line 686 "myingres.sc" */  /* disconnect */
720   {
721     IIsqInit(&sqlca);
722     IILQsidSessID(sess_id);
723     IIsqDisconnect();
724   }
725 /* # line 688 "myingres.sc" */  /* host code */
726       free(dbconn->msg);
727       free(dbconn);
728    }
729 }
730 char *INGerrorMessage(const INGconn *conn)
731 {
732 /* # line 695 "myingres.sc" */  
733   
734   char errbuf[256];
735 /* # line 697 "myingres.sc" */  
736   
737 /* # line 699 "myingres.sc" */  /* inquire_ingres */
738   {
739     IILQisInqSqlio((short *)0,1,32,255,errbuf,63);
740   }
741 /* # line 700 "myingres.sc" */  /* host code */
742    memcpy(conn->msg, &errbuf, 256);
743    return conn->msg;
744 }
745 char *INGcmdTuples(INGresult *res)
746 {
747    return res->numrowstring;
748 }
749 /* TODO?
750 int INGputCopyEnd(INGconn *conn, const char *errormsg);
751 int INGputCopyData(INGconn *conn, const char *buffer, int nbytes);
752 */
753 /* # line 714 "myingres.sc" */  
754 #endif