Sqlite3 Database is locked bei Drop Table

Alles rund um die Programmierung mit Qt
Antworten
GrooveXT
Beiträge: 26
Registriert: 18. September 2008 17:10

Sqlite3 Database is locked bei Drop Table

Beitrag von GrooveXT »

Hallo,
ich bräuchte dringends Hilfe. Ich habe hier eine Sqlite3 Datenbank mit QT aufgesetzt. Läuft soweit auch einwandfrei, bis zu dem Punkt wo ich alle Tabellen aus der Datenbank löschen möchte. Jedesmal kommt der Fehler "Database is locked"...Ich habe die Befehle ca. 100 mal überprüft und SQLite Admin ausprobiert (1:1 aus der Debug-Variable rauskopiert). Funktionieren einwandfrei! Aber irgendwie ist die Datenbank immer gelocked. Weiß nicht mehr was ich noch machen soll. Es geschehen auch defintiv keine anderen Zugriffe auf die DB während ich versuche sie zu löschen. Selects, Inserts und Updates funktionieren einwandfrei an dieser Stelle...nur eben nicht DROP TABLE.

Code: Alles auswählen

bool MEERP::eraseDatabase()
{
loginToDatabase();
	QString findTables = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;";
	if(m_query->exec(findTables))
	{
		QStringList tables;
		while(m_query->next())
		{
			tables << m_query->value(0).toString();
		}
		m_query->finish();
		for (int i=0;i<tables.size();i++)
		{
			QString dropTable = QString("DROP TABLE %1").arg(tables[i]);
			if(!m_query->exec(dropTable));
			{
				queryError("Tabelle löschen");
				return false;
			}	
		}
		
	}
	else
		return false;
	return true;
}
void MEERP::loginToDatabase()
{
	m_db.close();
	QSqlDatabase::removeDatabase("QSQLITE"); 
	m_db = QSqlDatabase::addDatabase("QSQLITE");
	m_db.setDatabaseName("data.s3db");
	m_db.setUserName("admin");
	m_db.setPassword("password");
	if(!m_db.open())
	{
		QMessageBox::warning(this, appTitle,tr("Die Datenbank konnte nicht geöffnet werden!"),QMessageBox::Ok);
		QApplication::quit();
		return;
	}
	m_query = new QSqlQuery(m_db);
}
Jmd die gloreiche Idee, was ich falsch mache? Schnelle Hilfe wäre super...auch reine Ideen sind erwünscht.

DANKE

Gruss
Groove
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Du brauchst weder eine QSqlQuery-Instanz (noch dazu nen pointer...) noch ein QSqlDatabase-Objekt speichern.
Du hast eh nur eine db, dann auch noch als defaultDatabase abgelegt.
In jeder FUnktion, die einen query losschickt, einfach kurz

Code: Alles auswählen

QSqlQuery query;
query.exec("SELECT irgendwas FROM irgendwo");
Und was du in loginToDatabase machst ist mir vollkommen schleierhaft...
Erst löschst du die DB (mit volkommen falschem Parameter -> DOKU!), dann erstellst du wieder eine db. Das geht nebenbei schief, da durch dein m_query noch auf die DB zugegriffen wird (daher wohl auch der LOCK...).
Lass das mal bleiben.

Poste dann wieder deinen bereinigten Code, wenn es immer noch Probleme gibt ;)
GrooveXT
Beiträge: 26
Registriert: 18. September 2008 17:10

Beitrag von GrooveXT »

Ok, erstmal danke.
Gut, das mit dem Query weiß ich, bin da nur ziemlich bequem und habe mir damit die Tipparbeit gespart, deswegen der Pointer. (Das Programm ist recht umfangreich)

So aber zum Testen habe ich es jetzt nochmal mit lokalen Querys probiert

Code: Alles auswählen

bool MEERP::eraseDatabase()
{
	QSqlQuery query;
	QString findTables = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;";
	if(query.exec(findTables))
	{
		QStringList tables;
		while(query.next())
		{
			tables << query.value(0).toString();
		}
		for (int i=0;i<tables.size();i++)
		{
			QString dropTable = QString("DROP TABLE %1").arg(tables[i]);
			if(!query.exec(dropTable));
			{
				queryError("Tabelle löschen",query);
				return false;
			}	
		}
	}
	else
		return false;
	return true;
}
Also der Query schmeißt immer noch nen false, aber er löscht die Tabellen...das auslesen des QSqlQuerryErrors ergibt keine Fehler! Soweit war ichzwischendurch auch mal...wäre nur interessant zu wissen, warum der Befehl ausgeführt wird, aber der Query nen false liefert...

