+++ /dev/null
-/*
- Bacula® - The Network Backup Solution
-
- Copyright (C) 2003-2007 Free Software Foundation Europe e.V.
-
- The main author of Bacula is Kern Sibbald, with contributions from
- many others, a complete list can be found in the file AUTHORS.
- This program is Free Software; you can redistribute it and/or
- modify it under the terms of version two of the GNU General Public
- License as published by the Free Software Foundation and included
- in the file LICENSE.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
- Bacula® is a registered trademark of Kern Sibbald.
- The licensor of Bacula is the Free Software Foundation Europe
- (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
- Switzerland, email:ftf@fsfeurope.org.
-*/
-/*
- * Bacula Catalog Database routines specific to Ingres
- * These are Ingres specific routines
- *
- * Stefan Reddig, June 2009
- * based uopn work done
- * by Dan Langille, December 2003 and
- * by Kern Sibbald, March 2000
- *
- */
-
-
-/* The following is necessary so that we do not include
- * the dummy external definition of DB.
- */
-#define __SQL_C /* indicate that this is sql.c */
-
-#include "bacula.h"
-#include "cats.h"
-
-#ifdef HAVE_INGRES
-
-#include "myingres.h"
-
-/* -----------------------------------------------------------------------
- *
- * Ingres dependent defines and subroutines
- *
- * -----------------------------------------------------------------------
- */
-
-/* List of open databases */ /* SRE: needed for ingres? */
-static BQUEUE db_list = {&db_list, &db_list};
-
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/*
- * Retrieve database type
- */
-const char *
-db_get_type(void)
-{
- return "Ingres";
-}
-
-/*
- * Initialize database data structure. In principal this should
- * never have errors, or it is really fatal.
- */
-B_DB *
-db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char *db_password,
- const char *db_address, int db_port, const char *db_socket,
- int mult_db_connections)
-{
- B_DB *mdb;
-
- if (!db_user) {
- Jmsg(jcr, M_FATAL, 0, _("A user name for Ingres must be supplied.\n"));
- return NULL;
- }
- P(mutex); /* lock DB queue */
- if (!mult_db_connections) {
- /* Look to see if DB already open */
- for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
- if (bstrcmp(mdb->db_name, db_name) &&
- bstrcmp(mdb->db_address, db_address) &&
- mdb->db_port == db_port) {
- Dmsg2(100, "DB REopen %d %s\n", mdb->ref_count, db_name);
- mdb->ref_count++;
- V(mutex);
- return mdb; /* already open */
- }
- }
- }
- Dmsg0(100, "db_open first time\n");
- mdb = (B_DB *)malloc(sizeof(B_DB));
- memset(mdb, 0, sizeof(B_DB));
- mdb->db_name = bstrdup(db_name);
- mdb->db_user = bstrdup(db_user);
- if (db_password) {
- mdb->db_password = bstrdup(db_password);
- }
- if (db_address) {
- mdb->db_address = bstrdup(db_address);
- }
- if (db_socket) {
- mdb->db_socket = bstrdup(db_socket);
- }
- mdb->db_port = db_port;
- mdb->have_insert_id = TRUE;
- mdb->errmsg = get_pool_memory(PM_EMSG); /* get error message buffer */
- *mdb->errmsg = 0;
- mdb->cmd = get_pool_memory(PM_EMSG); /* get command buffer */
- mdb->cached_path = get_pool_memory(PM_FNAME);
- mdb->cached_path_id = 0;
- mdb->ref_count = 1;
- mdb->fname = get_pool_memory(PM_FNAME);
- mdb->path = get_pool_memory(PM_FNAME);
- mdb->esc_name = get_pool_memory(PM_FNAME);
- mdb->esc_path = get_pool_memory(PM_FNAME);
- mdb->allow_transactions = mult_db_connections;
- qinsert(&db_list, &mdb->bq); /* put db in list */
- V(mutex);
- return mdb;
-}
-
-/* Check that the database correspond to the encoding we want */
-static bool check_database_encoding(JCR *jcr, B_DB *mdb)
-{
-/* SRE: TODO! Needed?
- SQL_ROW row;
- int ret=false;
-
- if (!db_sql_query(mdb, "SELECT getdatabaseencoding()", NULL, NULL)) {
- Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
- return false;
- }
-
- if ((row = sql_fetch_row(mdb)) == NULL) {
- Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
- Jmsg(jcr, M_ERROR, 0, "Can't check database encoding %s", mdb->errmsg);
- } else {
- ret = bstrcmp(row[0], "SQL_ASCII");
- if (!ret) {
- Mmsg(mdb->errmsg,
- _("Encoding error for database \"%s\". Wanted SQL_ASCII, got %s\n"),
- mdb->db_name, row[0]);
- Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
- Dmsg1(50, "%s", mdb->errmsg);
- }
- }
- return ret;
-*/
- return true;
-}
-
-/*
- * Check for errors in DBMS work
- */
-static int sql_check(B_DB *mdb)
-{
- return INGcheck();
-}
-
-/*
- * Now actually open the database. This can generate errors,
- * which are returned in the errmsg
- *
- * DO NOT close the database or free(mdb) here !!!!
- */
-int
-db_open_database(JCR *jcr, B_DB *mdb)
-{
- int errstat;
- char buf[10], *port;
-
- P(mutex);
- if (mdb->connected) {
- V(mutex);
- return 1;
- }
- mdb->connected = false;
-
- if ((errstat=rwl_init(&mdb->lock)) != 0) {
- berrno be;
- Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"),
- be.bstrerror(errstat));
- V(mutex);
- return 0;
- }
-
- if (mdb->db_port) {
- bsnprintf(buf, sizeof(buf), "%d", mdb->db_port);
- port = buf;
- } else {
- port = NULL;
- }
-
- mdb->db = INGconnectDB(mdb->db_name, mdb->db_user, mdb->db_password);
-
- Dmsg0(50, "Ingres real CONNECT done\n");
- Dmsg3(50, "db_user=%s db_name=%s db_password=%s\n", mdb->db_user, mdb->db_name,
- mdb->db_password==NULL?"(NULL)":mdb->db_password);
-
- if (sql_check(mdb)) {
- Mmsg2(&mdb->errmsg, _("Unable to connect to Ingres server.\n"
- "Database=%s User=%s\n"
- "It is probably not running or your password is incorrect.\n"),
- mdb->db_name, mdb->db_user);
- V(mutex);
- return 0;
- }
-
- mdb->connected = true;
-
- if (!check_tables_version(jcr, mdb)) {
- V(mutex);
- return 0;
- }
-
- //sql_query(mdb, "SET datestyle TO 'ISO, YMD'");
-
- /* check that encoding is SQL_ASCII */
- check_database_encoding(jcr, mdb);
-
- V(mutex);
- return 1;
-}
-
-void
-db_close_database(JCR *jcr, B_DB *mdb)
-{
- if (!mdb) {
- return;
- }
- db_end_transaction(jcr, mdb);
- P(mutex);
- sql_free_result(mdb);
- mdb->ref_count--;
- if (mdb->ref_count == 0) {
- qdchain(&mdb->bq);
- if (mdb->connected && mdb->db) {
- sql_close(mdb);
- }
- rwl_destroy(&mdb->lock);
- free_pool_memory(mdb->errmsg);
- free_pool_memory(mdb->cmd);
- free_pool_memory(mdb->cached_path);
- free_pool_memory(mdb->fname);
- free_pool_memory(mdb->path);
- free_pool_memory(mdb->esc_name);
- free_pool_memory(mdb->esc_path);
- if (mdb->db_name) {
- free(mdb->db_name);
- }
- if (mdb->db_user) {
- free(mdb->db_user);
- }
- if (mdb->db_password) {
- free(mdb->db_password);
- }
- if (mdb->db_address) {
- free(mdb->db_address);
- }
- if (mdb->db_socket) {
- free(mdb->db_socket);
- }
- free(mdb);
- }
- V(mutex);
-}
-
-void db_thread_cleanup()
-{ }
-
-/*
- * Return the next unique index (auto-increment) for
- * the given table. Return NULL on error.
- *
- * For Ingres, NULL causes the auto-increment value SRE: true?
- * to be updated.
- */
-int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index)
-{
- strcpy(index, "NULL");
- return 1;
-}
-
-
-/*
- * Escape strings so that Ingres is happy
- *
- * NOTE! len is the length of the old string. Your new
- * string must be long enough (max 2*old+1) to hold
- * the escaped output.
- * SRE: TODO!
- */
-void
-db_escape_string(JCR *jcr, B_DB *mdb, char *snew, char *old, int len)
-{
-/*
- int error;
-
- PQescapeStringConn(mdb->db, snew, old, len, &error);
- if (error) {
- Jmsg(jcr, M_FATAL, 0, _("PQescapeStringConn returned non-zero.\n"));*/
- /* error on encoding, probably invalid multibyte encoding in the source string
- see PQescapeStringConn documentation for details. */
-/* Dmsg0(500, "PQescapeStringConn failed\n");
- }*/
-}
-
-/*
- * Submit a general SQL command (cmd), and for each row returned,
- * the sqlite_handler is called with the ctx.
- */
-bool db_sql_query(B_DB *mdb, const char *query, DB_RESULT_HANDLER *result_handler, void *ctx)
-{
- SQL_ROW row;
-
- Dmsg0(500, "db_sql_query started\n");
-
- db_lock(mdb);
- if (sql_query(mdb, query) != 0) {
- Mmsg(mdb->errmsg, _("Query failed: %s: ERR=%s\n"), query, sql_strerror(mdb));
- db_unlock(mdb);
- Dmsg0(500, "db_sql_query failed\n");
- return false;
- }
- Dmsg0(500, "db_sql_query succeeded. checking handler\n");
-
- if (result_handler != NULL) {
- Dmsg0(500, "db_sql_query invoking handler\n");
- if ((mdb->result = sql_store_result(mdb)) != NULL) {
- int num_fields = sql_num_fields(mdb);
-
- Dmsg0(500, "db_sql_query sql_store_result suceeded\n");
- while ((row = sql_fetch_row(mdb)) != NULL) {
-
- Dmsg0(500, "db_sql_query sql_fetch_row worked\n");
- if (result_handler(ctx, num_fields, row))
- break;
- }
-
- sql_free_result(mdb);
- }
- }
- db_unlock(mdb);
-
- Dmsg0(500, "db_sql_query finished\n");
-
- return true;
-}
-
-/*
- * Close database connection
- */
-void my_ingres_close(B_DB *mdb)
-{
- INGdisconnectDB(mdb->db);
- //SRE: error handling?
-}
-
-INGRES_ROW my_ingres_fetch_row(B_DB *mdb)
-{
- int j;
- INGRES_ROW row = NULL; // by default, return NULL
-
- Dmsg0(500, "my_ingres_fetch_row start\n");
-
- if (!mdb->row || mdb->row_size < mdb->num_fields) {
- int num_fields = mdb->num_fields;
- Dmsg1(500, "we have need space of %d bytes\n", sizeof(char *) * mdb->num_fields);
-
- if (mdb->row) {
- Dmsg0(500, "my_ingres_fetch_row freeing space\n");
- free(mdb->row);
- }
- num_fields += 20; /* add a bit extra */
- mdb->row = (INGRES_ROW)malloc(sizeof(char *) * num_fields);
- mdb->row_size = num_fields;
-
- // now reset the row_number now that we have the space allocated
- mdb->row_number = 0;
- }
-
- // if still within the result set
- if (mdb->row_number < mdb->num_rows) {
- Dmsg2(500, "my_ingres_fetch_row row number '%d' is acceptable (0..%d)\n", mdb->row_number, mdb->num_rows);
- // get each value from this row
- for (j = 0; j < mdb->num_fields; j++) {
- mdb->row[j] = INGgetvalue(mdb->result, mdb->row_number, j);
- Dmsg2(500, "my_ingres_fetch_row field '%d' has value '%s'\n", j, mdb->row[j]);
- }
- // increment the row number for the next call
- mdb->row_number++;
-
- row = mdb->row;
- } else {
- Dmsg2(500, "my_ingres_fetch_row row number '%d' is NOT acceptable (0..%d)\n", mdb->row_number, mdb->num_rows);
- }
-
- Dmsg1(500, "my_ingres_fetch_row finishes returning %p\n", row);
-
- return row;
-}
-
-
-int my_ingres_max_length(B_DB *mdb, int field_num) {
- //
- // for a given column, find the max length
- //
- int max_length;
- int i;
- int this_length;
-
- max_length = 0;
- for (i = 0; i < mdb->num_rows; i++) {
- if (INGgetisnull(mdb->result, i, field_num)) {
- this_length = 4; // "NULL"
- } else {
- this_length = cstrlen(INGgetvalue(mdb->result, i, field_num));
- }
-
- if (max_length < this_length) {
- max_length = this_length;
- }
- }
-
- return max_length;
-}
-
-INGRES_FIELD * my_ingres_fetch_field(B_DB *mdb)
-{
- int i;
-
- Dmsg0(500, "my_ingres_fetch_field starts\n");
-
- if (!mdb->fields || mdb->fields_size < mdb->num_fields) {
- if (mdb->fields) {
- free(mdb->fields);
- }
- Dmsg1(500, "allocating space for %d fields\n", mdb->num_fields);
- mdb->fields = (INGRES_FIELD *)malloc(sizeof(INGRES_FIELD) * mdb->num_fields);
- mdb->fields_size = mdb->num_fields;
-
- for (i = 0; i < mdb->num_fields; i++) {
- Dmsg1(500, "filling field %d\n", i);
- strcpy(mdb->fields[i].name,INGfname(mdb->result, i));
- mdb->fields[i].max_length = my_ingres_max_length(mdb, i);
- mdb->fields[i].type = INGftype(mdb->result, i);
- mdb->fields[i].flags = 0;
-
- Dmsg4(500, "my_ingres_fetch_field finds field '%s' has length='%d' type='%d' and IsNull=%d\n",
- mdb->fields[i].name, mdb->fields[i].max_length, mdb->fields[i].type,
- mdb->fields[i].flags);
- } // end for
- } // end if
-
- // increment field number for the next time around
-
- Dmsg0(500, "my_ingres_fetch_field finishes\n");
- return &mdb->fields[mdb->field_number++];
-}
-
-void my_ingres_data_seek(B_DB *mdb, int row)
-{
- // set the row number to be returned on the next call
- // to my_ingres_fetch_row
- mdb->row_number = row;
-}
-
-void my_ingres_field_seek(B_DB *mdb, int field)
-{
- mdb->field_number = field;
-}
-
-/*
- * Note, if this routine returns 1 (failure), Bacula expects
- * that no result has been stored.
- * This is where QUERY_DB comes with Ingres. SRE: true?
- *
- * Returns: 0 on success
- * 1 on failure
- *
- */
-int my_ingres_query(B_DB *mdb, const char *query)
-{
- Dmsg0(500, "my_ingres_query started\n");
- // We are starting a new query. reset everything.
- mdb->num_rows = -1;
- mdb->row_number = -1;
- mdb->field_number = -1;
-
- if (mdb->result) {
- INGclear(mdb->result); /* hmm, someone forgot to free?? */
- mdb->result = NULL;
- }
-
- Dmsg1(500, "my_ingres_query starts with '%s'\n", query);
- mdb->result = INGexec(mdb->db, query);
- if (!mdb->result) {
- Dmsg1(50, "Query failed: %s\n", query);
- goto bail_out;
- }
-
- mdb->status = INGresultStatus(mdb->result);
- if (mdb->status == ING_COMMAND_OK) {
- Dmsg1(500, "we have a result\n", query);
-
- // how many fields in the set?
- mdb->num_fields = (int)INGnfields(mdb->result);
- Dmsg1(500, "we have %d fields\n", mdb->num_fields);
-
- mdb->num_rows = INGntuples(mdb->result);
- Dmsg1(500, "we have %d rows\n", mdb->num_rows);
-
- mdb->status = 0; /* succeed */
- } else {
- Dmsg1(50, "Result status failed: %s\n", query);
- goto bail_out;
- }
-
- Dmsg0(500, "my_ingres_query finishing\n");
- return mdb->status;
-
-bail_out:
- Dmsg1(500, "we failed\n", query);
- INGclear(mdb->result);
- mdb->result = NULL;
- mdb->status = 1; /* failed */
- return mdb->status;
-}
-
-void my_ingres_free_result(B_DB *mdb)
-{
-
- db_lock(mdb);
- if (mdb->result) {
- INGclear(mdb->result);
- mdb->result = NULL;
- }
-
- if (mdb->row) {
- free(mdb->row);
- mdb->row = NULL;
- }
-
- if (mdb->fields) {
- free(mdb->fields);
- mdb->fields = NULL;
- }
- db_unlock(mdb);
-}
-
-int my_ingres_currval(B_DB *mdb, const char *table_name)
-{
- // TODO!
- return -1;
-}
-
-#ifdef HAVE_BATCH_FILE_INSERT
-
-int my_ingres_batch_start(JCR *jcr, B_DB *mdb)
-{
- //TODO!
- return ING_ERROR;
-}
-
-/* set error to something to abort operation */
-int my_ingres_batch_end(JCR *jcr, B_DB *mdb, const char *error)
-{
- //TODO!
- return ING_ERROR;
-}
-
-int my_ingres_batch_insert(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
-{
- //TODO!
- return ING_ERROR;
-}
-
-#endif /* HAVE_BATCH_FILE_INSERT */
-
-/*
- * Escape strings so that Ingres is happy on COPY
- *
- * NOTE! len is the length of the old string. Your new
- * string must be long enough (max 2*old+1) to hold
- * the escaped output.
- */
-char *my_ingres_copy_escape(char *dest, char *src, size_t len)
-{
- /* we have to escape \t, \n, \r, \ */
- char c = '\0' ;
-
- while (len > 0 && *src) {
- switch (*src) {
- case '\n':
- c = 'n';
- break;
- case '\\':
- c = '\\';
- break;
- case '\t':
- c = 't';
- break;
- case '\r':
- c = 'r';
- break;
- default:
- c = '\0' ;
- }
-
- if (c) {
- *dest = '\\';
- dest++;
- *dest = c;
- } else {
- *dest = *src;
- }
-
- len--;
- src++;
- dest++;
- }
-
- *dest = '\0';
- return dest;
-}
-
-#ifdef HAVE_BATCH_FILE_INSERT
-const char *my_ingres_batch_lock_path_query =
- "BEGIN; LOCK TABLE Path IN SHARE ROW EXCLUSIVE MODE";
-
-
-const char *my_ingres_batch_lock_filename_query =
- "BEGIN; LOCK TABLE Filename IN SHARE ROW EXCLUSIVE MODE";
-
-const char *my_ingres_batch_unlock_tables_query = "COMMIT";
-
-const char *my_ingres_batch_fill_path_query =
- "INSERT INTO Path (Path) "
- "SELECT a.Path FROM "
- "(SELECT DISTINCT Path FROM batch) AS a "
- "WHERE NOT EXISTS (SELECT Path FROM Path WHERE Path = a.Path) ";
-
-
-const char *my_ingres_batch_fill_filename_query =
- "INSERT INTO Filename (Name) "
- "SELECT a.Name FROM "
- "(SELECT DISTINCT Name FROM batch) as a "
- "WHERE NOT EXISTS "
- "(SELECT Name FROM Filename WHERE Name = a.Name)";
-#endif /* HAVE_BATCH_FILE_INSERT */
-
-#endif /* HAVE_INGRES */
+++ /dev/null
-#!/bin/sh
-#
-# shell script to create Bacula PostgreSQL tables
-#
-bindir=@SQL_BINDIR@
-db_name=@db_name@
-
-sql $* ${db_name}
+++ /dev/null
-
-#include "bacula.h"
-#include "cats.h"
-
-#ifdef HAVE_INGRES
-
-#include <eqdefc.h>
-# include <eqsqlca.h>
-extern IISQLCA sqlca; /* SQL Communications Area */
-#include <eqsqlda.h>
-
-#include "myingres.h"
-#define INGRES_DEBUG 0
-#define DEBB(x) if (INGRES_DEBUG >= x) {
-#define DEBE }
-
-/* ---Implementations--- */
-int INGcheck()
-{
- char errbuf[256];
- if (sqlca.sqlcode < 0)
- {
-/* # line 23 "myingres.sc" */ /* inquire_ingres */
- {
- IILQisInqSqlio((short *)0,1,32,255,errbuf,63);
- }
-/* # line 24 "myingres.sc" */ /* host code */
- printf("Ingres-DBMS-Fehler: %s\n", errbuf);
- return sqlca.sqlcode;
- }
- else
- return 0;
-}
-short INGgetCols(const char *stmt)
-{
- short number = 1;
- IISQLDA *sqlda;
- sqlda = (IISQLDA *)calloc(1,IISQDA_HEAD_SIZE + (number * IISQDA_VAR_SIZE));
- if (sqlda == (IISQLDA *)0)
- { printf("Failure allocating %d SQLDA elements\n",number); }
- sqlda->sqln = number;
- char stmt_buffer[2000];
- strcpy(stmt_buffer,stmt);
-/* # line 46 "myingres.sc" */ /* prepare */
- {
- IIsqInit(&sqlca);
- IIsqPrepare(0,(char *)"s1",(char *)0,0,stmt_buffer);
- }
-/* # line 47 "myingres.sc" */ /* describe */
- {
- IIsqInit(&sqlca);
- IIsqDescribe(0,(char *)"s1",sqlda,0);
- }
-/* # line 49 "myingres.sc" */ /* host code */
- number = sqlda->sqld;
- free(sqlda);
- return number;
-}
-IISQLDA *INGgetDescriptor(short numCols, const char *stmt)
-{
- IISQLDA *sqlda;
- sqlda = (IISQLDA *)calloc(1,IISQDA_HEAD_SIZE + (numCols * IISQDA_VAR_SIZE));
- if (sqlda == (IISQLDA *)0)
- { printf("Failure allocating %d SQLDA elements\n",numCols); }
- sqlda->sqln = numCols;
- char stmt_buffer[2000];
- strcpy(stmt_buffer,stmt);
-/* # line 69 "myingres.sc" */ /* prepare */
- {
- IIsqInit(&sqlca);
- IIsqPrepare(0,(char *)"s2",sqlda,0,stmt_buffer);
- }
-/* # line 71 "myingres.sc" */ /* host code */
- int i;
- for (i=0;i<sqlda->sqld;++i)
- {
- sqlda->sqlvar[i].sqldata =
- (char *)malloc(sqlda->sqlvar[i].sqllen);
- if (sqlda->sqlvar[i].sqldata == (char *)0)
- { printf("Failure allocating %d bytes for SQLVAR data\n",sqlda->sqlvar[i].sqllen); }
- sqlda->sqlvar[i].sqlind = (short *)malloc(sizeof(short));
- if (sqlda->sqlvar[i].sqlind == (short *)0)
- { printf("Failure allocating sqlind\n"); }
- }
- return sqlda;
-}
-void INGfreeDescriptor(IISQLDA *sqlda)
-{
- int i;
- for ( i = 0 ; i < sqlda->sqld ; ++i )
- {
- free(sqlda->sqlvar[i].sqldata);
- free(sqlda->sqlvar[i].sqlind);
- }
- free(sqlda);
- sqlda = NULL;
-}
-int INGgetTypeSize(IISQLVAR *ingvar)
-{
- int inglength = 0;
- switch (ingvar->sqltype)
- {
- case IISQ_DTE_TYPE:
- inglength = 25;
- break;
- case IISQ_MNY_TYPE:
- inglength = 8;
- break;
- default:
- inglength = ingvar->sqllen;
- }
- return inglength;
-}
-INGresult *INGgetINGresult(IISQLDA *sqlda)
-{
- INGresult *result = NULL;
- result = (INGresult *)calloc(1, sizeof(INGresult));
- if (result == (INGresult *)0)
- { printf("Failure allocating INGresult\n"); }
- result->sqlda = sqlda;
- result->num_fields = sqlda->sqld;
- result->num_rows = 0;
- result->first_row = NULL;
- result->status = ING_EMPTY_RESULT;
- result->act_row = NULL;
- strcpy(result->numrowstring,"");
- result->fields = (INGRES_FIELD *)calloc(1, sizeof(INGRES_FIELD) * result->num_fields);
- if (result->fields == (INGRES_FIELD *)0)
- { printf("Failure allocating %d INGRES_FIELD elements\n",result->num_fields); }
- DEBB(2)
- printf("INGgetINGresult, before loop over %d fields\n", result->num_fields);
- DEBE
- int i;
- for (i=0;i<result->num_fields;++i)
- {
- memset(result->fields[i].name,'\0',34);
- strncpy(result->fields[i].name,
- sqlda->sqlvar[i].sqlname.sqlnamec,
- sqlda->sqlvar[i].sqlname.sqlnamel);
- result->fields[i].max_length = INGgetTypeSize(&sqlda->sqlvar[i]);
- result->fields[i].type = abs(sqlda->sqlvar[i].sqltype);
- result->fields[i].flags = (abs(sqlda->sqlvar[i].sqltype)<0) ? 1 : 0;
- }
- return result;
-}
-void INGfreeINGresult(INGresult *ing_res)
-{
- /* TODO: free all rows and fields, then res, not descriptor! */
- if( ing_res != NULL )
- {
- /* use of rows is a nasty workaround til I find the reason,
- why aggregates like max() don't work
- */
- int rows = ing_res->num_rows;
- ING_ROW *rowtemp;
- ing_res->act_row = ing_res->first_row;
- while (ing_res->act_row != NULL && rows > 0)
- {
- rowtemp = ing_res->act_row->next;
- INGfreeRowSpace(ing_res->act_row, ing_res->sqlda);
- ing_res->act_row = rowtemp;
- --rows;
- }
- free(ing_res->fields);
- }
- free(ing_res);
- ing_res = NULL;
-}
-ING_ROW *INGgetRowSpace(INGresult *ing_res)
-{
- IISQLDA *sqlda = ing_res->sqlda;
- ING_ROW *row = NULL;
- IISQLVAR *vars = NULL;
- row = (ING_ROW *)calloc(1,sizeof(ING_ROW));
- if (row == (ING_ROW *)0)
- { printf("Failure allocating ING_ROW\n"); }
- vars = (IISQLVAR *)calloc(1,sizeof(IISQLVAR) * sqlda->sqld);
- if (vars == (IISQLVAR *)0)
- { printf("Failure allocating %d SQLVAR elements\n",sqlda->sqld); }
- row->sqlvar = vars;
- row->next = NULL;
- int i;
- unsigned short len; /* used for VARCHAR type length */
- for (i=0;i<sqlda->sqld;++i)
- {
- /* make strings out of the data, then the space and assign
- (why string? at least it seems that way, looking into the sources)
- */
- switch (abs(ing_res->fields[i].type))
- {
- case IISQ_VCH_TYPE:
- len = ((ING_VARCHAR *)sqlda->sqlvar[i].sqldata)->len;
- DEBB(2)
- printf("length of varchar: %d\n", len);
- DEBE
- vars[i].sqldata = (char *)malloc(len+1);
- if (vars[i].sqldata == (char *)0)
- { printf("Failure allocating %d bytes for SQLVAR data\n",len+1); }
- memcpy(vars[i].sqldata,sqlda->sqlvar[i].sqldata+2,len);
- vars[i].sqldata[len] = '\0';
- break;
- case IISQ_CHA_TYPE:
- vars[i].sqldata = (char *)malloc(ing_res->fields[i].max_length+1);
- if (vars[i].sqldata == (char *)0)
- { printf("Failure allocating %d bytes for SQLVAR data\n",ing_res->fields[i].max_length); }
- memcpy(vars[i].sqldata,sqlda->sqlvar[i].sqldata,sqlda->sqlvar[i].sqllen);
- vars[i].sqldata[ing_res->fields[i].max_length] = '\0';
- break;
- case IISQ_INT_TYPE:
- vars[i].sqldata = (char *)malloc(20);
- memset(vars[i].sqldata,'\0',20);
- sprintf(vars[i].sqldata,"%d",*(int*)sqlda->sqlvar[i].sqldata);
- break;
- }
- vars[i].sqlind = (short *)malloc(sizeof(short));
- if (sqlda->sqlvar[i].sqlind == (short *)0)
- { printf("Failure allocating sqlind\n"); }
- memcpy(vars[i].sqlind,sqlda->sqlvar[i].sqlind,sizeof(short));
- DEBB(2)
- printf("INGgetRowSpace, Field %d, type %d, length %d, name %s\n",
- i, sqlda->sqlvar[i].sqltype, sqlda->sqlvar[i].sqllen, ing_res->fields[i].name);
- DEBE
- }
- return row;
-}
-void INGfreeRowSpace(ING_ROW *row, IISQLDA *sqlda)
-{
- int i;
- if (row == NULL || sqlda == NULL)
- {
- printf("INGfreeRowSpace: one argument is NULL!\n");
- return;
- }
- for ( i = 0 ; i < sqlda->sqld ; ++i )
- {
- free(row->sqlvar[i].sqldata);
- free(row->sqlvar[i].sqlind);
- }
- free(row->sqlvar);
- free(row);
-}
-int INGfetchAll(const char *stmt, INGresult *ing_res)
-{
- int linecount = 0;
- ING_ROW *row;
- IISQLDA *desc;
- char stmt_buffer[2000];
- strcpy(stmt_buffer,stmt);
- desc = ing_res->sqlda;
-/* # line 275 "myingres.sc" */ /* host code */
- INGcheck();
-/* # line 277 "myingres.sc" */ /* open */
- {
- IIsqInit(&sqlca);
- IIcsOpen((char *)"c2",19215,16475);
- IIwritio(0,(short *)0,1,32,0,(char *)"s2");
- IIcsQuery((char *)"c2",19215,16475);
- }
-/* # line 278 "myingres.sc" */ /* host code */
- INGcheck();
- /* for (linecount=0;sqlca.sqlcode==0;++linecount) */
- while(sqlca.sqlcode==0)
- {
-/* # line 283 "myingres.sc" */ /* fetch */
- {
- IIsqInit(&sqlca);
- if (IIcsRetScroll((char *)"c2",19215,16475,-1,-1) != 0) {
- IIcsDaGet(0,desc);
- IIcsERetrieve();
- } /* IIcsRetrieve */
- }
-/* # line 284 "myingres.sc" */ /* host code */
- INGcheck();
- if (sqlca.sqlcode == 0)
- {
- row = INGgetRowSpace(ing_res); /* alloc space for fetched row */
- /* initialize list when encountered first time */
- if (ing_res->first_row == 0)
- {
- ing_res->first_row = row; /* head of the list */
- ing_res->first_row->next = NULL;
- ing_res->act_row = ing_res->first_row;
- }
- ing_res->act_row->next = row; /* append row to old act_row */
- ing_res->act_row = row; /* set row as act_row */
- row->row_number = linecount;
- ++linecount;
- DEBB(2)
- int i;
- printf("Row %d ", linecount);
- for (i=0;i<ing_res->num_fields;++i)
- { printf("F%d:%s ",i,row->sqlvar[i].sqldata); }
- printf("\n");
- DEBE
- }
- }
-/* # line 313 "myingres.sc" */ /* close */
- {
- IIsqInit(&sqlca);
- IIcsClose((char *)"c2",19215,16475);
- }
-/* # line 315 "myingres.sc" */ /* host code */
- ing_res->status = ING_COMMAND_OK;
- ing_res->num_rows = linecount;
- return linecount;
-}
-ING_STATUS INGresultStatus(INGresult *res)
-{
- if (res == NULL) {return ING_NO_RESULT;}
- return res->status;
-}
-void INGrowSeek(INGresult *res, int row_number)
-{
- if (res->act_row->row_number == row_number) { return; }
- /* TODO: real error handling */
- if (row_number<0 || row_number>res->num_rows) { return;}
- ING_ROW *trow = res->first_row;
- while ( trow->row_number != row_number )
- { trow = trow->next; }
- res->act_row = trow;
- /* note - can be null - if row_number not found, right? */
-}
-char *INGgetvalue(INGresult *res, int row_number, int column_number)
-{
- if (row_number != res->act_row->row_number)
- { INGrowSeek(res, row_number); }
- return res->act_row->sqlvar[column_number].sqldata;
-}
-int INGgetisnull(INGresult *res, int row_number, int column_number)
-{
- if (row_number != res->act_row->row_number)
- { INGrowSeek(res, row_number); }
- return (short)*res->act_row->sqlvar[column_number].sqlind;
-}
-int INGntuples(const INGresult *res)
-{
- return res->num_rows;
-}
-int INGnfields(const INGresult *res)
-{
- return res->num_fields;
-}
-char *INGfname(const INGresult *res, int column_number)
-{
- if ( (column_number > res->num_fields) || (column_number < 0) )
- { return NULL; }
- else
- { return res->fields[column_number].name; }
-}
-short INGftype(const INGresult *res, int column_number)
-{
- return res->fields[column_number].type;
-}
-INGresult *INGexec(INGconn *conn, const char *query)
-{
- /* TODO: error handling -> res->status? */
- IISQLDA *desc = NULL;
- INGresult *res = NULL;
- int cols = -1;
- char stmt[2000];
- strncpy(stmt,query,strlen(query));
- stmt[strlen(query)]='\0';
- DEBB(1)
- printf("INGexec: query is >>%s<<\n",stmt);
- DEBE
- if ((cols = INGgetCols(query)) == 0)
- {
- DEBB(1)
- printf("INGexec: non-select\n");
- DEBE
- /* non-select statement - TODO: EXECUTE IMMEDIATE */
-/* # line 400 "myingres.sc" */ /* execute */
- {
- IIsqInit(&sqlca);
- IIsqExImmed(stmt);
- IIsyncup((char *)0,0);
- }
-/* # line 401 "myingres.sc" */ /* host code */
- }
- else
- {
- DEBB(1)
- printf("INGexec: select\n");
- DEBE
- /* select statement */
- desc = INGgetDescriptor(cols, query);
- res = INGgetINGresult(desc);
- INGfetchAll(query, res);
- }
- return res;
-}
-void INGclear(INGresult *res)
-{
- if (res == NULL) { return; }
- IISQLDA *desc = res->sqlda;
- INGfreeINGresult(res);
- INGfreeDescriptor(desc);
-}
-INGconn *INGconnectDB(char *dbname, char *user, char *passwd)
-{
- if (dbname == NULL || strlen(dbname) == 0)
- { return NULL; }
- INGconn *dbconn = (INGconn *)calloc(1,sizeof(INGconn));
- if (dbconn == (INGconn *)0)
- { printf("Failure allocating INGconn\n"); }
- char ingdbname[24];
- char ingdbuser[32];
- char ingdbpasw[32];
- char conn_name[32];
- int sess_id;
- strcpy(ingdbname,dbname);
- if ( user != NULL)
- {
- DEBB(1)
- printf("Connection: with user/passwd\n");
- DEBE
- strcpy(ingdbuser,user);
- if ( passwd != NULL)
- { strcpy(ingdbpasw,passwd); }
- else
- { strcpy(ingdbpasw, ""); }
-/* # line 452 "myingres.sc" */ /* connect */
- {
- IIsqInit(&sqlca);
- IIsqUser(ingdbuser);
- IIsqConnect(0,ingdbname,(char *)"-dbms_password",ingdbpasw,(char *)0,
- (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0,
- (char *)0, (char *)0, (char *)0, (char *)0);
- }
-/* # line 456 "myingres.sc" */ /* host code */
- }
- else
- {
- DEBB(1)
- printf("Connection: w/ user/passwd\n");
- DEBE
-/* # line 462 "myingres.sc" */ /* connect */
- {
- IIsqInit(&sqlca);
- IIsqConnect(0,ingdbname,(char *)0, (char *)0, (char *)0, (char *)0,
- (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0,
- (char *)0, (char *)0, (char *)0);
- }
-/* # line 463 "myingres.sc" */ /* host code */
- }
-/* # line 465 "myingres.sc" */ /* inquire_sql */
- {
- IILQisInqSqlio((short *)0,1,32,31,conn_name,13);
- }
-/* # line 466 "myingres.sc" */ /* inquire_sql */
- {
- IILQisInqSqlio((short *)0,1,30,sizeof(sess_id),&sess_id,11);
- }
-/* # line 468 "myingres.sc" */ /* host code */
- strcpy(dbconn->dbname,ingdbname);
- strcpy(dbconn->user,ingdbuser);
- strcpy(dbconn->password,ingdbpasw);
- strcpy(dbconn->connection_name,conn_name);
- dbconn->session_id = sess_id;
- DEBB(1)
- printf("Connected to '%s' with user/passwd %s/%s, sessID/name %i/%s\n",
- dbconn->dbname,
- dbconn->user,
- dbconn->password,
- dbconn->session_id,
- dbconn->connection_name
- );
- DEBE
- return dbconn;
-}
-void INGdisconnectDB(INGconn *dbconn)
-{
- /* TODO: use of dbconn */
-/* # line 490 "myingres.sc" */ /* disconnect */
- {
- IIsqInit(&sqlca);
- IIsqDisconnect();
- }
-/* # line 491 "myingres.sc" */ /* host code */
- free(dbconn);
-}
-char *INGerrorMessage(const INGconn *conn)
-{
- return NULL;
-}
-char *INGcmdTuples(INGresult *res)
-{
- return res->numrowstring;
-}
-/* TODO?
-char *INGerrorMessage(const INGconn *conn);
-int INGputCopyEnd(INGconn *conn, const char *errormsg);
-int INGputCopyData(INGconn *conn, const char *buffer, int nbytes);
-*/
-
-#endif
+++ /dev/null
-# include "/opt/Ingres/IngresII/ingres/files/eqdefc.h"
-#ifndef _MYINGRES_SH
-#define _MYINGRES_SH
-# include "/opt/Ingres/IngresII/ingres/files/eqsqlda.h"
-/* ---typedefs--- */
-typedef struct ing_field {
- char name[34];
- int max_length;
- unsigned int type;
- unsigned int flags; // 1 == not null
-} INGRES_FIELD;
-typedef struct ing_row {
- IISQLVAR *sqlvar; /* ptr to sqlvar[sqld] for one row */
- struct ing_row *next;
- int row_number;
-} ING_ROW;
-typedef enum ing_status {
- ING_COMMAND_OK,
- ING_TUPLES_OK,
- ING_NO_RESULT,
- ING_NO_ROWS_PROCESSED,
- ING_EMPTY_RESULT,
- ING_ERROR
-} ING_STATUS;
-typedef struct ing_varchar {
- short len;
- char* value;
-} ING_VARCHAR;
-/* It seems, Bacula needs the complete query result stored in one data structure */
-typedef struct ing_result {
- IISQLDA *sqlda; /* descriptor */
- INGRES_FIELD *fields;
- int num_rows;
- int num_fields;
- ING_STATUS status;
- ING_ROW *first_row;
- ING_ROW *act_row; /* just for iterating */
- char numrowstring[10];
-} INGresult;
-typedef struct ing_conn {
- char dbname[24];
- char user[32];
- char password[32];
- char connection_name[32];
- int session_id;
-} INGconn;
-/* ---Prototypes--- */
-int INGcheck();
-ING_STATUS INGresultStatus(INGresult *res);
-short INGgetCols(const char *stmt);
-IISQLDA *INGgetDescriptor(short numCols, const char *stmt);
-void INGfreeDescriptor(IISQLDA *sqlda);
-int INGgetTypeSize(IISQLVAR *ingvar);
-INGresult *INGgetINGresult(IISQLDA *sqlda);
-void INGfreeINGresult(INGresult *ing_res);
-ING_ROW *INGgetRowSpace(INGresult *ing_res);
-void INGfreeRowSpace(ING_ROW *row, IISQLDA *sqlda);
-int INGfetchAll(const char *stmt, INGresult *ing_res);
-void INGrowSeek(INGresult *res, int row_number);
-char *INGgetvalue(INGresult *res, int row_number, int column_number);
-int INGgetisnull(INGresult *res, int row_number, int column_number);
-int INGntuples(const INGresult *res);
-int INGnfields(const INGresult *res);
-char *INGfname(const INGresult *res, int column_number);
-short INGftype(const INGresult *res, int column_number);
-INGresult *INGexec(INGconn *db, const char *query);
-void INGclear(INGresult *res);
-INGconn *INGconnectDB(char *dbname, char *user, char *passwd);
-void INGdisconnectDB(INGconn *dbconn);
-char *INGerrorMessage(const INGconn *conn);
-char *INGcmdTuples(INGresult *res);
-#endif /* _MYINGRES_SH */
+++ /dev/null
-EXEC SQL INCLUDE SQLCA;
-EXEC SQL INCLUDE SQLDA;
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "myingres.h"
-
-#define INGRES_DEBUG 0
-#define DEBB(x) if (INGRES_DEBUG >= x) {
-#define DEBE }
-
-/* ---Implementations--- */
-int INGcheck()
-{
- EXEC SQL BEGIN DECLARE SECTION;
- char errbuf[256];
- EXEC SQL END DECLARE SECTION;
-
- if (sqlca.sqlcode < 0)
- {
- EXEC SQL INQUIRE_INGRES(:errbuf = ERRORTEXT);
- printf("Ingres-DBMS-Fehler: %s\n", errbuf);
- return sqlca.sqlcode;
- }
- else
- return 0;
-}
-
-short INGgetCols(const char *stmt)
-{
- short number = 1;
- IISQLDA *sqlda;
- sqlda = (IISQLDA *)calloc(1,IISQDA_HEAD_SIZE + (number * IISQDA_VAR_SIZE));
- if (sqlda == (IISQLDA *)0)
- { printf("Failure allocating %d SQLDA elements\n",number); }
- sqlda->sqln = number;
-
- EXEC SQL BEGIN DECLARE SECTION;
- char stmt_buffer[2000];
- EXEC SQL END DECLARE SECTION;
-
- strcpy(stmt_buffer,stmt);
-
- EXEC SQL PREPARE s1 from :stmt_buffer;
- EXEC SQL DESCRIBE s1 into :sqlda;
-
- number = sqlda->sqld;
- free(sqlda);
- return number;
-}
-
-IISQLDA *INGgetDescriptor(short numCols, const char *stmt)
-{
- IISQLDA *sqlda;
- sqlda = (IISQLDA *)calloc(1,IISQDA_HEAD_SIZE + (numCols * IISQDA_VAR_SIZE));
- if (sqlda == (IISQLDA *)0)
- { printf("Failure allocating %d SQLDA elements\n",numCols); }
-
- sqlda->sqln = numCols;
-
- EXEC SQL BEGIN DECLARE SECTION;
- char stmt_buffer[2000];
- EXEC SQL END DECLARE SECTION;
-
- strcpy(stmt_buffer,stmt);
-
- EXEC SQL PREPARE s2 INTO :sqlda FROM :stmt_buffer;
-
- int i;
- for (i=0;i<sqlda->sqld;++i)
- {
- sqlda->sqlvar[i].sqldata =
- (char *)malloc(sqlda->sqlvar[i].sqllen);
- if (sqlda->sqlvar[i].sqldata == (char *)0)
- { printf("Failure allocating %d bytes for SQLVAR data\n",sqlda->sqlvar[i].sqllen); }
-
- sqlda->sqlvar[i].sqlind = (short *)malloc(sizeof(short));
- if (sqlda->sqlvar[i].sqlind == (short *)0)
- { printf("Failure allocating sqlind\n"); }
- }
-
- return sqlda;
-}
-void INGfreeDescriptor(IISQLDA *sqlda)
-{
- int i;
- for ( i = 0 ; i < sqlda->sqld ; ++i )
- {
- free(sqlda->sqlvar[i].sqldata);
- free(sqlda->sqlvar[i].sqlind);
- }
- free(sqlda);
- sqlda = NULL;
-}
-
-int INGgetTypeSize(IISQLVAR *ingvar)
-{
- int inglength = 0;
-
- switch (ingvar->sqltype)
- {
- case IISQ_DTE_TYPE:
- inglength = 25;
- break;
- case IISQ_MNY_TYPE:
- inglength = 8;
- break;
- default:
- inglength = ingvar->sqllen;
- }
-
- return inglength;
-}
-
-INGresult *INGgetINGresult(IISQLDA *sqlda)
-{
- INGresult *result = NULL;
-
- result = (INGresult *)calloc(1, sizeof(INGresult));
- if (result == (INGresult *)0)
- { printf("Failure allocating INGresult\n"); }
-
- result->sqlda = sqlda;
- result->num_fields = sqlda->sqld;
- result->num_rows = 0;
- result->first_row = NULL;
- result->status = ING_EMPTY_RESULT;
- result->act_row = NULL;
- strcpy(result->numrowstring,"");
-
- result->fields = (INGRES_FIELD *)calloc(1, sizeof(INGRES_FIELD) * result->num_fields);
- if (result->fields == (INGRES_FIELD *)0)
- { printf("Failure allocating %d INGRES_FIELD elements\n",result->num_fields); }
-
- DEBB(2)
- printf("INGgetINGresult, before loop over %d fields\n", result->num_fields);
- DEBE
-
- int i;
- for (i=0;i<result->num_fields;++i)
- {
- memset(result->fields[i].name,'\0',34);
- strncpy(result->fields[i].name,
- sqlda->sqlvar[i].sqlname.sqlnamec,
- sqlda->sqlvar[i].sqlname.sqlnamel);
- result->fields[i].max_length = INGgetTypeSize(&sqlda->sqlvar[i]);
- result->fields[i].type = abs(sqlda->sqlvar[i].sqltype);
- result->fields[i].flags = (abs(sqlda->sqlvar[i].sqltype)<0) ? 1 : 0;
- }
-
- return result;
-}
-
-void INGfreeINGresult(INGresult *ing_res)
-{
- /* TODO: free all rows and fields, then res, not descriptor! */
- if( ing_res != NULL )
- {
- /* use of rows is a nasty workaround til I find the reason,
- why aggregates like max() don't work
- */
- int rows = ing_res->num_rows;
- ING_ROW *rowtemp;
- ing_res->act_row = ing_res->first_row;
- while (ing_res->act_row != NULL && rows > 0)
- {
- rowtemp = ing_res->act_row->next;
- INGfreeRowSpace(ing_res->act_row, ing_res->sqlda);
- ing_res->act_row = rowtemp;
- --rows;
- }
- free(ing_res->fields);
- }
- free(ing_res);
- ing_res = NULL;
-}
-
-ING_ROW *INGgetRowSpace(INGresult *ing_res)
-{
- IISQLDA *sqlda = ing_res->sqlda;
- ING_ROW *row = NULL;
- IISQLVAR *vars = NULL;
- row = (ING_ROW *)calloc(1,sizeof(ING_ROW));
- if (row == (ING_ROW *)0)
- { printf("Failure allocating ING_ROW\n"); }
-
- vars = (IISQLVAR *)calloc(1,sizeof(IISQLVAR) * sqlda->sqld);
- if (vars == (IISQLVAR *)0)
- { printf("Failure allocating %d SQLVAR elements\n",sqlda->sqld); }
-
- row->sqlvar = vars;
- row->next = NULL;
-
- int i;
- unsigned short len; /* used for VARCHAR type length */
- for (i=0;i<sqlda->sqld;++i)
- {
- /* make strings out of the data, then the space and assign
- (why string? at least it seems that way, looking into the sources)
- */
- switch (abs(ing_res->fields[i].type))
- {
- case IISQ_VCH_TYPE:
- len = ((ING_VARCHAR *)sqlda->sqlvar[i].sqldata)->len;
- DEBB(2)
- printf("length of varchar: %d\n", len);
- DEBE
- vars[i].sqldata = (char *)malloc(len+1);
- if (vars[i].sqldata == (char *)0)
- { printf("Failure allocating %d bytes for SQLVAR data\n",len+1); }
- memcpy(vars[i].sqldata,sqlda->sqlvar[i].sqldata+2,len);
- vars[i].sqldata[len] = '\0';
- break;
- case IISQ_CHA_TYPE:
- vars[i].sqldata = (char *)malloc(ing_res->fields[i].max_length+1);
- if (vars[i].sqldata == (char *)0)
- { printf("Failure allocating %d bytes for SQLVAR data\n",ing_res->fields[i].max_length); }
- memcpy(vars[i].sqldata,sqlda->sqlvar[i].sqldata,sqlda->sqlvar[i].sqllen);
- vars[i].sqldata[ing_res->fields[i].max_length] = '\0';
- break;
- case IISQ_INT_TYPE:
- vars[i].sqldata = (char *)malloc(20);
- memset(vars[i].sqldata,'\0',20);
- sprintf(vars[i].sqldata,"%d",*(int*)sqlda->sqlvar[i].sqldata);
- break;
- }
- vars[i].sqlind = (short *)malloc(sizeof(short));
- if (sqlda->sqlvar[i].sqlind == (short *)0)
- { printf("Failure allocating sqlind\n"); }
- memcpy(vars[i].sqlind,sqlda->sqlvar[i].sqlind,sizeof(short));
- DEBB(2)
- printf("INGgetRowSpace, Field %d, type %d, length %d, name %s\n",
- i, sqlda->sqlvar[i].sqltype, sqlda->sqlvar[i].sqllen, ing_res->fields[i].name);
- DEBE
- }
-
- return row;
-}
-
-
-void INGfreeRowSpace(ING_ROW *row, IISQLDA *sqlda)
-{
- int i;
- if (row == NULL || sqlda == NULL)
- {
- printf("INGfreeRowSpace: one argument is NULL!\n");
- return;
- }
-
- for ( i = 0 ; i < sqlda->sqld ; ++i )
- {
- free(row->sqlvar[i].sqldata);
- free(row->sqlvar[i].sqlind);
- }
- free(row->sqlvar);
- free(row);
-}
-
-int INGfetchAll(const char *stmt, INGresult *ing_res)
-{
- int linecount = 0;
- ING_ROW *row;
- IISQLDA *desc;
-
- EXEC SQL BEGIN DECLARE SECTION;
- char stmt_buffer[2000];
- EXEC SQL END DECLARE SECTION;
-
- strcpy(stmt_buffer,stmt);
- desc = ing_res->sqlda;
-
- EXEC SQL DECLARE c2 CURSOR FOR s2;
- INGcheck();
-
- EXEC SQL OPEN c2;
- INGcheck();
-
- /* for (linecount=0;sqlca.sqlcode==0;++linecount) */
- while(sqlca.sqlcode==0)
- {
- EXEC SQL FETCH c2 USING DESCRIPTOR :desc;
- INGcheck();
-
- if (sqlca.sqlcode == 0)
- {
- row = INGgetRowSpace(ing_res); /* alloc space for fetched row */
-
- /* initialize list when encountered first time */
- if (ing_res->first_row == 0)
- {
- ing_res->first_row = row; /* head of the list */
- ing_res->first_row->next = NULL;
- ing_res->act_row = ing_res->first_row;
- }
- ing_res->act_row->next = row; /* append row to old act_row */
- ing_res->act_row = row; /* set row as act_row */
- row->row_number = linecount;
- ++linecount;
-
- DEBB(2)
- int i;
- printf("Row %d ", linecount);
- for (i=0;i<ing_res->num_fields;++i)
- { printf("F%d:%s ",i,row->sqlvar[i].sqldata); }
- printf("\n");
- DEBE
-
- }
- }
-
- EXEC SQL CLOSE c2;
-
- ing_res->status = ING_COMMAND_OK;
- ing_res->num_rows = linecount;
- return linecount;
-}
-
-ING_STATUS INGresultStatus(INGresult *res)
-{
- if (res == NULL) {return ING_NO_RESULT;}
- return res->status;
-}
-
-void INGrowSeek(INGresult *res, int row_number)
-{
- if (res->act_row->row_number == row_number) { return; }
-
- /* TODO: real error handling */
- if (row_number<0 || row_number>res->num_rows) { return;}
-
- ING_ROW *trow = res->first_row;
- while ( trow->row_number != row_number )
- { trow = trow->next; }
- res->act_row = trow;
- /* note - can be null - if row_number not found, right? */
-}
-
-char *INGgetvalue(INGresult *res, int row_number, int column_number)
-{
- if (row_number != res->act_row->row_number)
- { INGrowSeek(res, row_number); }
- return res->act_row->sqlvar[column_number].sqldata;
-}
-
-int INGgetisnull(INGresult *res, int row_number, int column_number)
-{
- if (row_number != res->act_row->row_number)
- { INGrowSeek(res, row_number); }
- return (short)*res->act_row->sqlvar[column_number].sqlind;
-}
-
-int INGntuples(const INGresult *res)
-{
- return res->num_rows;
-}
-
-int INGnfields(const INGresult *res)
-{
- return res->num_fields;
-}
-
-char *INGfname(const INGresult *res, int column_number)
-{
- if ( (column_number > res->num_fields) || (column_number < 0) )
- { return NULL; }
- else
- { return res->fields[column_number].name; }
-}
-
-short INGftype(const INGresult *res, int column_number)
-{
- return res->fields[column_number].type;
-}
-
-INGresult *INGexec(INGconn *conn, const char *query)
-{
- /* TODO: error handling -> res->status? */
- IISQLDA *desc = NULL;
- INGresult *res = NULL;
- int cols = -1;
-
- EXEC SQL BEGIN DECLARE SECTION;
- char stmt[2000];
- EXEC SQL END DECLARE SECTION;
- strncpy(stmt,query,strlen(query));
- stmt[strlen(query)]='\0';
-
- DEBB(1)
- printf("INGexec: query is >>%s<<\n",stmt);
- DEBE
-
- if ((cols = INGgetCols(query)) == 0)
- {
- DEBB(1)
- printf("INGexec: non-select\n");
- DEBE
- /* non-select statement - TODO: EXECUTE IMMEDIATE */
- EXEC SQL EXECUTE IMMEDIATE :stmt;
- }
- else
- {
- DEBB(1)
- printf("INGexec: select\n");
- DEBE
- /* select statement */
- desc = INGgetDescriptor(cols, query);
- res = INGgetINGresult(desc);
- INGfetchAll(query, res);
- }
- return res;
-}
-
-void INGclear(INGresult *res)
-{
- if (res == NULL) { return; }
- IISQLDA *desc = res->sqlda;
- INGfreeINGresult(res);
- INGfreeDescriptor(desc);
-}
-
-INGconn *INGconnectDB(char *dbname, char *user, char *passwd)
-{
- if (dbname == NULL || strlen(dbname) == 0)
- { return NULL; }
-
- INGconn *dbconn = (INGconn *)calloc(1,sizeof(INGconn));
- if (dbconn == (INGconn *)0)
- { printf("Failure allocating INGconn\n"); }
-
- EXEC SQL BEGIN DECLARE SECTION;
- char ingdbname[24];
- char ingdbuser[32];
- char ingdbpasw[32];
- char conn_name[32];
- int sess_id;
- EXEC SQL END DECLARE SECTION;
-
- strcpy(ingdbname,dbname);
-
- if ( user != NULL)
- {
- DEBB(1)
- printf("Connection: with user/passwd\n");
- DEBE
- strcpy(ingdbuser,user);
- if ( passwd != NULL)
- { strcpy(ingdbpasw,passwd); }
- else
- { strcpy(ingdbpasw, ""); }
- EXEC SQL CONNECT
- :ingdbname
- identified by :ingdbuser
- dbms_password = :ingdbpasw;
- }
- else
- {
- DEBB(1)
- printf("Connection: w/ user/passwd\n");
- DEBE
- EXEC SQL CONNECT :ingdbname;
- }
-
- EXEC SQL INQUIRE_SQL(:conn_name = connection_name);
- EXEC SQL INQUIRE_SQL(:sess_id = session);
-
- strcpy(dbconn->dbname,ingdbname);
- strcpy(dbconn->user,ingdbuser);
- strcpy(dbconn->password,ingdbpasw);
- strcpy(dbconn->connection_name,conn_name);
- dbconn->session_id = sess_id;
-
- DEBB(1)
- printf("Connected to '%s' with user/passwd %s/%s, sessID/name %i/%s\n",
- dbconn->dbname,
- dbconn->user,
- dbconn->password,
- dbconn->session_id,
- dbconn->connection_name
- );
- DEBE
-
- return dbconn;
-}
-
-void INGdisconnectDB(INGconn *dbconn)
-{
- /* TODO: use of dbconn */
- EXEC SQL DISCONNECT;
- free(dbconn);
-}
-
-char *INGerrorMessage(const INGconn *conn)
-{
- return NULL;
-}
-
-char *INGcmdTuples(INGresult *res)
-{
- return res->numrowstring;
-}
-
-
-/* TODO?
-char *INGerrorMessage(const INGconn *conn);
-int INGputCopyEnd(INGconn *conn, const char *errormsg);
-int INGputCopyData(INGconn *conn, const char *buffer, int nbytes);
-*/
+++ /dev/null
-#ifndef _MYINGRES_SH
-#define _MYINGRES_SH
-
-EXEC SQL INCLUDE SQLDA;
-
-/* ---typedefs--- */
-
-typedef struct ing_field {
- char name[34];
- int max_length;
- unsigned int type;
- unsigned int flags; // 1 == not null
-} INGRES_FIELD;
-
-typedef struct ing_row {
- IISQLVAR *sqlvar; /* ptr to sqlvar[sqld] for one row */
- struct ing_row *next;
- int row_number;
-} ING_ROW;
-
-typedef enum ing_status {
- ING_COMMAND_OK,
- ING_TUPLES_OK,
- ING_NO_RESULT,
- ING_NO_ROWS_PROCESSED,
- ING_EMPTY_RESULT,
- ING_ERROR
-} ING_STATUS;
-
-typedef struct ing_varchar {
- short len;
- char* value;
-} ING_VARCHAR;
-
-/* It seems, Bacula needs the complete query result stored in one data structure */
-typedef struct ing_result {
- IISQLDA *sqlda; /* descriptor */
- INGRES_FIELD *fields;
- int num_rows;
- int num_fields;
- ING_STATUS status;
- ING_ROW *first_row;
- ING_ROW *act_row; /* just for iterating */
- char numrowstring[10];
-
-} INGresult;
-
-typedef struct ing_conn {
- char dbname[24];
- char user[32];
- char password[32];
- char connection_name[32];
- int session_id;
-} INGconn;
-
-
-/* ---Prototypes--- */
-int INGcheck();
-ING_STATUS INGresultStatus(INGresult *res);
-short INGgetCols(const char *stmt);
-IISQLDA *INGgetDescriptor(short numCols, const char *stmt);
-void INGfreeDescriptor(IISQLDA *sqlda);
-int INGgetTypeSize(IISQLVAR *ingvar);
-INGresult *INGgetINGresult(IISQLDA *sqlda);
-void INGfreeINGresult(INGresult *ing_res);
-ING_ROW *INGgetRowSpace(INGresult *ing_res);
-void INGfreeRowSpace(ING_ROW *row, IISQLDA *sqlda);
-int INGfetchAll(const char *stmt, INGresult *ing_res);
-void INGrowSeek(INGresult *res, int row_number);
-char *INGgetvalue(INGresult *res, int row_number, int column_number);
-int INGgetisnull(INGresult *res, int row_number, int column_number);
-int INGntuples(const INGresult *res);
-int INGnfields(const INGresult *res);
-char *INGfname(const INGresult *res, int column_number);
-short INGftype(const INGresult *res, int column_number);
-INGresult *INGexec(INGconn *db, const char *query);
-void INGclear(INGresult *res);
-INGconn *INGconnectDB(char *dbname, char *user, char *passwd);
-void INGdisconnectDB(INGconn *dbconn);
-char *INGerrorMessage(const INGconn *conn);
-char *INGcmdTuples(INGresult *res);
-
-#endif /* _MYINGRES_SH */
echo " "
bindir=@SQL_BINDIR@
-export PATH="$bindir:$PATH"
+PATH="$bindir:$PATH"
db_name=@db_name@
if psql -f - -d ${db_name} $* <<END-OF-DATA