mdb->esc_name = get_pool_memory(PM_FNAME);
mdb->esc_path = get_pool_memory(PM_FNAME);
mdb->allow_transactions = mult_db_connections;
+ mdb->limit_filter = new_bregexp("/LIMIT ([0-9]+)/FETCH FIRST $1 ROW ONLY/g");
qinsert(&db_list, &mdb->bq); /* put db in list */
V(mutex);
return mdb;
free_pool_memory(mdb->path);
free_pool_memory(mdb->esc_name);
free_pool_memory(mdb->esc_path);
+ free_bregexp(mdb->limit_filter);
if (mdb->db_name) {
free(mdb->db_name);
}
/* TODO: differentiate between SELECTs and other queries */
- if ((cols = INGgetCols(query)) <= 0) {
+ if ((cols = INGgetCols(mdb, query)) <= 0) {
if (cols < 0 ) {
Dmsg0(500,"my_ingres_query: neg.columns: no DML stmt!\n");
}
Dmsg0(500,"my_ingres_query (non SELECT) starting...\n");
/* non SELECT */
- mdb->num_rows = INGexec(mdb->db, query);
+ mdb->num_rows = INGexec(mdb, mdb->db, query);
if (INGcheck()) {
Dmsg0(500,"my_ingres_query (non SELECT) went wrong\n");
mdb->status = 1;
} else {
/* SELECT */
Dmsg0(500,"my_ingres_query (SELECT) starting...\n");
- mdb->result = INGquery(mdb->db, query);
+ mdb->result = INGquery(mdb, mdb->db, query);
if ( mdb->result != NULL ) {
Dmsg1(500, "we have a result\n", query);
return (sqlca.sqlcode < 0) ? sqlca.sqlcode : 0;
}
-short INGgetCols(const char *query)
+short INGgetCols(B_DB *mdb, const char *query)
{
+ bool stmt_free = false;
EXEC SQL BEGIN DECLARE SECTION;
char *stmt;
EXEC SQL END DECLARE SECTION;
sqlda->sqln = number;
- stmt = bstrdup(query);
+ /*
+ * See if we need to run this through the limit_filter.
+ */
+ if (strstr(query, "LIMIT") != NULL) {
+ stmt = mdb->limit_filter->replace(query);
+ } else {
+ stmt = bstrdup(query);
+ stmt_free = true;
+ }
EXEC SQL PREPARE s1 from :stmt;
if (INGcheck() < 0) {
number = -1;
goto bail_out;
}
+
EXEC SQL DESCRIBE s1 into :sqlda;
if (INGcheck() < 0) {
number = -1;
number = sqlda->sqld;
bail_out:
- free(stmt);
+ if (stmt_free) {
+ free(stmt);
+ }
free(sqlda);
return number;
}
-static inline IISQLDA *INGgetDescriptor(short numCols, const char *query)
+static inline IISQLDA *INGgetDescriptor(B_DB *mdb, short numCols, const char *query)
{
+ bool stmt_free = false;
EXEC SQL BEGIN DECLARE SECTION;
char *stmt;
EXEC SQL END DECLARE SECTION;
sqlda->sqln = numCols;
- stmt = bstrdup(query);
+ /*
+ * See if we need to run this through the limit_filter.
+ */
+ if (strstr(query, "LIMIT") != NULL) {
+ stmt = mdb->limit_filter->replace(query);
+ } else {
+ stmt = bstrdup(query);
+ stmt_free = true;
+ }
EXEC SQL PREPARE s2 INTO :sqlda FROM :stmt;
- free(stmt);
+ if (stmt_free) {
+ free(stmt);
+ }
for (i = 0; i < sqlda->sqld; ++i) {
/*
static void INGfreeDescriptor(IISQLDA *sqlda)
{
+ int i;
+
if (!sqlda) {
return;
}
- int i;
-
for (i = 0; i < sqlda->sqld; ++i) {
if (sqlda->sqlvar[i].sqldata) {
free(sqlda->sqlvar[i].sqldata);
static inline INGresult *INGgetINGresult(IISQLDA *sqlda)
{
+ int i;
+ INGresult *result = NULL;
+
if (!sqlda) {
return NULL;
}
- int i;
- INGresult *result = NULL;
-
result = (INGresult *)malloc(sizeof(INGresult));
memset(result, 0, sizeof(INGresult));
static void INGfreeINGresult(INGresult *ing_res)
{
+ int rows;
+ ING_ROW *rowtemp;
+
if (!ing_res) {
return;
}
- int rows;
- ING_ROW *rowtemp;
-
/*
* Free all rows and fields, then res, not descriptor!
+ *
+ * Use of rows is a nasty workaround til I find the reason,
+ * why aggregates like max() don't work
*/
- if (ing_res != NULL) {
- /*
- * Use of rows is a nasty workaround til I find the reason,
- * why aggregates like max() don't work
- */
- rows = ing_res->num_rows;
- 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;
- }
- if (ing_res->fields) {
- free(ing_res->fields);
- }
+ rows = ing_res->num_rows;
+ 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;
+ }
+ if (ing_res->fields) {
+ free(ing_res->fields);
}
free(ing_res);
ing_res = NULL;
static void INGrowSeek(INGresult *res, int row_number)
{
ING_ROW *trow = NULL;
+
if (res->act_row->row_number == row_number) {
return;
}
return;
}
- for (trow = res->first_row ; trow->row_number != row_number ; trow = trow->next );
+ for (trow = res->first_row; trow->row_number != row_number; trow = trow->next) ;
res->act_row = trow;
/*
* Note - can be null - if row_number not found, right?
if (row_number != res->act_row->row_number) {
INGrowSeek(res, row_number);
}
+
return res->act_row->sqlvar[column_number].sqldata;
}
if (row_number != res->act_row->row_number) {
INGrowSeek(res, row_number);
}
+
return (*res->act_row->sqlvar[column_number].sqlind == -1) 1 : 0;
}
return res->fields[column_number].type;
}
-int INGexec(INGconn *conn, const char *query)
+int INGexec(B_DB *mdb, INGconn *conn, const char *query)
{
+ bool stmt_free = false;
int check;
EXEC SQL BEGIN DECLARE SECTION;
int rowcount;
char *stmt;
EXEC SQL END DECLARE SECTION;
- stmt = bstrdup(query);
+ /*
+ * See if we need to run this through the limit_filter.
+ */
+ if (strstr(query, "LIMIT") != NULL) {
+ stmt = mdb->limit_filter->replace(query);
+ } else {
+ stmt = bstrdup(query);
+ stmt_free = true;
+ }
rowcount = -1;
EXEC SQL EXECUTE IMMEDIATE :stmt;
- free(stmt);
+
+ if (stmt_free) {
+ free(stmt);
+ }
+
if ((check = INGcheck()) < 0) {
return check;
}
return rowcount;
}
-INGresult *INGquery(INGconn *conn, const char *query)
+INGresult *INGquery(B_DB *mdb, INGconn *conn, const char *query)
{
/*
* TODO: error handling
IISQLDA *desc = NULL;
INGresult *res = NULL;
int rows = -1;
- int cols = INGgetCols(query);
+ int cols = INGgetCols(mdb, query);
desc = INGgetDescriptor(cols, query);
if (!desc) {
if (res == NULL) {
return;
}
- IISQLDA *desc = res->sqlda;
+
INGfreeINGresult(res);
- INGfreeDescriptor(desc);
+ INGfreeDescriptor(res->sqlda);
}
INGconn *INGconnectDB(char *dbname, char *user, char *passwd)
{
+ INGconn *dbconn;
+
if (dbname == NULL || strlen(dbname) == 0) {
return NULL;
}
- INGconn *dbconn = (INGconn *)malloc(sizeof(INGconn));
+ dbconn = (INGconn *)malloc(sizeof(INGconn));
memset(dbconn, 0, sizeof(INGconn));
EXEC SQL BEGIN DECLARE SECTION;
/* ---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);
+int INGcheck(void);
+short INGgetCols(B_DB *mdb, const char *stmt);
+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);
+int INGexec(B_DB *mdb, INGconn *db, const char *query);
+INGresult *INGquery(B_DB *mdb, 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);
+void INGdisconnectDB(INGconn *dbconn);
+char *INGerrorMessage(const INGconn *conn);
+char *INGcmdTuples(INGresult *res);
#endif /* _MYINGRES_SH */