Ansonsten hat das schon ein paar Probleme gelöst. Danke.

Erklär mir das aber mit der QSQLDatabase nochmal...ich brauche die in verschiedenen Widget, habe deswegen ne Klassenvariable angelegt und sie an die Widgets übergeben...kann ich mir die in den anderen Widget einfach mit QSQLDatabase::database holen?

Danke
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Dein query ist noch aktiv (vllt liegts daran...)

Code: Alles auswählen

bool MEERP::eraseDatabase() 
{  
   QStringList tables;
   {
      QSqlQuery query("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;"); 
      if(query.exec()) 
      { 
         while(query.next()) 
         { 
            tables << query.value(0).toString(); 
         }
      }
      else
         return false;
   }
   for (int i=0;i<tables.size();i++) 
   { 
      QSqlQuery query(QString("DROP TABLE %1;").arg(tables[i])); 
      if(!query.exec(dropTable)); 
      { 
         queryError("Tabelle löschen",query); 
         return false; 
      }     
   }
   return true; 
}
Besser?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

GrooveXT hat geschrieben:Erklär mir das aber mit der QSQLDatabase nochmal...ich brauche die in verschiedenen Widget, habe deswegen ne Klassenvariable angelegt und sie an die Widgets übergeben...kann ich mir die in den anderen Widget einfach mit QSQLDatabase::database holen?
Steht doch alles in der Doku ;)
Nur ein Beispiel:

Code: Alles auswählen

class DBUser
{
public:
    DBUser() {
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
        // db ist jetzt ein im Konstruktor lokales Objekt.
        // Es zeigt auf die defaultDatabase.
        db.setDatabaseName(Config::sqliteDBFile()); // setze sqlite-db-file
    }
    void doSomeScaryQuery()
    {
        QSqlQuery query; // query verwendet automatisch QSqlDatabase::database(), also die default-DB
        query.exec("SELECT car FROM carpark WHERE price>5000000000000;");
        // query verarbeiten;
    }
};
Sobald du deine db einmal initialisiert hast, kannst du von überall aus queries losschicken, selbst aus anderen Klassen(-Instanzen). Ein db-Objekt muss dabei nicht bekannt sein!
GrooveXT
Beiträge: 26
Registriert: 18. September 2008 17:10

Beitrag von GrooveXT »

Danke dir nochmal! :)

Wenn ich deinen Code einfüge, dann habe ich meine gute alte Fehlermeldung wieder, das die Datenbank gelockt ist. :)

Aber vielleicht liegt es wirklich an meinem Design, dass ich die Datenbank als Pointer übergeben habe... ich mache das gerade mal rückgängig...mal sehen obs klappt.

Für weitere Ideen bin ich aber noch offen ;)
GrooveXT
Beiträge: 26
Registriert: 18. September 2008 17:10

Beitrag von GrooveXT »

Ok, also nachdem ich nun alles entwirrt habe und überall die Pointer rausgenommen habe, bekomme ich nun eine anderen Fehlermeldung.. und zwar: no such table: articles

Die Tabelle heißt aber so und wurde auch gelöscht...naja wenigstens bin ich jetzt vom DB-Lock weg, dass ist schon mal nen Fortschritt.

Vielen Dank erstmal.
GrooveXT
Beiträge: 26
Registriert: 18. September 2008 17:10

Beitrag von GrooveXT »

Ok nun gehts!

Deine Quellcode war richtig...es lag wirklich an dem nicht geschlossenen Query. Danke.

Problem war nur folgendes

Code: Alles auswählen

if(!query.exec());
Das Semikolon gehörte da nicht hin...deswegen ist er immer in die Fehlerabfrage reinmaschiert. Habe ich aber auch die ganze Zeit übersehen :)

Danke dir nochmal! Nen schönen Abend noch !
Antworten