3

I'm puzzling over a weird problem I cannot replicate.

Scenario

I wrote a simple nodejs application that, after some UI interaction append some records to an Access 97 database. I'm using node-adodb to connect with it.

Some relevant piece of code.

var DBDATA = require('node-adodb'), dbConnection = DBDATA.open('Provider=Microsoft.Jet.OLEDB.4.0;Data Source=/path/to/my/file.mdb'); function append(data, callback) { var table; var query; var array = []; array.push({name: "Date", value: formatDate(data.date)}); array.push({name: "Time", value: formatTime(data.date)}); array.push({name: "Type", value: Number(data.Type)}); array.push({name: "Value", value: Number(exists(data.value, 0))}); // ...other fields var fields = array.map(function (e) { return "[" + e.name + "]"; }).join(","); var values = array.map(function (e) { return e.value; }).join(","); table = "tblData"; query = 'INSERT INTO ' + table + '(' + fields + ') ' + 'VALUES (' + values + ')'; dbConnection .execute(query) .on('done', function (data) { return callback({id: id, success: true}); }) .on('fail', function (data) { console.log(data); return callback({id: id, success: false}); }); } 

The issue

The above function is called whenever a new record is ready. Usually it works fine, but it happens about 1 time per week (among hundreds of records) that I find in the database multiple rows identical.

Due to the nature of the information this is impossible - I mean, it's impossible that the actual data is the same.

I guessed for a bug in the caller, that for some reasons sends me the same variable's content. Hence I added a check before append the record.

What I tried to do

function checkDuplicate(table, array, callback) { var query = "SELECT * FROM " + table + " WHERE "; array.forEach(function(element) { query += "([" + element.name + "]=" + element.value + ") AND "; }); query = query.substr(0, query.length - 4); dbConnection .query(query) .on("done", function (data) { return callback(data.records.length > 0); }) .on("fail", function (data) { return callback(false); }); } 

in the append function I call this one and if it returns a value > 0 I don't execute the query, because it would mean there already is the same row.

Testing it with fake data gave good results: no multiple records were added. Unfortunately, this didn't fixed the issue in the real world. After 20 days I noticed that a row was added three times.

Questions

  1. Do you see any evidence of a major mistake in my approach?
  2. Is there a more reliable way to avoid this problem?

Please note I cannot change the database structure because it's not mine.

UPDATE

This is the new code I'm using:

// Add only if there isn't an identical record query = 'INSERT INTO ' + table + '(' + fields + ') '; query += ' SELECT TOP 1 ' + values; query += ' FROM ' + table; query += ' WHERE NOT EXISTS ( SELECT 1 FROM ' + table + ' WHERE '; array.forEach(function(element) { query += "([" + element.name + "]=" + element.value + ") AND "; }); query = query.substr(0, query.length - 4); query += ' );'; dbConnection .execute(query) .on('done', function (data) { return callback({id: id, success: true}); }) .on('fail', function (data) { console.log(data); return callback({id: id, success: false}); }); 

but it doesn't solved the problem, i.e. sometimes I still found two or more records identical in the database.

I'm afraid it could be the same behavior: the client make multiple requests in a while and they are executed in parallel, so each one doesn't find the record, and all will be add it.

Hance, what is the right approach to avoid this without change the database structure? Is there a way to force node-adodb to execute only one query at time?

7
  • 1
    Javascript works parallel (async). That means, it would request data 3 times in almost the same timespan. After that, it would insert the data. That means it gets 0 returned all three times, and store the data three times after that. Commented Nov 14, 2017 at 14:48
  • Is it possible to force that function to work sync? Or what other tools I have to avoid the issue? Commented Nov 14, 2017 at 15:10
  • 1
    Checking existing records can be made even in sql Commented Nov 14, 2017 at 15:32
  • @Maxim something like this? stackoverflow.com/a/4253987/881712 Commented Nov 14, 2017 at 18:30
  • @Mark Yes, but probably ms access has some different syntax Commented Nov 16, 2017 at 7:45

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.