====== db_exec_sql ======
Modul mit einigen (Informix-)DB-Funktionen
**db_exec_sql.h**:
/*********************************************************************
*
* Autor: Jürgen Kreick
* Version: 1.0.0 vom 24.11.2010
*
**********************************************************************
*
* Hinweise zum Modul/Quelltext:
*
* In der aktuellen Version werden nur Verbindungen zu einer einzigen
* DB pro Sitzung unterstützt.
* Unterstützung von parallelen Sitzungen (zeitgleiche mehrere DB-Verbindungen zu
* jeweils unterschiedlichen DB) sind momentan nicht geplant.
*
**********************************************************************
*
* Release Notes:
*
* Ver 1.0.0 (vom 24.11.2010):
* Die erste Version des Moduls. Umfasst (nach aussen) folgende Funktionen:
* dbInit(), dbDone(), dbSetIsolation(), dbSetModeWait().
*
**********************************************************************/
#ifndef db_exec_sql_h_H
#define db_exec_sql_h_H
// Rückgabewerte:
#define RC_DB_OK 0
#define RC_DB_ERR -1
#define RC_DB_NOTFOUND 100
// IsolationsLevel
#define DIRTY_READ 1
// "Dirty Read" und "Uncommitted Read" ist das gleiche
#define UNCOMMITTED_READ 1
#define COMMITTED_READ 2
// Die Liste ist nicht vollständig!
// Werte für dbEndTransaction()
#define TRANSACTION_COMMIT 1
#define TRANSACTION_ROLLBACK 2
// Transaktionskontext: ON = erforderlich, OFF = nicht erforderlich
#define TRANSACTION_OFF 0
#define TRANSACTION_ON 1
// Transaktion: IN_OF_TRNS = man befindet sich innerhalb eines Transaktionskontextes, OUT_OF_TRNS = außerhalb
#define TRANSACTION_IN_OF_TRNS 1
#define TRANSACTION_OUT_OF_TRNS 0
// Log-Meldungen
#define LOG_FEHLGESCHLAGEN "fehlgeschlagen."
#define LOG_BEGIN_WORK "BEGIN WORK"
#define LOG_BEGIN_WORK_FEHLGESCHLAGEN "BEGIN WORK fehlgeschlagen."
#define LOG_COMMIT_WORK "COMMIT WORK"
#define LOG_COMMIT_WORK_FEHLGESCHLAGEN "COMMIT WORK fehlgeschlagen."
#define LOG_ROLLBACK_WORK "ROLLBACK WORK"
#define LOG_ROLLBACK_WORK_FEHLGESCHLAGEN "ROLLBACK WORK fehlgeschlagen."
#define LOG_TRANSACTION_PARAM_ERROR "Falsche Parameter beim Aufruf von dbEndTransaction()"
// ******************** Prototypen ****************************************
// dbInit() wird ein Mal pro DB-Sitzung aufgerufen und baut eine Verbindung zur
// DB auf.
//
// Parameter:
//
// char *dbName : Name der DB (z.B. "test_db@test_system")
// int extLogFileID : externe LogFileID für das Logging-System
//
// Rückgabewert: RC_DB_OK (Erfolg) oder RC_DB_ERR (bei Fehlern)
int dbInit (const char *dbName, int extLogFileID);
// dbDone() wird ein Mal pro DB-Sitzung aufgerufen und baut die existierende
// Verbindung zur DB ab.
//
// Parameter: keine.
//
// Rückgabewert: RC_DB_OK (Erfolg) oder RC_DB_ERR (bei Fehlern)
int dbDone ();
// dbSetIsolation() setzt den aktuellen IsolationsLevel für die Verbindung
int dbSetIsolation (int level);
// dbSetModeWait() setzt die Wartezeit in Sekunden beim Warten auf einen gelockten Satz.
// Negative Werte für "sec" bedeuten kein Warten.
// sec = 0 bedeutet keine Begrenzung beim Warten.
int dbSetModeWait (int sec);
// Diese Funktion führt einfache SQLs aus.
// Eingabeparameter:
// sql - SQL-String, der ausgeführt werden soll;
// text - Text (z.B. updated / deleted / inserted) für Massenoperationen
// funktionname - "__func__"-Makro der aufrufenden Funktion (für Trace)
// Ausgabeparameter:
// rows - Falls NULL, wird ignoriert, sonst wird dort bei Erfolg die Zahl durch SQL betroffener Sätze zurück gegeben
int execSimpleSQL (const char *sql, const int *rows, const char *text, const char *modulName, int lineNumber, const char *functName);
// Transaktionkontext öffnen (BEGIN WORK;)
int dbBeginTransaction ();
// Transaktion beenden (mit COMMIT WORK; oder ROLLBACK WORK;)
int dbEndTransaction (int transactionEnd);
/* Everything else goes here */
#endif
**db_exec_sql.ec**:
#include "db_exec_sql.h"
// Wehen Logging:
#include "logging_ext.h"
// Konstanten:
#define TMP_STR_LEN_MAX 8191
#define ON 1
#define OFF 0
// ******************** lokale Strukturen ****************************************
// ******************** externe Variablen ****************************************
int dbLogFileID = 0;
// ******************** lokale Variablen ****************************************
int dbConnected = 0; // 0 - keine Verbindung, 1 - Verbindung existiert (oder OFF/ON)
// ******************** interne Funktionen ****************************************
// ******************** export-Funktionen ****************************************
int dbInit (const char *dbName, int extLogFileID)
{
int rc = RC_OK;
int rc_SQL = RC_DB_OK;
char logStr [TMP_STR_LEN_MAX + 1];
EXEC SQL BEGIN DECLARE SECTION;
char dbDatabase [TMP_STR_LEN_MAX + 1];
EXEC SQL END DECLARE SECTION;
dbLogFileID = extLogFileID; // Da es von außen gesetzt wird, übernehmen wir es blind (sicherheitstechnisch unkritisch).
memset(logStr, '\0', sizeof(logStr));
memset(dbDatabase, '\0', sizeof(dbDatabase));
logEntry(LOG_INFO, dbLogFileID, __FILE__, __func__);
// Plausibilitätsprüfung:
if (dbName) // dbName existiert?
{
strlcpy(dbDatabase, dbName, sizeof(dbDatabase)); // Vor dem trim'men umkopieren
trimAll(dbDatabase, NULL, sizeof(dbDatabase)); // Von den Leerzeichen links und rechts befreien
if (strlen(dbDatabase) <= 0) // Der DB-Name darf nicht leer sein
{
logLog(LOG_ERR, dbLogFileID, __FILE__, __LINE__, __func__, "Fehlerhafter Aufruf: Name der DB ist leer.");
rc = RC_ERR;
} // if
}
else // dbName darf nicht NULL sein
{
logLog(LOG_ERR, dbLogFileID, __FILE__, __LINE__, __func__, "Fehlerhafter Aufruf: Parameter 'dbName' ist NULL.");
rc = RC_ERR;
} // if
if (!rc)
{
logLog(LOG_NOTICE, dbLogFileID, __FILE__, __LINE__, __func__, "Es wird versucht eine Verbindung zur DB aufzubauen...");
if (dbConnected) // Verbindung ist bereits vorhanden
{
logLog(LOG_ERR, dbLogFileID, __FILE__, __LINE__, __func__, "Eine Verbindung zur DB existiert bereits.");
rc = RC_ERR;
} // if
} // if
if (!rc)
{
snprintf(logStr, sizeof(logStr), "Database = [%s]", dbDatabase);
logLog(LOG_NOTICE, dbLogFileID, __FILE__, __LINE__, __func__, logStr);
EXEC SQL DATABASE :dbDatabase ;
if (rc_SQL = sqlca.sqlcode) rc = RC_ERR;
} // if
if (!rc) logLog(LOG_NOTICE, dbLogFileID, __FILE__, __LINE__, __func__, "Verbindung zur DB erfolgreich aufgebaut.");
else logLog(LOG_ERR, dbLogFileID, __FILE__, __LINE__, __func__, "Verbindung zur DB konnte nicht aufgebaut werden.");
if (!rc) dbConnected = ON;
logExitRC(LOG_INFO, dbLogFileID, __FILE__, __func__, rc);
return rc;
} // dbInit()
int dbDone ()
{
int rc = RC_OK;
logEntry(LOG_INFO, dbLogFileID, __FILE__, __func__);
if (dbConnected) // Verbindung existiert
{
// TODO: z.B. Cursor frei geben
} // if
if (dbConnected) dbConnected = OFF;
else rc = RC_ERR; // Es gibt keine Verbindung, die abgebaut werden soll.
logExitRC(LOG_INFO, dbLogFileID, __FILE__, __func__, rc);
return rc;
} // dbDone()
int dbSetIsolation (int level)
{
int rc = RC_OK;
int rc_SQL = RC_DB_OK;
logEntry(LOG_INFO, dbLogFileID, __FILE__, __func__);
switch (level)
{
case DIRTY_READ:
logLog(LOG_NOTICE, dbLogFileID, __FILE__, __LINE__, __func__, "SET ISOLATION TO DIRTY READ;");
EXEC SQL SET ISOLATION TO DIRTY READ;
if (rc_SQL = sqlca.sqlcode) rc = RC_ERR;
break; // case DIRTY_READ
case COMMITTED_READ:
logLog(LOG_NOTICE, dbLogFileID, __FILE__, __LINE__, __func__, "SET ISOLATION TO COMMITTED READ;");
EXEC SQL SET ISOLATION TO COMMITTED READ;
if (rc_SQL = sqlca.sqlcode) rc = RC_ERR;
break; // case COMMITTED_READ
default: rc = RC_ERR;
} // switch (level)
if (rc) logLog(LOG_ERR, dbLogFileID, __FILE__, __LINE__, __func__, "IsolationsLevel konnte nicht gesetzt werden.");
logExitRC(LOG_INFO, dbLogFileID, __FILE__, __func__, rc);
return rc;
} // int dbSetIsolation()
int dbSetModeWait (int sec)
{
int rc = RC_OK;
int rc_SQL = RC_DB_OK;
EXEC SQL BEGIN DECLARE SECTION;
char tmpStrSQL [TMP_STR_LEN_MAX + 1];
EXEC SQL END DECLARE SECTION;
logEntry(LOG_INFO, dbLogFileID, __FILE__, __func__);
memset(tmpStrSQL, '\0', sizeof(tmpStrSQL));
if (sec < 0) // Kein Warten.
{
logLog(LOG_NOTICE, dbLogFileID, __FILE__, __LINE__, __func__, "SET LOCK MODE TO NOT WAIT;");
EXEC SQL SET LOCK MODE TO NOT WAIT;
if (rc_SQL = sqlca.sqlcode) rc = RC_ERR;
}
else if (sec == 0) // Keine Begrenzung beim Warten.
{
logLog(LOG_NOTICE, dbLogFileID, __FILE__, __LINE__, __func__, "SET LOCK MODE TO WAIT;");
EXEC SQL SET LOCK MODE TO WAIT;
if (rc_SQL = sqlca.sqlcode) rc = RC_ERR;
}
else // "sec" Sekunden Warten.
{
snprintf(tmpStrSQL, sizeof(tmpStrSQL), "SET LOCK MODE TO WAIT %i;", sec);
logLog(LOG_NOTICE, dbLogFileID, __FILE__, __LINE__, __func__, tmpStrSQL);
EXEC SQL EXECUTE IMMEDIATE :tmpStrSQL;
if (rc_SQL = sqlca.sqlcode) rc = RC_ERR;
} // if
if (rc) logLog(LOG_ERR, dbLogFileID, __FILE__, __LINE__, __func__, "WaitMode konnte nicht gesetzt werden.");
logExitRC(LOG_INFO, dbLogFileID, __FILE__, __func__, rc);
return rc;
} // int dbSetModeWait()
int execSimpleSQL (const char *sql, const int *rows, const char *text, const char *modulName, int lineNumber, const char *functName) // Führt einfache SQLs aus
{
int rc_SQL = RC_DB_OK;
int countRows = 0;
char tmpStr [TMP_STR_LEN_MAX + 1];
EXEC SQL BEGIN DECLARE SECTION;
char tmpStrSQL [TMP_STR_LEN_MAX + 1];
EXEC SQL END DECLARE SECTION;
countRows = 0;
memset(tmpStr, '\0', sizeof(tmpStr));
memset(tmpStrSQL, '\0', sizeof(tmpStrSQL));
logEntry(LOG_INFO, dbLogFileID, __FILE__, __func__);
logLog(LOG_DEBUG, dbLogFileID, __FILE__, __LINE__, __func__, sql);
strlcpy(tmpStrSQL, sql, sizeof(tmpStrSQL));
logLog(LOG_INFO, dbLogFileID, __FILE__, __LINE__, __func__, tmpStrSQL);
EXEC SQL EXECUTE IMMEDIATE :tmpStrSQL;
if (rc_SQL = sqlca.sqlcode)
{
logLogRC_SQL(LOG_ERR, dbLogFileID, __FILE__, __LINE__, __func__, LOG_FEHLGESCHLAGEN, tmpStrSQL, rc_SQL);
snprintf(tmpStr, sizeof(tmpStr), "Aufgerufen aus %s[%d]:%s()", modulName, lineNumber, functName);
logLog(LOG_ERR, dbLogFileID, __FILE__, __LINE__, __func__, tmpStr);
}
else
{
countRows = sqlca.sqlerrd[2]; // Anzahl betroffener Saetze uebernehmen
if (text) // Falls nicht NULL
{
snprintf(tmpStr, sizeof(tmpStr), "%d rows %s.", countRows, text);
logLog(LOG_INFO, dbLogFileID, __FILE__, __LINE__, __func__, tmpStr);
} // if
if (rows) // Falls nicht NULL
{
// Anzahl betroffener Saetze zurueck geben
*rows = countRows; // Achtung! Es wird nicht ueberprueft, ob "*rows" ausreichend Platz hat!
} // if
} // if
logExitRC(LOG_INFO, dbLogFileID, __FILE__, __func__, rc_SQL);
return rc_SQL;
} // execSimpleSQL()
int dbBeginTransaction () // Transaktionkontext öffnen
{
int rc_SQL = RC_DB_OK;
logEntry(LOG_INFO, dbLogFileID, __FILE__, __func__);
logLog(LOG_INFO, dbLogFileID, __FILE__, __LINE__, __func__, LOG_BEGIN_WORK);
EXEC SQL BEGIN WORK;
if (rc_SQL = sqlca.sqlcode) logLog(LOG_ERR, dbLogFileID, __FILE__, __LINE__, __func__, LOG_BEGIN_WORK_FEHLGESCHLAGEN);
logExitRC(LOG_INFO, dbLogFileID, __FILE__, __func__, rc_SQL);
return rc_SQL;
} // dbBeginTransaction()
int dbEndTransaction (int transactionEnd) // Transaktion beenden (mit COMMIT WORK; oder ROLLBACK WORK;)
{
int rc_SQL = RC_DB_OK;
logEntry(LOG_INFO, dbLogFileID, __FILE__, __func__);
switch (transactionEnd) // Entweder COMMIT WORK; oder ROLLBACK WORK;
{
case TRANSACTION_COMMIT: // COMMIT WORK;
logLog(LOG_INFO, dbLogFileID, __FILE__, __LINE__, __func__, LOG_COMMIT_WORK);
EXEC SQL COMMIT WORK;
if (rc_SQL = sqlca.sqlcode) logLog(LOG_ERR, dbLogFileID, __FILE__, __LINE__, __func__, LOG_COMMIT_WORK_FEHLGESCHLAGEN);
break; // case TRANSACTION_COMMIT:
case TRANSACTION_ROLLBACK: // ROLLBACK WORK;
logLog(LOG_INFO, dbLogFileID, __FILE__, __LINE__, __func__, LOG_ROLLBACK_WORK);
EXEC SQL ROLLBACK WORK;
if (rc_SQL = sqlca.sqlcode) logLog(LOG_ERR, dbLogFileID, __FILE__, __LINE__, __func__, LOG_ROLLBACK_WORK_FEHLGESCHLAGEN);
break; // case TRANSACTION_ROLLBACK:
default: // Unzulässiger Parameterwert
logLog(LOG_ERR, dbLogFileID, __FILE__, __LINE__, __func__, LOG_TRANSACTION_PARAM_ERROR);
rc_SQL = RC_DB_ERR;
} // switch (transactionEnd)
logExitRC(LOG_INFO, dbLogFileID, __FILE__, __func__, rc_SQL);
return rc_SQL;
} // dbEndTransaction()
// EOF
----
Stand: 24.11.2010\\
--- //[[feedback.jk-wiki@kreick.de|: Jürgen Kreick]]//
EOF