Hallo hmm,
ich habe schon verstanden, was Du erreichen willst. Nur halte ich deinen Weg für sehr umständlich, daher die Frage, ob es mit einer UPDATE/INSERT Sequenz nicht einfacher wäre.
Die dbLokal.run() Befehle einzeln in einen serialize zu packen, nützt definitiv nichts. Das habe ich so auch nicht vorgeschlagen. Und dedlfix meinte, dass serialize() nicht unbedingt nützt, weil die run() Befehle IMMER noch sofort zurückkehren.
dedlfix hat dich auch auf prepared statements hingewiesen - sqlite hat eine Syntax für einen transparenten Prepare. Die verwende ich nun.
Das Promise-Geraffel ist VIEL Boilerplate-Code, das gefällt mir nicht wirklich. Aber mit Promises geht's wohl nicht anders.
var SQL_INSERT_MITARBEITER = "insert into mitarbeiter (name) select $name where not exists (select 1 from mitarbeiter where name = $name );";
var SQL_SELECT_USER_MITARBEITER_ID = "select user_id, mitarbeiter_id from user, mitarbeiter where user.email = ?email and mitarbeiter.name = $name;";
var SQL_INSERT_USER_MITARBEITER = "insert into user_mitarbeiter (user_id, mitarbeiter_id) select $user_id, $m_id where not exists (select 1 from user_mitarbeiter where user_id = $user_id and mitarbeiter_id = $m_id);";
var SQL_INSERT_SKILL = "insert into mitarbeiter_skill (mitarbeiter_id, skill, subskill, nivau) values ($m_id, $skill, $subskill, $nivau);";
var SQL_UPDATE_SKILL = "update mitarbeiter_skill set niveau=$niveau where mitarbeiter_id = $m_id and skill = $skill and subskill = $subskill;";
this.generateOneUpdate = function(email, data) {
var db = new sqlite3.Database(dbRef);
new Promise(function(resolve, reject) {
db.run(SQL_INSERT_MITARBEITER,
{ name: data.name },
function(err) {
if (err)
// todo: Setze sinnvolle Message
reject({ success: false, dbError: err, msg: "msg1" })
else
resolve();
});
})
.then(function() {
return new Promise(function(resolve,reject) {
db.get(SQL_SELECT_USER_MITARBEITER_ID,
{ email: email, name: data.name },
function(err, row) {
if (err)
reject({ success: false, dbError: err, msg: "msg2" });
else
resolve(row);
});
});
})
.then(function(umaRow) {
if (umaRow == null) {
// Deine Entscheidung, ob das ein Fehler ist. Wenn ja, msg setzen.
reject({success: ???});
} else {
return new Promise(function(resolve, reject) {
db.run(SQL_INSERT_USER_MITARBEITER,
{ user_id: umaRow.user_id, m_id: umaRow.mitarbeiter_id },
function(err) {
if (err)
reject({dbError: true, err: err, msg: "msg3"});
else
resolve();
});
});
})
.then(...) // UPDATE-Versuch, reject({success:true}) wenn erfolgreich
.then(...) // INSERT
.catch(function(err) {
// Catch mit Success:true diente nur dem Abbruch der Sequenz
if (err.success) return;
if (err.dbError) {
// db-Fehler behandeln, err.msg protokollieren
} else if (err.msg) {
// msg ohne dbFehler, kann auch sein
}
});
}
Ich habe es nicht komplett aufgeschrieben, der Rest ist für dich zum Üben (um beim Fisch/Angel Modell zu bleiben: ich habe dir gezeigt wie man die Angel auswirft und der Fisch hat angebissen, nun nimm die Angel und hol den Fisch selbst ein.)
Gezeigt habe ich jedenfalls:
- Wie verkettest Du Promises, wenn im then ein weiterer asynchroner Prozess gestartet werden muss
- Wie brichst Du eine then-Kette ab, wenn eine Voraussetzung zur Fortsetzung nicht erfüllt ist
- Wie vermeidest Du Deine .replace() Orgien
Und einen Hinweis auf eine bessere SQL Sequenz für die Skills hast Du auch.
Möglicherweise sind Syntaxfehler im Code, ich habe das geschrieben ohne es auf irgendeine Script-Engine loszulassen.
Und - äh, ja - es geht mir wir Dedlfix: Ich habe NUR Doku gelesen und wiedergegeben, was ich verstanden habe. Praxiserfahrung mit sqlite3 unter node habe ich nicht.
Hoffe, dass es nicht nur verwirrt hat...
Rolf
Dosen sind silbern