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