5 Stimmen

No Such Table Fehler von SQLite Speicher DB über DataMapper

Ich habe ein Ruby-Programm, das DataMapper als ORM verwendet, um mit einer In-Memory-SQLite-DB zu sprechen. Dies hat gut funktioniert, aber ich habe gerade vor kurzem eine neue DM-Klasse und die entsprechende Tabelle hinzugefügt. Zu meiner Überraschung, Dinge jetzt sprengen während einer auto_migrate!

Hier ist das von DataMapper generierte SQL:

~ (0.000390) PRAGMA table_info("sensationd_channels")
~ (0.000010) PRAGMA table_info("sensationd_commands")
~ (0.000009) PRAGMA table_info("sensationd_configurations")
~ (0.000052) PRAGMA table_info("sensationd_measurements")
~ (0.000028) SELECT sqlite_version(*)
~ (0.000035) DROP TABLE IF EXISTS "sensationd_channels"
~ (0.000009) PRAGMA table_info("sensationd_channels")
~ (0.000423) CREATE TABLE "sensationd_channels" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "channel" INTEGER NOT NULL, "name" VARCHAR(50), "precision" INTEGER DEFAULT 11, "gain" INTEGER DEFAULT 1, "differential" BOOLEAN DEFAULT 'f', "configuration_id" INTEGER NOT NULL)
~ (0.000191) CREATE INDEX "index_sensationd_channels_configuration" ON "sensationd_channels" ("configuration_id")
~ (0.000015) DROP TABLE IF EXISTS "sensationd_commands"
~ (0.000009) PRAGMA table_info("sensationd_commands")
~ (0.000153) CREATE TABLE "sensationd_commands" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "action" INTEGER DEFAULT 1, "complete" BOOLEAN DEFAULT 'f', "issued_at" TIMESTAMP, "completed_at" TIMESTAMP)
~ (0.000015) DROP TABLE IF EXISTS "sensationd_configurations"
~ (0.000009) PRAGMA table_info("sensationd_configurations")
~ (0.000155) CREATE TABLE "sensationd_configurations" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "created_on" TIMESTAMP, "modified_on" TIMESTAMP, "name" VARCHAR(50) NOT NULL, "active" BOOLEAN)
~ (0.000015) DROP TABLE IF EXISTS "sensationd_measurements"
~ (0.000009) PRAGMA table_info("sensationd_measurements")
~ (0.000152) CREATE TABLE "sensationd_measurements" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "timestamp" TIMESTAMP, "measurement" VARCHAR(65535) NOT NULL, "channel_id" INTEGER NOT NULL, "channel_configuration_id" INTEGER NOT NULL)
~ (0.000175) CREATE INDEX "index_sensationd_measurements_channel" ON "sensationd_measurements" ("channel_id", "channel_configuration_id")
~ (0.000083) SELECT "id", "created_on", "modified_on", "name", "active" FROM "sensationd_configurations" WHERE "active" = 't' ORDER BY "id" LIMIT 1
~ (0.000073) INSERT INTO "sensationd_configurations" ("created_on", "modified_on", "name", "active") VALUES ('2011-08-01T12:36:18-07:00', '2011-08-01T12:36:18-07:00', 'Test U6-Pro Configuration, differential.', 't')
~ (0.000109) SELECT "id", "action", "complete", "issued_at", "completed_at" FROM "sensationd_commands" ORDER BY "issued_at" DESC LIMIT 1
~ (0.000086) INSERT INTO "sensationd_channels" ("channel", "name", "precision", "gain", "differential", "configuration_id") VALUES (0, '0', 11, 0, 't', 1)
~ no such table: sensationd_commands (code: 1, sql state: , query: SELECT "id", "action", "complete", "issued_at", "completed_at" FROM "sensationd_commands" ORDER BY "issued_at" DESC LIMIT 1, uri: sqlite3::memory:?scheme=sqlite&user=&password=&host=&port=&query=&fragment=&adapter=sqlite3&path=:memory:)

Es sieht so aus, als ob das Erstellen der Tabelle gut funktioniert, aber nur ein paar Zeilen später kann sie nicht mehr gefunden werden. Ich würde denken, dass ich die DB-Verbindung falsch konfiguriert habe, außer dass die anderen Tabellen gefunden werden und einwandfrei funktionieren.

Software im Spiel:

  • Ruby 1.9.2p289 über RVM
  • SQLite3 @3.7.7.1 über MacPorts
  • DataMapper gem v 1.1.0

Weiß jemand, warum das Problem auftritt, und was ich dagegen tun kann?

4voto

namelessjon Punkte 907

Das Problem liegt, so vermute ich, am Thread-Pooling, das DataMapper (oder genauer gesagt DataObjects, der Datenbanktreiber, den DataMapper verwendet) automatisch durchführt. Die Datenbankverbindung wird nicht zwischen Threads geteilt. Das ist in Ordnung (und sogar vorteilhaft) für so etwas wie Postgresql oder Mysql oder sogar Sqlite3 als "file-backed" Datenbank. Im Fall von sqlite3's In-Memory-Speicher, wird die Verbindung ist die Datenbank. Daher werden weitere Threads aus diesem Grund fehlschlagen. Außerdem wird der Thread nach einer gewissen Zeit der Inaktivität (~1 Minute?) gelöscht und die Datenbank wird ebenfalls gelöscht.

Wenn dies der Fall ist, bin ich mir nicht sicher, ob es eine einfache Lösung dafür gibt. Vielleicht können Sie do_sqlite3 ändern, um dies zu vermeiden. Eine andere Alternative, die im Grunde genauso schnell sein sollte, ist die Verwendung einer Datei-backed sqlite3 DB auf einem ramdrive.

3voto

Robertiano Punkte 352

Ich kopiere meinen Kommentar als Antwort auf Anregung von @Lukas_Skywalker

Ich weiß, es ist zu spät, aber vielleicht kann es jemandem helfen. Sie können den gemeinsamen SQLite-Speicher-Cache verwenden, indem Sie den speziellen Dateinamen file::memory:?cache=shared verwenden. Dadurch können verschiedene Datenbankverbindungen dieselbe In-Memory-Datenbank gemeinsam nutzen. sqlite.org/inmemorydb.html

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X