From 02c8ba87e2c392cf555ab6797fe290795bd2b68d Mon Sep 17 00:00:00 2001 From: Stefan Reddig Date: Thu, 1 Apr 2010 18:04:58 +0200 Subject: [PATCH] fixed syntax LIMIT/NULL behavior/improved tests --- bacula/src/cats/ingres.c | 6 +- bacula/src/cats/make_ingres_tables.in | 2 +- bacula/src/cats/myingres.c | 177 ++++++++++++++------------ bacula/src/cats/myingres.sc | 110 +++++++++------- bacula/src/cats/sql_cmds.c | 89 ++++++++++++- bacula/src/cats/sql_find.c | 91 ++++++++++++- bacula/src/cats/sql_get.c | 73 +++++++++++ bacula/src/cats/sql_list.c | 8 ++ bacula/src/tools/ing_test.c | 155 +++++++++++++--------- regress/prototype.conf | 2 - 10 files changed, 520 insertions(+), 193 deletions(-) diff --git a/bacula/src/cats/ingres.c b/bacula/src/cats/ingres.c index 45d4a3485a..75067b8dc6 100755 --- a/bacula/src/cats/ingres.c +++ b/bacula/src/cats/ingres.c @@ -419,11 +419,13 @@ INGRES_ROW my_ingres_fetch_row(B_DB *mdb) mdb->row_size = num_fields; // now reset the row_number now that we have the space allocated - mdb->row_number = 1; + //mdb->row_number = 1; + mdb->row_number = 0; } // if still within the result set - if (mdb->row_number <= mdb->num_rows) { + //if (mdb->row_number <= mdb->num_rows) { + 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++) { diff --git a/bacula/src/cats/make_ingres_tables.in b/bacula/src/cats/make_ingres_tables.in index 78c3b5c23c..62908f34c4 100755 --- a/bacula/src/cats/make_ingres_tables.in +++ b/bacula/src/cats/make_ingres_tables.in @@ -174,7 +174,7 @@ CREATE TABLE media maxvolfiles integer default 0, maxvolbytes bigint default 0, inchanger smallint default 0, - StorageId integer default 0, + StorageId bigint default 0, DeviceId integer default 0, mediaaddressing smallint default 0, volreadtime bigint default 0, diff --git a/bacula/src/cats/myingres.c b/bacula/src/cats/myingres.c index e4d1751cfc..313a90ad99 100644 --- a/bacula/src/cats/myingres.c +++ b/bacula/src/cats/myingres.c @@ -6,6 +6,7 @@ #include extern IISQLCA sqlca; /* SQL Communications Area */ #include +/* # line 7 "myingres.sc" */ /* host code */ #include #include #include @@ -80,6 +81,15 @@ IISQLDA *INGgetDescriptor(short numCols, const char *stmt) /* # line 76 "myingres.sc" */ /* host code */ free(stmtd); for (i = 0; i < sqlda->sqld; ++i) { + /* + * Negative type indicates nullable coulumns, so an indicator + * is allocated, otherwise it's null + */ + if (sqlda->sqlvar[i].sqltype > 0) { + sqlda->sqlvar[i].sqlind = NULL; + } else { + sqlda->sqlvar[i].sqlind = (short *)malloc(sizeof(short)); + } /* * Alloc space for variable like indicated in sqllen * for date types sqllen is always 0 -> allocate by type @@ -95,7 +105,10 @@ IISQLDA *INGgetDescriptor(short numCols, const char *stmt) sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN); break; default: - sqlda->sqlvar[i].sqldata = (char *)malloc(sqlda->sqlvar[i].sqllen); + /* + * plus one to avoid zero mem allocs + */ + sqlda->sqlvar[i].sqldata = (char *)malloc(sqlda->sqlvar[i].sqllen+1); break; } } @@ -161,7 +174,7 @@ INGresult *INGgetINGresult(IISQLDA *sqlda) bstrncpy(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; + result->fields[i].flags = (sqlda->sqlvar[i].sqltype < 0) ? 1 : 0; } } return result; @@ -214,51 +227,59 @@ ING_ROW *INGgetRowSpace(INGresult *ing_res) * Make strings out of the data, then the space and assign * (why string? at least it seems that way, looking into the sources) */ - switch (ing_res->fields[i].type) { - case IISQ_VCH_TYPE: - len = ((ING_VARCHAR *)sqlda->sqlvar[i].sqldata)->len; - vars[i].sqldata = (char *)malloc(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); - 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); - switch (sqlda->sqlvar[i].sqllen) { - case 2: - bsnprintf(vars[i].sqldata, 20, "%d",*(short*)sqlda->sqlvar[i].sqldata); - break; - case 4: - bsnprintf(vars[i].sqldata, 20, "%ld",*(int*)sqlda->sqlvar[i].sqldata); - break; - case 8: - bsnprintf(vars[i].sqldata, 20, "%lld",*(long*)sqlda->sqlvar[i].sqldata); - break; - } - break; - case IISQ_TSTMP_TYPE: - vars[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN+1); - vars[i].sqldata[IISQ_TSTMP_LEN] = '\0'; - break; - case IISQ_TSWO_TYPE: - vars[i].sqldata = (char *)malloc(IISQ_TSWO_LEN+1); - vars[i].sqldata[IISQ_TSWO_LEN] = '\0'; - break; - case IISQ_TSW_TYPE: - vars[i].sqldata = (char *)malloc(IISQ_TSW_LEN+1); - vars[i].sqldata[IISQ_TSW_LEN] = '\0'; - break; - } vars[i].sqlind = (short *)malloc(sizeof(short)); if (sqlda->sqlvar[i].sqlind) { memcpy(vars[i].sqlind,sqlda->sqlvar[i].sqlind,sizeof(short)); } else { - *vars[i].sqlind = 0; + *vars[i].sqlind = NULL; + } + /* + * if sqlind pointer exists AND points to -1 -> column is 'null' + */ + if ( *vars[i].sqlind && (*vars[i].sqlind == -1)) { + vars[i].sqldata = NULL; + } else { + switch (ing_res->fields[i].type) { + case IISQ_VCH_TYPE: + len = ((ING_VARCHAR *)sqlda->sqlvar[i].sqldata)->len; + vars[i].sqldata = (char *)malloc(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); + 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); + switch (sqlda->sqlvar[i].sqllen) { + // %d,%ld,%lld + case 2: + bsnprintf(vars[i].sqldata, 20, "%hd",*(signed short*)sqlda->sqlvar[i].sqldata); + break; + case 4: + bsnprintf(vars[i].sqldata, 20, "%d",*(signed int*)sqlda->sqlvar[i].sqldata); + break; + case 8: + bsnprintf(vars[i].sqldata, 20, "%ld",*(signed long*)sqlda->sqlvar[i].sqldata); + break; + } + break; + case IISQ_TSTMP_TYPE: + vars[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN+1); + vars[i].sqldata[IISQ_TSTMP_LEN] = '\0'; + break; + case IISQ_TSWO_TYPE: + vars[i].sqldata = (char *)malloc(IISQ_TSWO_LEN+1); + vars[i].sqldata[IISQ_TSWO_LEN] = '\0'; + break; + case IISQ_TSW_TYPE: + vars[i].sqldata = (char *)malloc(IISQ_TSW_LEN+1); + vars[i].sqldata[IISQ_TSW_LEN] = '\0'; + break; + } } } return row; @@ -287,32 +308,32 @@ int INGfetchAll(const char *stmt, INGresult *ing_res) IISQLDA *desc; int check = -1; desc = ing_res->sqlda; -/* # line 317 "myingres.sc" */ /* host code */ +/* # line 335 "myingres.sc" */ /* host code */ if ((check = INGcheck()) < 0) { return check; } -/* # line 321 "myingres.sc" */ /* open */ +/* # line 339 "myingres.sc" */ /* open */ { IIsqInit(&sqlca); - IIcsOpen((char *)"c2",9341,8444); + IIcsOpen((char *)"c2",10703,7614); IIwritio(0,(short *)0,1,32,0,(char *)"s2"); - IIcsQuery((char *)"c2",9341,8444); + IIcsQuery((char *)"c2",10703,7614); } -/* # line 322 "myingres.sc" */ /* host code */ +/* # line 340 "myingres.sc" */ /* host code */ if ((check = INGcheck()) < 0) { return check; } /* for (linecount = 0; sqlca.sqlcode == 0; ++linecount) */ do { -/* # line 328 "myingres.sc" */ /* fetch */ +/* # line 346 "myingres.sc" */ /* fetch */ { IIsqInit(&sqlca); - if (IIcsRetScroll((char *)"c2",9341,8444,-1,-1) != 0) { + if (IIcsRetScroll((char *)"c2",10703,7614,-1,-1) != 0) { IIcsDaGet(0,desc); IIcsERetrieve(); } /* IIcsRetrieve */ } -/* # line 330 "myingres.sc" */ /* host code */ +/* # line 348 "myingres.sc" */ /* host code */ if ( (sqlca.sqlcode == 0) || (sqlca.sqlcode == -40202) ) { row = INGgetRowSpace(ing_res); /* alloc space for fetched row */ /* @@ -325,16 +346,16 @@ int INGfetchAll(const char *stmt, INGresult *ing_res) } ing_res->act_row->next = row; /* append row to old act_row */ ing_res->act_row = row; /* set row as act_row */ - ++linecount; row->row_number = linecount; + ++linecount; } } while ( (sqlca.sqlcode == 0) || (sqlca.sqlcode == -40202) ); -/* # line 348 "myingres.sc" */ /* close */ +/* # line 366 "myingres.sc" */ /* close */ { IIsqInit(&sqlca); - IIcsClose((char *)"c2",9341,8444); + IIcsClose((char *)"c2",10703,7614); } -/* # line 350 "myingres.sc" */ /* host code */ +/* # line 368 "myingres.sc" */ /* host code */ ing_res->status = ING_COMMAND_OK; ing_res->num_rows = linecount; return linecount; @@ -374,7 +395,7 @@ 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; + return (*res->act_row->sqlvar[column_number].sqlind == -1) ? 1 : 0; } int INGntuples(const INGresult *res) { @@ -399,31 +420,31 @@ short INGftype(const INGresult *res, int column_number) int INGexec(INGconn *conn, const char *query) { int check; -/* # line 425 "myingres.sc" */ +/* # line 443 "myingres.sc" */ int rowcount; char *stmt; -/* # line 428 "myingres.sc" */ +/* # line 446 "myingres.sc" */ stmt = (char *)malloc(strlen(query)+1); bstrncpy(stmt,query,strlen(query)+1); rowcount = -1; -/* # line 434 "myingres.sc" */ /* execute */ +/* # line 452 "myingres.sc" */ /* execute */ { IIsqInit(&sqlca); IIsqExImmed(stmt); IIsyncup((char *)0,0); } -/* # line 435 "myingres.sc" */ /* host code */ +/* # line 453 "myingres.sc" */ /* host code */ free(stmt); if ((check = INGcheck()) < 0) { return check; } -/* # line 440 "myingres.sc" */ /* inquire_ingres */ +/* # line 458 "myingres.sc" */ /* inquire_ingres */ { IILQisInqSqlio((short *)0,1,30,sizeof(rowcount),&rowcount,8); } -/* # line 441 "myingres.sc" */ /* host code */ +/* # line 459 "myingres.sc" */ /* host code */ if ((check = INGcheck()) < 0) { return check; } @@ -470,14 +491,14 @@ INGconn *INGconnectDB(char *dbname, char *user, char *passwd) } INGconn *dbconn = (INGconn *)malloc(sizeof(INGconn)); memset(dbconn, 0, sizeof(INGconn)); -/* # line 495 "myingres.sc" */ +/* # line 513 "myingres.sc" */ char ingdbname[24]; char ingdbuser[32]; char ingdbpasw[32]; char conn_name[32]; int sess_id; -/* # line 501 "myingres.sc" */ +/* # line 519 "myingres.sc" */ bstrncpy(ingdbname, dbname, sizeof(ingdbname)); if (user != NULL) { @@ -487,7 +508,7 @@ INGconn *INGconnectDB(char *dbname, char *user, char *passwd) } else { memset(ingdbpasw, 0, sizeof(ingdbpasw)); } -/* # line 512 "myingres.sc" */ /* connect */ +/* # line 530 "myingres.sc" */ /* connect */ { IIsqInit(&sqlca); IIsqUser(ingdbuser); @@ -495,26 +516,26 @@ INGconn *INGconnectDB(char *dbname, char *user, char *passwd) (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0, (char *)0); } -/* # line 516 "myingres.sc" */ /* host code */ +/* # line 534 "myingres.sc" */ /* host code */ } else { -/* # line 517 "myingres.sc" */ /* connect */ +/* # line 535 "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 518 "myingres.sc" */ /* host code */ +/* # line 536 "myingres.sc" */ /* host code */ } -/* # line 520 "myingres.sc" */ /* inquire_sql */ +/* # line 538 "myingres.sc" */ /* inquire_sql */ { IILQisInqSqlio((short *)0,1,32,31,conn_name,13); } -/* # line 521 "myingres.sc" */ /* inquire_sql */ +/* # line 539 "myingres.sc" */ /* inquire_sql */ { IILQisInqSqlio((short *)0,1,30,sizeof(sess_id),&sess_id,11); } -/* # line 523 "myingres.sc" */ /* host code */ +/* # line 541 "myingres.sc" */ /* host code */ bstrncpy(dbconn->dbname, ingdbname, sizeof(dbconn->dbname)); bstrncpy(dbconn->user, ingdbuser, sizeof(dbconn->user)); bstrncpy(dbconn->password, ingdbpasw, sizeof(dbconn->password)); @@ -529,12 +550,12 @@ void INGdisconnectDB(INGconn *dbconn) /* * TODO: check for any real use of dbconn: maybe whenn multithreaded? */ -/* # line 539 "myingres.sc" */ /* disconnect */ +/* # line 557 "myingres.sc" */ /* disconnect */ { IIsqInit(&sqlca); IIsqDisconnect(); } -/* # line 540 "myingres.sc" */ /* host code */ +/* # line 558 "myingres.sc" */ /* host code */ if (dbconn != NULL) { free(dbconn->msg); free(dbconn); @@ -542,16 +563,16 @@ void INGdisconnectDB(INGconn *dbconn) } char *INGerrorMessage(const INGconn *conn) { -/* # line 548 "myingres.sc" */ +/* # line 566 "myingres.sc" */ char errbuf[256]; -/* # line 550 "myingres.sc" */ +/* # line 568 "myingres.sc" */ -/* # line 552 "myingres.sc" */ /* inquire_ingres */ +/* # line 570 "myingres.sc" */ /* inquire_ingres */ { IILQisInqSqlio((short *)0,1,32,255,errbuf,63); } -/* # line 553 "myingres.sc" */ /* host code */ +/* # line 571 "myingres.sc" */ /* host code */ memcpy(conn->msg,&errbuf,256); return conn->msg; } @@ -563,5 +584,5 @@ char *INGcmdTuples(INGresult *res) int INGputCopyEnd(INGconn *conn, const char *errormsg); int INGputCopyData(INGconn *conn, const char *buffer, int nbytes); */ -/* # line 567 "myingres.sc" */ +/* # line 585 "myingres.sc" */ #endif diff --git a/bacula/src/cats/myingres.sc b/bacula/src/cats/myingres.sc index 4143577d71..068a3d621f 100644 --- a/bacula/src/cats/myingres.sc +++ b/bacula/src/cats/myingres.sc @@ -76,6 +76,15 @@ IISQLDA *INGgetDescriptor(short numCols, const char *stmt) free(stmtd); for (i = 0; i < sqlda->sqld; ++i) { + /* + * Negative type indicates nullable coulumns, so an indicator + * is allocated, otherwise it's null + */ + if (sqlda->sqlvar[i].sqltype > 0) { + sqlda->sqlvar[i].sqlind = NULL; + } else { + sqlda->sqlvar[i].sqlind = (short *)malloc(sizeof(short)); + } /* * Alloc space for variable like indicated in sqllen * for date types sqllen is always 0 -> allocate by type @@ -91,7 +100,10 @@ IISQLDA *INGgetDescriptor(short numCols, const char *stmt) sqlda->sqlvar[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN); break; default: - sqlda->sqlvar[i].sqldata = (char *)malloc(sqlda->sqlvar[i].sqllen); + /* + * plus one to avoid zero mem allocs + */ + sqlda->sqlvar[i].sqldata = (char *)malloc(sqlda->sqlvar[i].sqllen+1); break; } } @@ -170,7 +182,7 @@ INGresult *INGgetINGresult(IISQLDA *sqlda) bstrncpy(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; + result->fields[i].flags = (sqlda->sqlvar[i].sqltype < 0) ? 1 : 0; } } @@ -232,54 +244,60 @@ ING_ROW *INGgetRowSpace(INGresult *ing_res) * Make strings out of the data, then the space and assign * (why string? at least it seems that way, looking into the sources) */ - switch (ing_res->fields[i].type) { - case IISQ_VCH_TYPE: - len = ((ING_VARCHAR *)sqlda->sqlvar[i].sqldata)->len; - vars[i].sqldata = (char *)malloc(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); - 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); - switch (sqlda->sqlvar[i].sqllen) { - case 2: - bsnprintf(vars[i].sqldata, 20, "%d",*(short*)sqlda->sqlvar[i].sqldata); - break; - case 4: - bsnprintf(vars[i].sqldata, 20, "%ld",*(int*)sqlda->sqlvar[i].sqldata); - break; - case 8: - bsnprintf(vars[i].sqldata, 20, "%lld",*(long*)sqlda->sqlvar[i].sqldata); - break; - } - break; - case IISQ_TSTMP_TYPE: - vars[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN+1); - vars[i].sqldata[IISQ_TSTMP_LEN] = '\0'; - break; - case IISQ_TSWO_TYPE: - vars[i].sqldata = (char *)malloc(IISQ_TSWO_LEN+1); - vars[i].sqldata[IISQ_TSWO_LEN] = '\0'; - break; - case IISQ_TSW_TYPE: - vars[i].sqldata = (char *)malloc(IISQ_TSW_LEN+1); - vars[i].sqldata[IISQ_TSW_LEN] = '\0'; - break; - } vars[i].sqlind = (short *)malloc(sizeof(short)); if (sqlda->sqlvar[i].sqlind) { memcpy(vars[i].sqlind,sqlda->sqlvar[i].sqlind,sizeof(short)); } else { - *vars[i].sqlind = 0; + *vars[i].sqlind = NULL; + } + /* + * if sqlind pointer exists AND points to -1 -> column is 'null' + */ + if ( *vars[i].sqlind && (*vars[i].sqlind == -1)) { + vars[i].sqldata = NULL; + } else { + switch (ing_res->fields[i].type) { + case IISQ_VCH_TYPE: + len = ((ING_VARCHAR *)sqlda->sqlvar[i].sqldata)->len; + vars[i].sqldata = (char *)malloc(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); + 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); + switch (sqlda->sqlvar[i].sqllen) { + case 2: + bsnprintf(vars[i].sqldata, 20, "%d",*(short*)sqlda->sqlvar[i].sqldata); + break; + case 4: + bsnprintf(vars[i].sqldata, 20, "%ld",*(int*)sqlda->sqlvar[i].sqldata); + break; + case 8: + bsnprintf(vars[i].sqldata, 20, "%lld",*(long*)sqlda->sqlvar[i].sqldata); + break; + } + break; + case IISQ_TSTMP_TYPE: + vars[i].sqldata = (char *)malloc(IISQ_TSTMP_LEN+1); + vars[i].sqldata[IISQ_TSTMP_LEN] = '\0'; + break; + case IISQ_TSWO_TYPE: + vars[i].sqldata = (char *)malloc(IISQ_TSWO_LEN+1); + vars[i].sqldata[IISQ_TSWO_LEN] = '\0'; + break; + case IISQ_TSW_TYPE: + vars[i].sqldata = (char *)malloc(IISQ_TSW_LEN+1); + vars[i].sqldata[IISQ_TSW_LEN] = '\0'; + break; + } } } - return row; } @@ -340,8 +358,8 @@ int INGfetchAll(const char *stmt, INGresult *ing_res) } ing_res->act_row->next = row; /* append row to old act_row */ ing_res->act_row = row; /* set row as act_row */ - ++linecount; row->row_number = linecount; + ++linecount; } } while ( (sqlca.sqlcode == 0) || (sqlca.sqlcode == -40202) ); @@ -392,7 +410,7 @@ 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; + return (*res->act_row->sqlvar[column_number].sqlind == -1) 1 : 0; } int INGntuples(const INGresult *res) diff --git a/bacula/src/cats/sql_cmds.c b/bacula/src/cats/sql_cmds.c index c930e6369d..b8dd1b4c9b 100644 --- a/bacula/src/cats/sql_cmds.c +++ b/bacula/src/cats/sql_cmds.c @@ -287,11 +287,19 @@ const char *uar_count_files = "SELECT JobFiles FROM Job WHERE JobId=%s"; /* List last 20 Jobs */ +#if HAVE_INGRES +const char *uar_list_jobs = + "SELECT JobId,Client.Name as Client,StartTime,Level as " + "JobLevel,JobFiles,JobBytes " + "FROM Client,Job WHERE Client.ClientId=Job.ClientId AND JobStatus IN ('T','W') " + "AND Type='B' ORDER BY StartTime DESC FETCH FIRST 20 ROWS ONLY"; +#else const char *uar_list_jobs = "SELECT JobId,Client.Name as Client,StartTime,Level as " "JobLevel,JobFiles,JobBytes " "FROM Client,Job WHERE Client.ClientId=Job.ClientId AND JobStatus IN ('T','W') " "AND Type='B' ORDER BY StartTime DESC LIMIT 20"; +#endif const char *uar_print_jobs = "SELECT DISTINCT JobId,Level,JobFiles,JobBytes,StartTime,VolumeName" @@ -312,6 +320,21 @@ const char *uar_sel_files = const char *uar_del_temp = "DROP TABLE temp"; const char *uar_del_temp1 = "DROP TABLE temp1"; +#if HAVE_INGRES +const char *uar_last_full = + "INSERT INTO temp1 SELECT Job.JobId,JobTdate " + "FROM Client,Job,JobMedia,Media,FileSet WHERE Client.ClientId=%s " + "AND Job.ClientId=%s " + "AND Job.StartTime < '%s' " + "AND Level='F' AND JobStatus IN ('T','W') AND Type='B' " + "AND JobMedia.JobId=Job.JobId " + "AND Media.Enabled=1 " + "AND JobMedia.MediaId=Media.MediaId " + "AND Job.FileSetId=FileSet.FileSetId " + "AND FileSet.FileSet='%s' " + "%s" + "ORDER BY Job.JobTDate DESC FETCH FIRST 1 ROW ONLY"; +#else const char *uar_last_full = "INSERT INTO temp1 SELECT Job.JobId,JobTdate " "FROM Client,Job,JobMedia,Media,FileSet WHERE Client.ClientId=%s " @@ -325,6 +348,7 @@ const char *uar_last_full = "AND FileSet.FileSet='%s' " "%s" "ORDER BY Job.JobTDate DESC LIMIT 1"; +#endif const char *uar_full = "INSERT INTO temp SELECT Job.JobId,Job.JobTDate," @@ -336,6 +360,24 @@ const char *uar_full = "AND JobMedia.JobId=Job.JobId " "AND JobMedia.MediaId=Media.MediaId"; +#if HAVE_INGRES +const char *uar_dif = + "INSERT INTO temp SELECT Job.JobId,Job.JobTDate,Job.ClientId," + "Job.Level,Job.JobFiles,Job.JobBytes," + "Job.StartTime,Media.VolumeName,JobMedia.StartFile," + "Job.VolSessionId,Job.VolSessionTime " + "FROM Job,JobMedia,Media,FileSet " + "WHERE Job.JobTDate>%s AND Job.StartTime<'%s' " + "AND Job.ClientId=%s " + "AND JobMedia.JobId=Job.JobId " + "AND Media.Enabled=1 " + "AND JobMedia.MediaId=Media.MediaId " + "AND Job.Level='D' AND JobStatus IN ('T','W') AND Type='B' " + "AND Job.FileSetId=FileSet.FileSetId " + "AND FileSet.FileSet='%s' " + "%s" + "ORDER BY Job.JobTDate DESC FETCH FIRST 1 ROW ONLY"; +#else const char *uar_dif = "INSERT INTO temp SELECT Job.JobId,Job.JobTDate,Job.ClientId," "Job.Level,Job.JobFiles,Job.JobBytes," @@ -352,6 +394,7 @@ const char *uar_dif = "AND FileSet.FileSet='%s' " "%s" "ORDER BY Job.JobTDate DESC LIMIT 1"; +#endif const char *uar_inc = "INSERT INTO temp SELECT Job.JobId,Job.JobTDate,Job.ClientId," @@ -400,6 +443,20 @@ const char *uar_mediatype = * Find JobId, FileIndex for a given path/file and date * for use when inserting individual files into the tree. */ +#if HAVE_INGRES +const char *uar_jobid_fileindex = + "SELECT Job.JobId,File.FileIndex FROM Job,File,Path,Filename,Client " + "WHERE Job.JobId=File.JobId " + "AND Job.StartTime<='%s' " + "AND Path.Path='%s' " + "AND Filename.Name='%s' " + "AND Client.Name='%s' " + "AND Job.ClientId=Client.ClientId " + "AND Path.PathId=File.PathId " + "AND Filename.FilenameId=File.FilenameId " + "AND JobStatus IN ('T','W') AND Type='B' " + "ORDER BY Job.StartTime DESC FETCH FIRST 1 ROW ONLY"; +#else const char *uar_jobid_fileindex = "SELECT Job.JobId,File.FileIndex FROM Job,File,Path,Filename,Client " "WHERE Job.JobId=File.JobId " @@ -412,7 +469,22 @@ const char *uar_jobid_fileindex = "AND Filename.FilenameId=File.FilenameId " "AND JobStatus IN ('T','W') AND Type='B' " "ORDER BY Job.StartTime DESC LIMIT 1"; +#endif +#if HAVE_INGRES +const char *uar_jobids_fileindex = + "SELECT Job.JobId,File.FileIndex FROM Job,File,Path,Filename,Client " + "WHERE Job.JobId IN (%s) " + "AND Job.JobId=File.JobId " + "AND Job.StartTime<='%s' " + "AND Path.Path='%s' " + "AND Filename.Name='%s' " + "AND Client.Name='%s' " + "AND Job.ClientId=Client.ClientId " + "AND Path.PathId=File.PathId " + "AND Filename.FilenameId=File.FilenameId " + "ORDER BY Job.StartTime DESC FETCH FIRST 1 ROW ONLY"; +#else const char *uar_jobids_fileindex = "SELECT Job.JobId,File.FileIndex FROM Job,File,Path,Filename,Client " "WHERE Job.JobId IN (%s) " @@ -425,6 +497,7 @@ const char *uar_jobids_fileindex = "AND Path.PathId=File.PathId " "AND Filename.FilenameId=File.FilenameId " "ORDER BY Job.StartTime DESC LIMIT 1"; +#endif /* Query to get list of files from table -- presuably built by an external program */ const char *uar_jobid_fileindex_from_table = @@ -690,7 +763,17 @@ const char *uar_file[4] = { "AND Client.ClientId=Job.ClientId " "AND Job.JobId=File.JobId AND File.FileIndex > 0 " "AND Path.PathId=File.PathId AND Filename.FilenameId=File.FilenameId " - "AND Filename.Name='%s' ORDER BY StartTime DESC LIMIT 20"}; + "AND Filename.Name='%s' ORDER BY StartTime DESC LIMIT 20", + /* Ingres */ + "SELECT Job.JobId as JobId," + "Path.Path||Filename.Name as Name, " + "StartTime,Type as JobType,JobStatus,JobFiles,JobBytes " + "FROM Client,Job,File,Filename,Path WHERE Client.Name='%s' " + "AND Client.ClientId=Job.ClientId " + "AND Job.JobId=File.JobId AND File.FileIndex > 0 " + "AND Path.PathId=File.PathId AND Filename.FilenameId=File.FilenameId " + "AND Filename.Name='%s' ORDER BY StartTime DESC FETCH FIRST 20 ROWS ONLY" + }; const char *uar_create_temp[5] = { /* Mysql */ @@ -753,8 +836,8 @@ const char *uar_create_temp[5] = { "Level CHAR," "JobFiles INTEGER," "JobBytes BIGINT," - "StartTime TEXT," - "VolumeName TEXT," + "StartTime VARCHAR(256)," + "VolumeName VARCHAR(256)," "StartFile INTEGER," "VolSessionId INTEGER," "VolSessionTime INTEGER)" diff --git a/bacula/src/cats/sql_find.c b/bacula/src/cats/sql_find.c index fb77dee9d5..6247e10ce0 100644 --- a/bacula/src/cats/sql_find.c +++ b/bacula/src/cats/sql_find.c @@ -75,12 +75,21 @@ db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime) /* If no Id given, we must find corresponding job */ if (jr->JobId == 0) { /* Differential is since last Full backup */ +#if HAVE_INGRES + Mmsg(mdb->cmd, +"SELECT StartTime FROM Job WHERE JobStatus IN ('T','W') AND Type='%c' AND " +"Level='%c' AND Name='%s' AND ClientId=%s AND FileSetId=%s " +"ORDER BY StartTime DESC FETCH FIRST 1 ROW ONLY", + jr->JobType, L_FULL, jr->Name, + edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2)); +#else Mmsg(mdb->cmd, "SELECT StartTime FROM Job WHERE JobStatus IN ('T','W') AND Type='%c' AND " "Level='%c' AND Name='%s' AND ClientId=%s AND FileSetId=%s " "ORDER BY StartTime DESC LIMIT 1", jr->JobType, L_FULL, jr->Name, edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2)); +#endif if (jr->JobLevel == L_DIFFERENTIAL) { /* SQL cmd for Differential backup already edited above */ @@ -105,12 +114,21 @@ db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime) } sql_free_result(mdb); /* Now edit SQL command for Incremental Job */ +#if HAVE_INGRES + Mmsg(mdb->cmd, +"SELECT StartTime FROM Job WHERE JobStatus IN ('T','W') AND Type='%c' AND " +"Level IN ('%c','%c','%c') AND Name='%s' AND ClientId=%s " +"AND FileSetId=%s ORDER BY StartTime DESC FETCH FIRST 1 ROW ONLY", + jr->JobType, L_INCREMENTAL, L_DIFFERENTIAL, L_FULL, jr->Name, + edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2)); +#else Mmsg(mdb->cmd, "SELECT StartTime FROM Job WHERE JobStatus IN ('T','W') AND Type='%c' AND " "Level IN ('%c','%c','%c') AND Name='%s' AND ClientId=%s " "AND FileSetId=%s ORDER BY StartTime DESC LIMIT 1", jr->JobType, L_INCREMENTAL, L_DIFFERENTIAL, L_FULL, jr->Name, edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2)); +#endif } else { Mmsg1(mdb->errmsg, _("Unknown level=%d\n"), jr->JobLevel); goto bail_out; @@ -166,12 +184,21 @@ db_find_last_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime, i pm_strcpy(stime, "0000-00-00 00:00:00"); /* default */ +#if HAVE_INGRES + Mmsg(mdb->cmd, +"SELECT StartTime FROM Job WHERE JobStatus IN ('T','W') AND Type='%c' AND " +"Level='%c' AND Name='%s' AND ClientId=%s AND FileSetId=%s " +"ORDER BY StartTime DESC FETCH FIRST 1 ROW ONLY", + jr->JobType, JobLevel, jr->Name, + edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2)); +#else Mmsg(mdb->cmd, "SELECT StartTime FROM Job WHERE JobStatus IN ('T','W') AND Type='%c' AND " "Level='%c' AND Name='%s' AND ClientId=%s AND FileSetId=%s " "ORDER BY StartTime DESC LIMIT 1", jr->JobType, JobLevel, jr->Name, edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2)); +#endif if (!QUERY_DB(jcr, mdb, mdb->cmd)) { Mmsg2(&mdb->errmsg, _("Query error for start time request: ERR=%s\nCMD=%s\n"), sql_strerror(mdb), mdb->cmd); @@ -209,6 +236,16 @@ db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int & db_lock(mdb); /* Differential is since last Full backup */ +#if HAVE_INGRES + Mmsg(mdb->cmd, +"SELECT Level FROM Job WHERE JobStatus NOT IN ('T','W') AND " +"Type='%c' AND Level IN ('%c','%c') AND Name='%s' AND ClientId=%s " +"AND FileSetId=%s AND StartTime>'%s' " +"ORDER BY StartTime DESC FETCH FIRST 1 ROW ONLY", + jr->JobType, L_FULL, L_DIFFERENTIAL, jr->Name, + edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2), + stime); +#else Mmsg(mdb->cmd, "SELECT Level FROM Job WHERE JobStatus NOT IN ('T','W') AND " "Type='%c' AND Level IN ('%c','%c') AND Name='%s' AND ClientId=%s " @@ -217,7 +254,7 @@ db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int & jr->JobType, L_FULL, L_DIFFERENTIAL, jr->Name, edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2), stime); - +#endif if (!QUERY_DB(jcr, mdb, mdb->cmd)) { db_unlock(mdb); return false; @@ -254,24 +291,46 @@ db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr) db_lock(mdb); Dmsg2(100, "JobLevel=%d JobType=%d\n", jr->JobLevel, jr->JobType); if (jr->JobLevel == L_VERIFY_CATALOG) { +#if HAVE_INGRES + Mmsg(mdb->cmd, +"SELECT JobId FROM Job WHERE Type='V' AND Level='%c' AND " +" JobStatus IN ('T','W') AND Name='%s' AND " +"ClientId=%s ORDER BY StartTime DESC FETCH FIRST 1 ROW ONLY", + L_VERIFY_INIT, jr->Name, + edit_int64(jr->ClientId, ed1)); +#else Mmsg(mdb->cmd, "SELECT JobId FROM Job WHERE Type='V' AND Level='%c' AND " " JobStatus IN ('T','W') AND Name='%s' AND " "ClientId=%s ORDER BY StartTime DESC LIMIT 1", L_VERIFY_INIT, jr->Name, edit_int64(jr->ClientId, ed1)); +#endif } else if (jr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG || jr->JobLevel == L_VERIFY_DISK_TO_CATALOG || jr->JobType == JT_BACKUP) { if (Name) { +#if HAVE_INGRES + Mmsg(mdb->cmd, +"SELECT JobId FROM Job WHERE Type='B' AND JobStatus IN ('T','W') AND " +"Name='%s' ORDER BY StartTime DESC FETCH FIRST 1 ROW ONLY", Name); +#else Mmsg(mdb->cmd, "SELECT JobId FROM Job WHERE Type='B' AND JobStatus IN ('T','W') AND " "Name='%s' ORDER BY StartTime DESC LIMIT 1", Name); +#endif } else { +#if HAVE_INGRES + Mmsg(mdb->cmd, +"SELECT JobId FROM Job WHERE Type='B' AND JobStatus IN ('T','W') AND " +"ClientId=%s ORDER BY StartTime DESC FETCH FIRST 1 ROW ONLY", + edit_int64(jr->ClientId, ed1)); +#else Mmsg(mdb->cmd, "SELECT JobId FROM Job WHERE Type='B' AND JobStatus IN ('T','W') AND " "ClientId=%s ORDER BY StartTime DESC LIMIT 1", edit_int64(jr->ClientId, ed1)); +#endif } } else { Mmsg1(&mdb->errmsg, _("Unknown Job level=%d\n"), jr->JobLevel); @@ -324,6 +383,19 @@ db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr db_lock(mdb); if (item == -1) { /* find oldest volume */ /* Find oldest volume */ +#if HAVE_INGRES + Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," + "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," + "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs," + "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger," + "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId," + "Enabled,LocationId,RecycleCount,InitialWrite," + "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime,ActionOnPurge " + "FROM Media WHERE PoolId=%s AND MediaType='%s' AND VolStatus IN ('Full'," + "'Recycle','Purged','Used','Append') AND Enabled=1 " + "ORDER BY LastWritten FETCH FIRST 1 ROW ONLY", + edit_int64(mr->PoolId, ed1), mr->MediaType); +#else Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs," @@ -335,6 +407,7 @@ db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr "'Recycle','Purged','Used','Append') AND Enabled=1 " "ORDER BY LastWritten LIMIT 1", edit_int64(mr->PoolId, ed1), mr->MediaType); +#endif item = 1; } else { POOL_MEM changer(PM_FNAME); @@ -349,6 +422,21 @@ db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr } else { order = "ORDER BY LastWritten IS NULL,LastWritten DESC,MediaId"; /* take most recently written */ } +#if HAVE_INGRES + Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," + "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," + "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs," + "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger," + "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId," + "Enabled,LocationId,RecycleCount,InitialWrite," + "ScratchPoolId,RecyclePoolId,VolReadTime,VolWriteTime,ActionOnPurge " + "FROM Media WHERE PoolId=%s AND MediaType='%s' AND Enabled=1 " + "AND VolStatus='%s' " + "%s " + "%s FETCH FIRST %d ROWS ONLY", + edit_int64(mr->PoolId, ed1), mr->MediaType, + mr->VolStatus, changer.c_str(), order, item); +#else Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs," @@ -362,6 +450,7 @@ db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr "%s LIMIT %d", edit_int64(mr->PoolId, ed1), mr->MediaType, mr->VolStatus, changer.c_str(), order, item); +#endif } Dmsg1(050, "fnextvol=%s\n", mdb->cmd); if (!QUERY_DB(jcr, mdb, mdb->cmd)) { diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index b5e9c9677d..729d53b98a 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -116,6 +116,16 @@ int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr) char ed1[50], ed2[50], ed3[50]; if (jcr->getJobLevel() == L_VERIFY_DISK_TO_CATALOG) { +#if HAVE_INGRES + Mmsg(mdb->cmd, +"SELECT FileId, LStat, MD5 FROM File,Job WHERE " +"File.JobId=Job.JobId AND File.PathId=%s AND " +"File.FilenameId=%s AND Job.Type='B' AND Job.JobStatus IN ('T','W') AND " +"ClientId=%s ORDER BY StartTime DESC FETCH FIRST 1 ROW ONLY", + edit_int64(fdbr->PathId, ed1), + edit_int64(fdbr->FilenameId, ed2), + edit_int64(jr->ClientId,ed3)); +#else Mmsg(mdb->cmd, "SELECT FileId, LStat, MD5 FROM File,Job WHERE " "File.JobId=Job.JobId AND File.PathId=%s AND " @@ -124,6 +134,7 @@ int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr) edit_int64(fdbr->PathId, ed1), edit_int64(fdbr->FilenameId, ed2), edit_int64(jr->ClientId,ed3)); +#endif } else { Mmsg(mdb->cmd, "SELECT FileId, LStat, MD5 FROM File WHERE File.JobId=%s AND File.PathId=%s AND " @@ -790,9 +801,15 @@ int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr) "WHERE FileSetId=%s", edit_int64(fsr->FileSetId, ed1)); } else { /* find by name */ +#if HAVE_INGRES + Mmsg(mdb->cmd, + "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet " + "WHERE FileSet='%s' ORDER BY CreateTime DESC FETCH FIRST 1 ROW ONLY", fsr->FileSet); +#else Mmsg(mdb->cmd, "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet " "WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", fsr->FileSet); +#endif } if (QUERY_DB(jcr, mdb, mdb->cmd)) { @@ -1163,6 +1180,21 @@ bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb, jobids->count = 0; /* First, find the last good Full backup for this job/client/fileset */ +#if HAVE_INGRES + Mmsg(query, +"CREATE TABLE btemp3%s AS " + "SELECT JobId, StartTime, EndTime, JobTDate, PurgedFiles " + "FROM Job JOIN FileSet USING (FileSetId) " + "WHERE ClientId = %s " + "AND Level='F' AND JobStatus IN ('T','W') AND Type='B' " + "AND StartTime<'%s' " + "AND FileSet.FileSet=(SELECT FileSet FROM FileSet WHERE FileSetId = %s) " + "ORDER BY Job.JobTDate DESC FETCH FIRST 1 ROW ONLY", + edit_uint64(jcr->JobId, jobid), + edit_uint64(jr->ClientId, clientid), + date, + edit_uint64(jr->FileSetId, filesetid)); +#else Mmsg(query, "CREATE TABLE btemp3%s AS " "SELECT JobId, StartTime, EndTime, JobTDate, PurgedFiles " @@ -1176,6 +1208,7 @@ bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb, edit_uint64(jr->ClientId, clientid), date, edit_uint64(jr->FileSetId, filesetid)); +#endif if (!db_sql_query(mdb, query.c_str(), NULL, NULL)) { goto bail_out; @@ -1183,6 +1216,23 @@ bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb, if (jr->JobLevel == L_INCREMENTAL || jr->JobLevel == L_VIRTUAL_FULL) { /* Now, find the last differential backup after the last full */ +#if HAVE_INGRES + Mmsg(query, +"INSERT INTO btemp3%s (JobId, StartTime, EndTime, JobTDate, PurgedFiles) " + "SELECT JobId, StartTime, EndTime, JobTDate, PurgedFiles " + "FROM Job JOIN FileSet USING (FileSetId) " + "WHERE ClientId = %s " + "AND Level='D' AND JobStatus IN ('T','W') AND Type='B' " + "AND StartTime > (SELECT EndTime FROM btemp3%s ORDER BY EndTime DESC LIMIT 1) " + "AND StartTime < '%s' " + "AND FileSet.FileSet= (SELECT FileSet FROM FileSet WHERE FileSetId = %s) " + "ORDER BY Job.JobTDate DESC FETCH FIRST 1 ROW ONLY ", + jobid, + clientid, + jobid, + date, + filesetid); +#else Mmsg(query, "INSERT INTO btemp3%s (JobId, StartTime, EndTime, JobTDate, PurgedFiles) " "SELECT JobId, StartTime, EndTime, JobTDate, PurgedFiles " @@ -1198,12 +1248,30 @@ bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb, jobid, date, filesetid); +#endif if (!db_sql_query(mdb, query.c_str(), NULL, NULL)) { goto bail_out; } /* We just have to take all incremental after the last Full/Diff */ +#if HAVE_INGRES + Mmsg(query, +"INSERT INTO btemp3%s (JobId, StartTime, EndTime, JobTDate, PurgedFiles) " + "SELECT JobId, StartTime, EndTime, JobTDate, PurgedFiles " + "FROM Job JOIN FileSet USING (FileSetId) " + "WHERE ClientId = %s " + "AND Level='I' AND JobStatus IN ('T','W') AND Type='B' " + "AND StartTime > (SELECT EndTime FROM btemp3%s ORDER BY EndTime DESC FETCH FIRST 1 ROW ONLY) " + "AND StartTime < '%s' " + "AND FileSet.FileSet= (SELECT FileSet FROM FileSet WHERE FileSetId = %s) " + "ORDER BY Job.JobTDate DESC ", + jobid, + clientid, + jobid, + date, + filesetid); +#else Mmsg(query, "INSERT INTO btemp3%s (JobId, StartTime, EndTime, JobTDate, PurgedFiles) " "SELECT JobId, StartTime, EndTime, JobTDate, PurgedFiles " @@ -1219,6 +1287,7 @@ bool db_accurate_get_jobids(JCR *jcr, B_DB *mdb, jobid, date, filesetid); +#endif if (!db_sql_query(mdb, query.c_str(), NULL, NULL)) { goto bail_out; } @@ -1275,6 +1344,10 @@ bool db_get_base_jobid(JCR *jcr, B_DB *mdb, JOB_DBR *jr, JobId_t *jobid) // "AND FileSet.FileSet= '%s' " // "AND Client.Name = '%s' " "AND StartTime<'%s' " +#if HAVE_INGRES +#else + "ORDER BY Job.JobTDate DESC FETCH FIRST 1 ROW ONLY", +#endif "ORDER BY Job.JobTDate DESC LIMIT 1", jr->Name, // edit_uint64(jr->ClientId, clientid), diff --git a/bacula/src/cats/sql_list.c b/bacula/src/cats/sql_list.c index aa903a0ca0..4942ca7940 100644 --- a/bacula/src/cats/sql_list.c +++ b/bacula/src/cats/sql_list.c @@ -249,7 +249,11 @@ void db_list_copies_records(JCR *jcr, B_DB *mdb, uint32_t limit, char *JobIds, POOL_MEM str_jobids(PM_MESSAGE); if (limit > 0) { +#if HAVE_INGRES + Mmsg(str_limit, " FETCH FIRST %d ROWS ONLY", limit); +#else Mmsg(str_limit, " LIMIT %d", limit); +#endif } if (JobIds && JobIds[0]) { @@ -330,7 +334,11 @@ db_list_job_records(JCR *jcr, B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, char limit[100]; db_lock(mdb); if (jr->limit > 0) { +#if HAVE_INGRES + snprintf(limit, sizeof(limit), " FETCH FIRST %d ROWS ONLY", jr->limit); +#else snprintf(limit, sizeof(limit), " LIMIT %d", jr->limit); +#endif } else { limit[0] = 0; } diff --git a/bacula/src/tools/ing_test.c b/bacula/src/tools/ing_test.c index d8b0505749..9bf5400075 100644 --- a/bacula/src/tools/ing_test.c +++ b/bacula/src/tools/ing_test.c @@ -77,7 +77,7 @@ PROG_COPYRIGHT */ static int test_handler(void *ctx, int num_fields, char **row) { - Dmsg2(200, " Values are %d, %s\n", str_to_int64(row[0]), row[1]); + Pmsg2(0, " Values are %d, %s\n", str_to_int64(row[0]), row[1]); return 0; } @@ -86,7 +86,7 @@ static int test_handler(void *ctx, int num_fields, char **row) */ static int string_handler(void *ctx, int num_fields, char **row) { - Dmsg1(200, " Value is >>%s<<\n", row[0]); + Pmsg1(0, " Value is >>%s<<\n", row[0]); return 0; } @@ -199,75 +199,110 @@ int main (int argc, char *argv[]) if (verbose) { Pmsg2(000, _("Using Database: %s, User: %s\n"), db_name, db_user); } - - - /* simple CRUD test including create/drop table */ + /* + * simple CRUD test including create/drop table + */ Pmsg0(0, "\nsimple CRUD test...\n\n"); - - Dmsg0(200, "DB-Statement: CREATE TABLE t1 ( c1 integer, c2 varchar(29))\n"); - if (!db_sql_query(db, "CREATE TABLE t1 ( c1 integer, c2 varchar(29))", NULL, NULL)) { - Emsg0(M_ERROR_TERM, 0, _("CREATE-Stmt went wrong\n")); - } - - Dmsg0(200, "DB-Statement: INSERT INTO t1 VALUES (1, 'foo')\n"); - if (!db_sql_query(db, "INSERT INTO t1 VALUES (1, 'foo')", NULL, NULL)) { - Emsg0(M_ERROR_TERM, 0, _("INSERT-Stmt went wrong\n")); - } - - Dmsg0(200, "DB-Statement: SELECT c1,c2 FROM t1 (should be 1, foo)\n"); - if (!db_sql_query(db, "SELECT c1,c2 FROM t1", test_handler, NULL)) { - Emsg0(M_ERROR_TERM, 0, _("SELECT-Stmt went wrong\n")); - } - - Dmsg0(200, "DB-Statement: UPDATE t1 SET c2='bar' WHERE c1=1\n"); - if (!db_sql_query(db, "UPDATE t1 SET c2='bar' WHERE c1=1", NULL, NULL)) { - Emsg0(M_ERROR_TERM, 0, _("UPDATE-Stmt went wrong\n")); - } - - Dmsg0(200, "DB-Statement: SELECT * FROM t1 (should be 1, bar)\n"); - if (!db_sql_query(db, "SELECT * FROM t1", test_handler, NULL)) { - Emsg0(M_ERROR_TERM, 0, _("SELECT-Stmt went wrong\n")); - } - - Dmsg0(200, "DB-Statement: DELETE FROM t1 WHERE c2 LIKE '\%r'\n"); - if (!db_sql_query(db, "DELETE FROM t1 WHERE c2 LIKE '%r'", NULL, NULL)) { - Emsg0(M_ERROR_TERM, 0, _("DELETE-Stmt went wrong\n")); - } - - Dmsg0(200, "DB-Statement: SELECT * FROM t1 (should be 0 rows)\n"); - if (!db_sql_query(db, "SELECT * FROM t1", test_handler, NULL)) { - Emsg0(M_ERROR_TERM, 0, _("SELECT-Stmt went wrong\n")); + const char *stmt1[8] = { + "CREATE TABLE t1 ( c1 integer, c2 varchar(29))", + "INSERT INTO t1 VALUES (1, 'foo')", + "SELECT c1,c2 FROM t1", + "UPDATE t1 SET c2='bar' WHERE c1=1", + "SELECT * FROM t1", + "DELETE FROM t1 WHERE c2 LIKE '\%r'", + "SELECT * FROM t1", + "DROP TABLE t1" + }; + int (*hndl1[8])(void*,int,char**) = { + NULL, + NULL, + test_handler, + NULL, + test_handler, + NULL, + test_handler, + NULL + }; + + for (int i=0; i<8; ++i) { + Pmsg1(0, "DB-Statement: %s\n",stmt1[i]); + if (!db_sql_query(db, stmt1[i], hndl1[i], NULL)) { + Emsg0(M_ERROR_TERM, 0, _("Stmt went wrong\n")); + } } - Dmsg0(200, "DB-Statement: DROP TABLE t1\n"); - if (!db_sql_query(db, "DROP TABLE t1", NULL, NULL)) { - Emsg0(M_ERROR_TERM, 0, _("DROP-Stmt went wrong\n")); - } /* - * simple SELECT test without tables + * simple SELECT tests without tables */ - - Dmsg0(200, "DB-Statement: SELECT 'Test of simple SELECT!'\n"); - if (!db_sql_query(db, "SELECT 'Test of simple SELECT!'", string_handler, NULL)) { - Emsg0(M_ERROR_TERM, 0, _("SELECT-Stmt went wrong\n")); - } - - Dmsg0(200, "DB-Statement: SELECT 'Test of simple SELECT!' as Text\n"); - if (!db_sql_query(db, "SELECT 'Test of simple SELECT!' as Text", string_handler, NULL)) { - Emsg0(M_ERROR_TERM, 0, _("SELECT-Stmt went wrong\n")); + Pmsg0(0, "\nsimple SELECT tests without tables...\n\n"); + const char *stmt2[8] = { + "SELECT 'Test of simple SELECT!'", + "SELECT 'Test of simple SELECT!' as Text", + "SELECT VARCHAR(LENGTH('Test of simple SELECT!'))", + "SELECT DBMSINFO('_version')", + "SELECT 'This is a ''quoting'' test with single quotes'", + "SELECT 'This is a \"quoting\" test with double quotes'", + "SELECT null", + "SELECT ''" + }; + int (*hndl2[8])(void*,int,char**) = { + string_handler, + string_handler, + string_handler, + string_handler, + string_handler, + string_handler, + string_handler, + string_handler + }; + + for (int i=0; i<8; ++i) { + Pmsg1(0, "DB-Statement: %s\n",stmt2[i]); + if (!db_sql_query(db, stmt2[i], hndl2[i], NULL)) { + Emsg0(M_ERROR_TERM, 0, _("Stmt went wrong\n")); + } } - Dmsg0(200, "DB-Statement: SELECT VARCHAR(LENGTH('Test of simple SELECT!'))\n"); - if (!db_sql_query(db, "SELECT VARCHAR(LENGTH('Test of simple SELECT!'))", string_handler, NULL)) { - Emsg0(M_ERROR_TERM, 0, _("SELECT-Stmt went wrong\n")); + /* + * testing aggregates like avg, max, sum + */ + Pmsg0(0, "\ntesting aggregates...\n\n"); + const char *stmt[11] = { + "CREATE TABLE t1 (c1 integer, c2 varchar(29))", + "INSERT INTO t1 VALUES (1,'foo')", + "INSERT INTO t1 VALUES (2,'bar')", + "INSERT INTO t1 VALUES (3,'fun')", + "INSERT INTO t1 VALUES (4,'egg')", + "SELECT max(c1) from t1", + "SELECT sum(c1) from t1", + "INSERT INTO t1 VALUES (5,NULL)", + "SELECT count(*) from t1", + "SELECT count(c2) from t1", + "DROP TABLE t1" + }; + int (*hndl[11])(void*,int,char**) = { + NULL, + NULL, + NULL, + NULL, + NULL, + string_handler, + string_handler, + NULL, + string_handler, + string_handler, + NULL + }; + + for (int i=0; i<11; ++i) { + Pmsg1(0, "DB-Statement: %s\n",stmt[i]); + if (!db_sql_query(db, stmt[i], hndl[i], NULL)) { + Emsg0(M_ERROR_TERM, 0, _("Stmt went wrong\n")); + } } - Dmsg0(200, "DB-Statement: SELECT DBMSINFO('_version')\n"); - if (!db_sql_query(db, "SELECT DBMSINFO('_version')", string_handler, NULL)) { - Emsg0(M_ERROR_TERM, 0, _("SELECT-Stmt went wrong\n")); - } /* * datatypes test diff --git a/regress/prototype.conf b/regress/prototype.conf index ace6b55fba..814f2c06a7 100644 --- a/regress/prototype.conf +++ b/regress/prototype.conf @@ -108,5 +108,3 @@ WIN32_FILE="c:/users/xxxx" WIN32_PORT=9102 # Win32 Client password WIN32_PASSWORD="zzzzz" -# Where the win32 client will have to contact the SD -WIN32_STORE_ADDR="zzzz" -- 2.39.5