SQLitewrapped & BCB6



  • Hallo,

    ich habe folgendes Problem.
    Ich habe mir eine neues Projekt erstellt und die Dateien des sqlitewrapped-1.3 hinzugefügt und in das Projekt eingebunden. Nun habe ich das Problem das ich einen seltsamen und mir unbegreiflichen Fehler beim Kompilieren bekomme

    [C++ Warnung] Database.cpp(227): W8004 'd' wurde ein Wert zugewiesen, der nie verwendet wird
      [C++ Warnung] Query.cpp(463): W8004 'found' wurde ein Wert zugewiesen, der nie verwendet wird
      [C++ Fehler] SysLog.cpp(16): E2090 Qualifizierer 'SysLog' ist kein Name einer Klasse oder einer Struktur
      [C++ Fehler] SysLog.cpp(16): E2040 Deklaration nicht ordnungsgemäß abgeschlossen
    

    Die entsprechenden SysLog.cpp und SysLog.h sehen wie folgt aus:

    #ifndef WIN32
    
    #include <sqlite3.h>
    
    #include "Database.h"
    #include "Query.h"
    #include "IError.h"
    #include "SysLog.h"
    
    #ifdef SQLITEW_NAMESPACE
    namespace SQLITEW_NAMESPACE {
    #endif
    
    SysLog::SysLog(const std::string& appname,int option,int facility)
    {
    static	char blah[100];
    	strcpy(blah, appname.c_str());
    	openlog(blah, option, facility);
    }
    
    SysLog::~SysLog()
    {
    	closelog();
    }
    
    void SysLog::error(Database& db,const std::string& str)
    {
    	syslog(LOG_ERR, "%s", str.c_str() );
    }
    
    void SysLog::error(Database& db,Query& q,const std::string& str)
    {
    	syslog(LOG_ERR, "%s: %s(%d)", str.c_str(),q.GetError().c_str(),q.GetErrno() );
    	syslog(LOG_ERR, "QUERY: \"%s\"", q.GetLastQuery().c_str());
    }
    
    #ifdef SQLITEW_NAMESPACE
    } // namespace SQLITEW_NAMESPACE {
    #endif
    
    #endif // WIN32
    
    #ifndef _SYSLOG_H_SQLITE
    #define _SYSLOG_H_SQLITE
    #ifndef WIN32
    
    #include "syslog.h"
    
    #ifdef SQLITEW_NAMESPACE
    namespace SQLITEW_NAMESPACE {
    #endif
    
    /** Log class writing to syslog. */
    class SysLog : public IError
    {
    public:
    	SysLog(const std::string& = "database", int = LOG_PID, int = LOG_USER);
    	virtual ~SysLog();
    
    	void error(Database&,const std::string&);
    	void error(Database&,Query&,const std::string&);
    
    };
    
    #ifdef SQLITEW_NAMESPACE
    } // namespace SQLITEW_NAMESPACE {
    #endif
    
    #endif // WIN32
    #endif // _SYSLOG_H
    

    Wo bitte liegt denn da der Fehler? Ich hab echt keine Ahnung was ich noch machen bzw. suchen soll?

    Gruß Merlot



  • das

    #include "syslog.h"
    

    aus deinem headerfile gehoert in dein *.cpp file. oder warum sollte dich die syslog.h selbst inkludieren ?
    woher kommt 'Database'?
    im headerfile alle anderen headerfiles die du brauchst inkludieren.
    headerfiles die du nur in der cpp brauchst, bleiben dort.

    Meep Meep



  • Meep Meep schrieb:

    das

    #include "syslog.h"
    

    aus deinem headerfile gehoert in dein *.cpp file. oder warum sollte dich die syslog.h selbst inkludieren ?

    Ja ehrlich gesagt verstehe ich das auch nicht. Die Original-H-Datei sieht aber exakt gleich aus, also von mir kommt dieses #include nicht. Auch wenn ich das syslog.h aus der h-Datei lösche bekomm ich die selben Fehler.

    Die Database.h ist ebenfalls ein Teil des Wrappers.



  • Weiß keiner mehr nen Rat?
    Ich könnte auch das komplette wenn auch noch total leere Projekt zur Verfügung stellen damit ein Interessierter es sich mal genauer anschaut.

    Kleiner Nachtrag, ich habe meine sqlite3.h nach diesem Beitrag -> hier <- von VergissEs verändert.

    Wenn ich die Änderung nicht durchführe bekomme ich folgende Fehler:

    [C++ Fehler] sqlite3.h(2475): E2232 Konstante-Element 'sqlite3_index_info::nConstraint' in Klasse ohne Konstruktoren
      [C++ Fehler] sqlite3.h(2475): E2232 Konstante-Element 'sqlite3_index_info::aConstraint' in Klasse ohne Konstruktoren
      [C++ Fehler] sqlite3.h(2475): E2232 Konstante-Element 'sqlite3_index_info::nOrderBy' in Klasse ohne Konstruktoren
      [C++ Fehler] sqlite3.h(2475): E2232 Konstante-Element 'sqlite3_index_info::aOrderBy' in Klasse ohne Konstruktoren
      [C++ Fehler] sqlite3.h(2475): E2232 Konstante-Element 'sqlite3_index_info::aConstraintUsage' in Klasse ohne Konstruktoren
    


  • merlot schrieb:

    Kleiner Nachtrag, ich habe meine sqlite3.h nach diesem Beitrag -> hier <- von VergissEs verändert.

    Wenn ich die Änderung nicht durchführe bekomme ich folgende Fehler:

    [C++ Fehler] sqlite3.h(2475): E2232 Konstante-Element 'sqlite3_index_info::nConstraint' in Klasse ohne Konstruktoren
      [C++ Fehler] sqlite3.h(2475): E2232 Konstante-Element 'sqlite3_index_info::aConstraint' in Klasse ohne Konstruktoren
      [C++ Fehler] sqlite3.h(2475): E2232 Konstante-Element 'sqlite3_index_info::nOrderBy' in Klasse ohne Konstruktoren
      [C++ Fehler] sqlite3.h(2475): E2232 Konstante-Element 'sqlite3_index_info::aOrderBy' in Klasse ohne Konstruktoren
      [C++ Fehler] sqlite3.h(2475): E2232 Konstante-Element 'sqlite3_index_info::aConstraintUsage' in Klasse ohne Konstruktoren
    

    hehe einen Sinn sollte die Änderung ja auch haben 🙂

    So hier mal mein SQLite Wrapper:

    sqlite_db.h

    #ifndef SQLITE_DBH
    #define SQLITE_DBH
    //---------------------------------------------------------------------------
    #include <string>
    #include <map>
    #include <vector>
    #include "sqlite.h"
    //---------------------------------------------------------------------------
    typedef std::map<std::string,std::string> sqlite_fields;
    typedef std::vector<sqlite_fields> sqlite_result;
    //---------------------------------------------------------------------------
    class sqlite_db
    {
    	private:
    		sqlite3* db_;
    		static int sqlite_callback(void *param,int colcount,char **cols,char **colnames);
    		void SaveLog(std::string msg);
    
       public:
    		sqlite_db():db_(NULL){}
    		virtual ~sqlite_db(){if(db_)close();}
    		const char *version()const{return SQLITE_VERSION;}
    		void open(const std::string& db);
    		void close();
    		sqlite_result exec_sql(const std::string& query);
    		void exec_dml(const std::string& query);
    };
    //---------------------------------------------------------------------------
    #endif
    

    sqlite_db.cpp

    #include "sqlite_db.h"
    #include "SysUtils.hpp"
    //---------------------------------------------------------------------------
    void sqlite_db::open(const std::string& db)
    {
    	if (db!=":memory:") {
    		if (Sysutils::FileExists(db.c_str())) {
    			if (FileIsReadOnly(db.c_str())) {
    				//SaveLog("Filename "+WideString(db.c_str())+" is readonly!");
    			}
    		}
    	}
    
    	try {
    		if(db_)close();
    
    		char *errmsg = NULL;
    
    		int rc = sqlite3_open(db.c_str(), &db_);
    		if (rc) {
    			errmsg = (char*)sqlite3_errmsg(db_);
    			std::string error = "Can't open database: " + (std::string)errmsg;
    			//SaveLog(db.c_str());
    		}
    	} catch (...) {
    		SaveLog(db.c_str());
    	}
    }
    //---------------------------------------------------------------------------
    void sqlite_db::close()
    {
    	if(db_)sqlite3_close(db_);
    	db_ = NULL;
    }
    //---------------------------------------------------------------------------
    sqlite_result sqlite_db::exec_sql(const std::string& query)
    {
    	sqlite_result result;
    	if (!db_) return result;
    
    	try {
    		char* errmsg = NULL;
    		int res = sqlite3_exec(db_,query.c_str(),sqlite_callback,(void*)&result,&errmsg);
    		if(res != SQLITE_OK) {
    			//SaveLog(query.c_str());
    		}
    		return result;
    	}
    	catch(...) {
    		//SaveLog(query.c_str());
    		Beep();
    	}
    	return result;
    }
    //---------------------------------------------------------------------------
    void sqlite_db::exec_dml(const std::string& query)
    {
    	if(!db_) return;
    
    	try {
    		char* errmsg = NULL;
    		int res = sqlite3_exec(db_,query.c_str(),sqlite_callback,(void*)NULL,&errmsg);
    		if(res != SQLITE_OK) {
    			errmsg = (char*)sqlite3_errmsg(db_);
    			std::string error(errmsg);
    			//SaveLog(query.c_str()+(WideString)error.c_str());
    		}
    	} catch (...) {}
    
    }
    //---------------------------------------------------------------------------
    int sqlite_db::sqlite_callback(void *param,int colcount,char **cols,char **colnames)
    {
    	try {
    		sqlite_result* result = reinterpret_cast<sqlite_result*>(param);
    		sqlite_fields f;
    		for(int i = 0;i < colcount;++i) {
    			f[colnames[i]] = cols[i];
    		}
    		result->push_back(f);
    	} catch (...) {}
    	return 0;
    }
    //---------------------------------------------------------------------------
    

    Die Funktion SaveLog hab ich mal ausdokumentiert evtl. ggf. mit was eigenes ersetzten.

    So nun zur Benutzung:

    sqlite_db *db = new sqlite_db();
    std::string query = "SELECT * FROM Table;";
    sqlite_result result = db->exec_sql(query);
    
    //SELECT Anweisungen
    for(sqlite_result::size_type i = 0; i < result.size(); ++i) {
    
        sqlite_fields row = result[i];
        AnsiString FeldName = row["Feldname"].c_str();
    }
    
    //Einmalige SQL Befehle
    db->exec_dml("CREATE TABLE tabelle(id INTEGER PRIMARY KEY, field TEXT);");
    
    db->close();
    delete db;
    


  • Danke für den Wrapper!! Was bedeutet DML in exec_dml eigentlich?

    In deinem Wrapper fehlt eine Funktion, die ich hier mal nachhole.
    Wobei zu beachten wäre das dies VCL ist und unter anderen C++ Entwicklungen wohl nicht einsetzbar.

    bool sqlite_db::FileIsReadOnly(std::string FileName)
    {
        int Attrs = FileGetAttr(FileName.c_str());
        if (Attrs & faReadOnly)
        {
            return true;
        }
        return false;
    }
    


  • Weiss wer was das

    if (db!=":memory:")
    

    in

    sqlite_db::open(const std::string& db)
    

    bedeuten soll?



  • :memory:
    

    Erzeugt eine temporäre Datenbank im Arbeitsspeicher. Alle Einträge gehen nach beenden der Software verloren.

    Willst du die Einträge behalten (was ja logisch erscheint), dann musst du den Namen deiner DB angeben.

    if (db!="beispiel.db")
    anstatt
    if (db!=":memory:")
    

    Ist die DB nicht vorhanden wird sie automatisch leer angelegt. Heißt ohne Tabellen und Einträge.



  • Ah. Man kann also über :memory: eine Datenbank aufbauen, die man nur temporär während der Arbeitszeit benötigt. Das ja Klasse. Danke für die Aufklärung.



  • ~SQLite schrieb:

    Danke für den Wrapper!! Was bedeutet DML in exec_dml eigentlich?

    Er meint data manipulation language, der SQL-Sprachteil, der sich mit der Änderung des DB-Kataloges beschäftigt (ALTER TABLE, CREATE TABLE, ...), also der Teil, der keine Ergebnisrelation wie bei SELECT zurückliefert.



  • Danke für die Aufklärung.



  • Verdammt,

    DML - data manipulation language
    + Daten werden geändert (INSERT, UPDATE, DELETE)

    DDL - data definition language
    + Katalog wird geändert (CREATE TABLE, ALTER TABLE, ...)

    Wahrscheinlich ist mit dieser Extra-Funktion gemeint, dass diese aufgerufen werden soll, wenn das Statement keine Ergebnisrelation zurückliefert und somit vielleicht preiswerter implementiert werden kann.



  • Ein Mittelweg scheint es nicht zu geben, oder?
    Wenn ich ein INSERT durchführe, dann wird dieses sofort in die Datei geschrieben.

    Ich vermisse die Option mit :memory: zu öffnen und als Datei zu speichern.

    Wichtiger gar als Datei zu öffnen und es wird rein im Speicher mit ihr gearbeitet und erst mittels close() oder einer save() Funktion in die Datei zurückgeschrieben.

    Ich vermisse dies, weil ich hier mit einem SpinButton Werte ändere und rechne und man sehr deutchlich die Festplatte rödeln hört bei jeder Aktion.



  • Warum musst du bei jeder Änderung von Spin Button speichern ?
    Das ist eine recht merkwürdige Art. Rechnen tust du nicht in der Datenbank.



  • Na dann erstell doch eine Memory Datenbank und speichere die dann beim Beenden in eine SQLLite File Datenbank

    ATTACH DATABASE



  • Danke für den Hinweis.

    sql-statement ::= 	ATTACH [DATABASE] database-filename AS database-name
    

    Für eine bestehende Datenbank muss ich wohl Variablen schaffen, die die Daten aufnehmen zum bearbeiten und erst am Ende es Programmes dann zurück in DB speichern. Sonst würde der Dateizugriff wohl zu massiv, da bestehende Datenbank (meines wissens) nicht als :memory: geht.



  • Ich habe den Wrapper mal übernommen und da er noch so wenig drin hat auch gern etwas erweitern.

    Mir persönlich fehlt zum Beispiel noch int mysql_num_rows($result) (PHP)
    Mein Versuch scheiterte allerdings kläglich.

    query = "SELECT COUNT(*) FROM IMDG WHERE col=5";
    sqlite_result result = db->exec_sql(query);
    printf("count:%d",result.size());
    

    Er gibt immer 1 aus, obwohl da sehr viele Datensätze drin sind und die Bedingung erfüllen. Was mach ich falsch? 🙂



  • Er hat doch recht: Das Ergebnis dieser Anfrage besteht aus einer Zeile und einer Spalte, darin steht eben die Anzahl, die Du mit COUNT(*) angefragt hast. Wahrscheinlich wird db->exec_sql(query) die Anzahl veränderter Zeilen bei einem DML-Statement zurückgeben. Du musst den Inhalt des ersten Feldes der ersten Zeile des Ergebnisses auslesen, wenn Du die Anzahl passender Zeilen haben willst.



  • BTW, warum willst Du eine solche Funktion überhaupt schreiben? Reicht nicht result.size()?



  • Danke, habs hinbekommen. Führe gleich mal Fragespiel fort. 😉

    Ich UPDATE und DELETE Einträge und aus MySQL weiss ich das ein "LIMIT 1" angehängt das ganze wesentlich beschleunigt. In SQLite jedoch meckert er Syntaxfehler wenn ein LIMIT vorhanden ist. Warum? In SELECT kann man es offensichtlich benutzen.

    Beispiel: sqlite3_exec("DELETE FROM datenbank WHERE feld=7 LIMIT 1")


Anmelden zum Antworten