273 lines
8.8 KiB
C
273 lines
8.8 KiB
C
|
/*---------------------------------------------------------------------------------*/
|
|||
|
/* $RCSfile: testSelect.c,v $ */
|
|||
|
/*---------------------------------------------------------------------------------*/
|
|||
|
/* $Revision: 1.1 $ */
|
|||
|
/* $Name: $ */
|
|||
|
/* $Date: 2006/02/28 23:28:21 $ */
|
|||
|
/* $Author: agibert $ */
|
|||
|
/*---------------------------------------------------------------------------------*/
|
|||
|
|
|||
|
/*---------------------------------------------------------------------------------*/
|
|||
|
/* This file is part of LibDataBase */
|
|||
|
/* */
|
|||
|
/* LibDataBase is free software; you can redistribute it and/or modify */
|
|||
|
/* it under the terms of the GNU Lesser General Public Licence as published by */
|
|||
|
/* the Free Software Foundation; either version 2.1 of the License, or */
|
|||
|
/* (at your option) any later version. */
|
|||
|
/* */
|
|||
|
/* LibDataBase 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 Lesser General Public License for more details. */
|
|||
|
/* */
|
|||
|
/* You should have received a copy of the GNU Lesser General Public License */
|
|||
|
/* along with LibDataBase; if not, write to the Free Software */
|
|||
|
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
|
/*---------------------------------------------------------------------------------*/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#include <stdio.h>
|
|||
|
#include <libgen.h>
|
|||
|
#include <string.h>
|
|||
|
|
|||
|
#include <bdm.h>
|
|||
|
#include <database.h>
|
|||
|
|
|||
|
int main(int argc, char **argv);
|
|||
|
int parseArgs(int argc, char **argv, char **login, char **pwd, char **base, char **sql, int *tp);
|
|||
|
int sqlAnalyse(const char *sql);
|
|||
|
int execQuery(DBT_Connection *conn, const char *sql, int tp);
|
|||
|
|
|||
|
int main(int argc, char **argv) {
|
|||
|
DBT_Connection conn;
|
|||
|
DBT_Status rco;
|
|||
|
char *login = NULL;
|
|||
|
char *pwd = NULL;
|
|||
|
char *base = NULL;
|
|||
|
char *sql = NULL;
|
|||
|
int tp = 1;
|
|||
|
int rc = 1;
|
|||
|
|
|||
|
if (parseArgs(argc, argv, &login, &pwd, &base, &sql, &tp)) {
|
|||
|
BDM_Trace(0, "testSelect", "main", "Usage : %s options\n\n\
|
|||
|
Les options sont :\n\
|
|||
|
-sql ou --sql-query <requete SQL> : requ<EFBFBD>te <EFBFBD> ex<EFBFBD>cuter\n\
|
|||
|
-ps ou --packet-size <taille paquets> : nombre de lignes par fetch (1 par d<EFBFBD>faut)\n\
|
|||
|
-db ou --db-connection <user/pwd@base> : param<EFBFBD>tres de connexion <EFBFBD> Oracle\n\
|
|||
|
--debug<n> : niveau de trace", basename(argv[0]));
|
|||
|
return rc;
|
|||
|
}
|
|||
|
|
|||
|
/* connexion Oracle */
|
|||
|
DB_Library_Open(0);
|
|||
|
memset(&conn, 0, sizeof(conn));
|
|||
|
while (1) {
|
|||
|
rco = DB_Connect(&conn, login, pwd, base);
|
|||
|
if (DB_ERROR(rco)) break;
|
|||
|
while (1) {
|
|||
|
if (execQuery(&conn, sql, tp)) break;
|
|||
|
if (1) break;
|
|||
|
}
|
|||
|
DB_Disconnect(&conn);
|
|||
|
rc = 0;
|
|||
|
if (1) break;
|
|||
|
}
|
|||
|
|
|||
|
DB_Library_Close();
|
|||
|
|
|||
|
return rc;
|
|||
|
}
|
|||
|
|
|||
|
int parseArgs(int argc, char **argv, char **login, char **pwd, char **base, char **sql, int *tp) {
|
|||
|
int i = 1;
|
|||
|
|
|||
|
while (i < argc) {
|
|||
|
if (!strcmp(argv[i], "-sql") || !strcmp(argv[i], "--sql-query")) {
|
|||
|
if (++i == argc) {
|
|||
|
BDM_Trace(0, "testSelect", "parseArgs", "Param<EFBFBD>tre attendu apr<70>s %s", argv[i - 1]);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
if (*sql) BDM_Trace(1, "testSelect", "parseArgs", "Une seule requ<71>te SQL attendue : seule la derni<6E>re est prise en compte");
|
|||
|
*sql = argv[i++];
|
|||
|
} else if (!strcmp(argv[i], "-ps") || !strcmp(argv[i], "--packet-size")) {
|
|||
|
if (++i == argc) {
|
|||
|
BDM_Trace(0, "testSelect", "parseArgs", "Param<EFBFBD>tre attendu apr<70>s %s", argv[i - 1]);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
if (atoi(argv[i]) < 1) {
|
|||
|
BDM_Trace(0, "testSelect", "parseArgs", "Le nombre de lignes par fetch doit <20>tre > 0");
|
|||
|
return 1;
|
|||
|
}
|
|||
|
*tp = atoi(argv[i++]);
|
|||
|
} else if (!strcmp(argv[i], "-db") || !strcmp(argv[i], "--db-connection")) {
|
|||
|
char *start, *end;
|
|||
|
if (++i == argc) {
|
|||
|
BDM_Trace(0, "testSelect", "parseArgs", "Param<EFBFBD>tre attendu apr<70>s %s", argv[i - 1]);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
start = argv[i++];
|
|||
|
end = start;
|
|||
|
while (*end && *end != '/') ++end;
|
|||
|
if (!*end) return 1;
|
|||
|
*end = '\0';
|
|||
|
*login = start;
|
|||
|
start = ++end;
|
|||
|
while (*end && *end != '@') ++end;
|
|||
|
*pwd = start;
|
|||
|
if (*end == '@') {
|
|||
|
*end = '\0';
|
|||
|
*base = end + 1;
|
|||
|
}
|
|||
|
} else if (!strncmp(argv[i], "--debug", 7)) {
|
|||
|
int level;
|
|||
|
level = atoi(argv[i++] + 7);
|
|||
|
if (level < 0) {
|
|||
|
BDM_Trace(0, "testSelect", "parseArgs", "Le niveau de trace doit <20>tre fix<69> par --debug<n> : --debug2, --debug5, etc");
|
|||
|
return 1;
|
|||
|
}
|
|||
|
BDM_Trace_SetLevel(level, "testSelect");
|
|||
|
} else {
|
|||
|
BDM_Trace(0, "testSelect", "parseArgs", "Option %s non reconnue", argv[i]);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!*sql) {
|
|||
|
BDM_Trace(0, "testSelect", "parseArgs", "Option -sql obligatoire");
|
|||
|
return 1;
|
|||
|
}
|
|||
|
if (!*login) {
|
|||
|
BDM_Trace(0, "testSelect", "parseArgs", "Option -db obligatoire");
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
int sqlAnalyse(const char *sql) {
|
|||
|
int colCount = 0;
|
|||
|
int par = 0;
|
|||
|
const char *ptr;
|
|||
|
const char *sep = "() \t\n\r";
|
|||
|
|
|||
|
BDM_Trace(3, "testSelect", "sqlAnalyse", "Analyse de \"%s\"", sql);
|
|||
|
|
|||
|
/* ptr : d<>but de la 1<>re colonne */
|
|||
|
ptr = sql;
|
|||
|
while (*ptr && strchr(sep, *ptr) == NULL) ++ptr;
|
|||
|
|
|||
|
while (*ptr) {
|
|||
|
if (*ptr == '(') {
|
|||
|
++par;
|
|||
|
++ptr;
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (*ptr == ')') {
|
|||
|
if (!par) {
|
|||
|
BDM_Trace(0, "testSelect", "sqlAnalyse", ") rencontr<74> sans ( : %s", ptr);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
--par;
|
|||
|
++ptr;
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (*ptr == ',' && !par) {
|
|||
|
++colCount;
|
|||
|
++ptr;
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (strchr(sep, *ptr)) {
|
|||
|
char tmp[6];
|
|||
|
int i;
|
|||
|
strncpy(tmp, ptr + 1, 5);
|
|||
|
tmp[5] = '\0';
|
|||
|
for (i = 0; i < 5; ++i)
|
|||
|
if (tmp[i] >= 'A' && tmp[i] <= 'Z') tmp[i] += 'a' - 'A';
|
|||
|
if (!strcmp(tmp, "from ")) {
|
|||
|
++colCount;
|
|||
|
break;
|
|||
|
}
|
|||
|
++ptr;
|
|||
|
continue;
|
|||
|
}
|
|||
|
++ptr;
|
|||
|
}
|
|||
|
|
|||
|
if (!*ptr) {
|
|||
|
BDM_Trace(0, "testSelect", "sqlAnalyse", "FROM non trouv<75> dans la requ<71>te");
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
if (!colCount) {
|
|||
|
BDM_Trace(0, "testSelect", "sqlAnalyse", "Aucune colonne n'a <20>t<EFBFBD> identifi<66>e");
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
BDM_Trace(2, "testSelect", "sqlAnalyse", "La requ<71>te devrait retourner %d colonnes", colCount);
|
|||
|
|
|||
|
return colCount;
|
|||
|
}
|
|||
|
|
|||
|
int execQuery(DBT_Connection *conn, const char *sql, int tp) {
|
|||
|
int colCount = sqlAnalyse(sql);
|
|||
|
int idx;
|
|||
|
DBT_HostVar *hv = NULL;
|
|||
|
char *data = NULL;
|
|||
|
const int max = 100 + 1;
|
|||
|
DBT_Indicator *inull = NULL;
|
|||
|
DBT_Status rc = DBS_OK;
|
|||
|
DBT_Statement st;
|
|||
|
DBT_Result res;
|
|||
|
|
|||
|
/* nombre de colonnes */
|
|||
|
if (colCount == 0) return 1;
|
|||
|
|
|||
|
while (1) {
|
|||
|
BDM_Trace(3, "testSelect", "execQuery", "Pr<EFBFBD>paration des variables pour %d colonnes x %d lignes", colCount, tp);
|
|||
|
/* HostVar */
|
|||
|
hv = (DBT_HostVar *)malloc(sizeof(DBT_HostVar) * colCount);
|
|||
|
memset(hv, 0, sizeof(DBT_HostVar) * colCount);
|
|||
|
/* data */
|
|||
|
data = (char *)malloc((size_t)tp * max * colCount);
|
|||
|
/* inull */
|
|||
|
inull = (DBT_Indicator *)malloc(sizeof(DBT_Indicator) * colCount * tp);
|
|||
|
for (idx = 0; !DB_ERROR(rc) && idx < colCount; ++idx)
|
|||
|
rc = DB_HostVar_Setup(&hv[idx], DBD_STRING, max, data + tp * max * idx, &inull[tp * idx]);
|
|||
|
if (DB_ERROR(rc)) break;
|
|||
|
rc = DB_Statement_Init(conn, &st);
|
|||
|
if (DB_ERROR(rc)) break;
|
|||
|
rc = DB_Statement_Prepare(&st, sql);
|
|||
|
if (DB_ERROR(rc)) break;
|
|||
|
for (idx = 0; !DB_ERROR(rc) && idx < colCount; ++idx)
|
|||
|
rc = DB_Statement_DefineVar(&st, tp, idx + 1, &hv[idx]);
|
|||
|
if (DB_ERROR(rc)) break;
|
|||
|
BDM_Trace(3, "testSelect", "execQuery", "Variables initialis<69>es");
|
|||
|
|
|||
|
rc = DB_Statement_ExecuteSelect(&st, &res);
|
|||
|
while (rc == DBS_OK) {
|
|||
|
int nl;
|
|||
|
BDM_Trace(3, "testSelect", "execQuery", "Lecture de %d enregistrements", res.rowsProcessed);
|
|||
|
for (nl = 0; nl < res.rowsProcessed; ++nl) {
|
|||
|
for (idx = 0; idx < colCount; ++idx)
|
|||
|
printf("%s%s", idx ? ";" : "", inull[idx * tp + nl] ? "" : data + max * (idx * tp + nl));
|
|||
|
printf("\n");
|
|||
|
}
|
|||
|
if (st.isEOF) break;
|
|||
|
rc = DB_Statement_Fetch(&st, &res);
|
|||
|
}
|
|||
|
DB_Statement_Close(&st);
|
|||
|
if (1) break;
|
|||
|
}
|
|||
|
|
|||
|
free(inull);
|
|||
|
free(data);
|
|||
|
free(hv);
|
|||
|
|
|||
|
if (DB_ERROR(rc)) return 1;
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|