Error: Missing query string MariaDB NodeJS - node.js

I have this error every time I try to run a query to DB:
Error: Missing query string
I don't understand what could be wrong with my code, the query is correct I have tested it:
function getChannelCTSize(octopusMac, channelID, adcTicks, callback){
var queryString = "SELECT Channels.CT_size FROM Channels INNER JOIN Octopus ON Octopus.Id=Channels.Octopus_Id WHERE Octopus.Mac = ? AND Channels.Channel_Id = ?";
var filter = [octopusMac, channelID];
var query = mariaDB.query({
sql: queryString
}, filter );
query.on('error', function(err) {
if (err) {
console.log(err.code);
return
}
})
.on('result', function(row) {
callback(result[0].CT_size, channelID, octopusMac, adcTicks);
})
.on('end', function() {
mariaDB.release();
});
}

The query function of mariasql should be invoked with a string as first argument (the query) instead of an object)
It should look like:
var queryString = "SELECT Channels.CT_size FROM Channels INNER JOIN Octopus ON Octopus.Id=Channels.Octopus_Id WHERE Octopus.Mac = :octopusMac AND Channels.Channel_Id = :channelID";
var query = mariaDB.query(queryString, { octopusMac, channelID }, function(err, rows) {
if (err)
console.log(err.code);
callback(rows[0].CT_size, channelID, octopusMac, adcTicks);
})

Related

in sqlite3 (node package), how to run multiple queries by sequence?

I am using this pakcage: sqlite3 to manipulate database queries, code like this:
single query is quit simple:
var sqlite3 = require('sqlite3').verbose();
let db = new sqlite3.Database('database.sqlite3');
let entity_1_name = ''
db.serialize(function(){
db.get('select * from table1 where id = 1', function(error, row){
entity_1_name = row.name
})
})
db.close()
But how to execute multiple queries and in sequence?
(e.g. I want to run query1, then query2, then query3 )
just like:
var sqlite3 = require('sqlite3').verbose();
let db = new sqlite3.Database('database.sqlite3');
let entity_1_name = ''
let entity_2_name = ''
db.serialize(function(){
// this is query1
db.get('select * from table1 where id = 1', [], function(error, row){
entity_1_name = row.name
})
// this is query2
db.get('select * from table2 where dependency_column_name = ' + entity_1_name, function(error,row){
// this sql returns null value, because when this query was executed, the variable "entity_1_name" was not determined by query1.
})
})
db.close()
https://stackoverflow.com/a/40903302/16140221 May help you out
Their solution was to place each query within a function, then simply calling them.
(This is directly the code taken from the answer, it is not mine.)
function db_query1(your_param,...., callback){
  // database operation
db.run( sql , [param,...] , function(err,rows){
if(err) // return
else{
// get rows with callback
callback(null, rows);
}
});
}
function db_query2(your_param,...., callback){
  // database operation
db.run( sql , [param,...] , function(err,rows){
if(err) // return
else{
// get rows with callback
callback(null, rows);
}
});
}
Then calling the functions
db_query1(....,function(err,result1){
if(err) ...// return
// do the things with result1
// And then call query2
db_query2(....,function(err,result2){
if(err) ...// return
// do the things with result1
});
});
OK, at last, I used promise + async + await to make it done.
Step1. define a function return new Promise()
do_query_1(material_name){
// 1. return this new Promise()
return new Promise( (resolve, reject) => {
let db = this.$database_tool.get_db()
let that = this
db.serialize(function(){
db.get(`select * from table1 where id = 1`, [], function(error, row){
// 2. this is the point, put anything you want to result to resolve()
resolve(row.id)
})
})
db.close();
})
},
Step2. define a async function, to call the method defined in Step1.
async do_query_2(){
let that = this
// other lines was omitted.
// HERE , use await to get the result from STEP1.
let entity_1_name = await that.do_query_1(row.material_name)
db.serialize(function(){
let sql = `'select * from table2 where dependency_column_name = ' + entity_1_name`
db.run(sql)
})
db.close();
},
Step3. call do_query_2() in normal way:
do_query_2()
That's it!

Cosmos db readDocument api not work in stored procedure

A simple stored procedure using readDocument function in CosmosDB/DocumentDB, but it does not work.
function testRead() {
var collection = getContext().getCollection();
var docId = collection.getSelfLink() + 'docs/myDocId';
// Query documents and take 1st item.
var isAccepted = collection.readDocument(docId, {}, function (err, doc, options) {
if (err) throw err;
response.setBody(JSON.stringify(doc));
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
it always get error code 400.
{"code":400,"body":"{\"code\":\"BadRequest\",\"message\":\"Message:
{\\"Errors\\":[\\"Encountered exception while executing Javascript.
Exception = Error: Error creating request message\\r\\nStack
trace: Error: Error creating request message\\n at readDocument
(testRead.js:512:17)\\n at testRead (testRead.js:8:5)\\n at
__docDbMain (testRead.js:18:5)\\n at Global code (testRead.js:1:2)\\"]}\r\nActivityId:
2fb0f7ef-c192-4b56-b8bb-9681c9f8fa6e, Request URI:
/apps/DocDbApp/services/DocDbServer22/partitions/a4cb4962-38c8-11e6-8106-8cdcd42c33be/replicas/1p/,
RequestStats: , SDK:
Microsoft.Azure.Documents.Common/1.22.0.0\"}","activityId":"2fb0f7ef-c192-4b56-b8bb-9681c9f8fa6e","substatus":400}
Anyone can help me ?
Can you try this: var docId = collection.getAltLink() + 'docs/myDocId';
-- self link is not for "name routing".
According to Michael's suggestion, my sample works now, here is the code
function testRead() {
var collection = getContext().getCollection();
var response = getContext().getResponse();
var docId = collection.getAltLink() + '/docs/myDocId';
// Query documents and take 1st item.
var isAccepted = collection.readDocument(docId, {}, function (err, doc, options) {
if (err) throw err;
response.setBody(JSON.stringify(doc));
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
You could modify your code like :
function testRead() {
var collection = getContext().getCollection();
var docId = collection.getAltLink() + 'docs/myDocId';
console.log(collection.getSelfLink() + 'docs/myDocId');
var isAccepted = collection.readDocument(docId, {}, function (err, doc, options) {
if (err) throw err;
response.setBody(JSON.stringify(doc));
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
Or you could use follow sample code to query the document, it also contains all of the fields.
function testRead() {
var collection = getContext().getCollection();
var query = "select * from c where c.id = '1'";
var isAccepted = collection.queryDocuments(collection.getSelfLink(), query,function (err, doc, options) {
if (err) throw err;
var response = getContext().getResponse();
response.setBody(JSON.stringify(doc));
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}

how to promises in a loop?

I am trying write a cron function in nodejs which fetches user_ids of all the users from the db and then I want to parse through each user_id.
Here is my code :
cron.schedule('43 11 * * *', function(){
var now = moment()
var formatted = now.format('YYYY-MM-DD HH:mm:ss')
console.log('Starting the cron boss!');
var dbSelectPromise = function(db, sql1) {
return new Promise(function(resolve, reject) {
db.select(sql1, function(err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
}
var users =[]
var sql = "select distinct(user_id) from user_level_task"
dbSelectPromise(db,sql).then(function(secondResult){
for(i=0;i<secondResult.length;i++){
var sql1 = "select max(level_id) as level from user_level_task where user_id ="+secondResult[i].user_id
dbSelectPromise(db,sql1).then(function(thirdResult){
console.log(thirdResult)
console.log(current)
var sql2 = "select task_id form user_level_task where user_id = '"+secondResult[i].user_id+"' and level_id = '"+thirdResult[0].level+"' "
dbSelectPromise(db,sql2).then(function(fourthResult){
var leng = fourthResult.length
for(i=0;i<leng;i++){
console.log(fourthResult[i])
}
})
})
}
})
});
The problem i am facing is i cannot access value of i in third and fourth promises. Please help!
I think what's happening is that i is no longer the same when you create those new promises because the for loop is still running. It appears that what you really need is the user_id and level_id. I suggest you restructure your code a bit to reduce nesting and pass on the values you need for future promises.
Perhaps something similar to this:
dbSelectPromise(db, sql)
.then(secondResult => {
const levelPromises = [];
secondResult.forEach(res => {
levelPromises.push(getLevelByUserId(res.user_id, db));
});
return Promise.all(levelPromises); // Promise.all only if you want to handle all success cases
})
.then(result => {
result.forEach( level => {
{ userId, queryResult } = level;
// ...
})
//...
})
.catch(err => {
console.log(err);
});
function getLevelByUserId(userId, db) {
const query = `select max(level_id) as level from user_level_task where user_id = ${userId}`;
return dbselectPromise(db, query).then(result => { userId, result });
}
It creates an array of all the get level queries as promises and then passes it along to the next step using Promise.all() which will only resolve if all queries were successful. At that point, you will have access to the userId again of each result because we returned it in our new function for your next set of queries.
I think you should abstract your queries a bit further instead of using a generic dbSelectPromise and don't forget to catch() at the end otherwise you won't know what's happening.
Note: It assumes your db variable instantiated properly and your original db.select doesn't need to be returned based on whatever library you're using. There's also some new syntax there.
The problem i am facing is i cannot access value of i in third and fourth promises. Please help!
This is because you're using reinitializing i without using let. When the loop is in process, the value will be different than what you expect.
each promise is dependant on the other and need to run synchronously
For this to work, You need to chain promises. Also, you can make use of Promise.all() to execute a bunches of promises at once. Remember, Promise.all() is all or nothing.
Making those changes to your code, I get the following structure.
'use strict';
let _ = require('lodash');
function dbSelectPromise(db, sql1) {
return new Promise((resolve, reject) => {
return db.select(sql1, (err, data) => {
if (err) {
return reject(err);
}
return resolve(data);
});
});
}
function process(secondResult) {
let sql1 = "select max(level_id) as level from user_level_task where user_id =" + secondResult[i].user_id;
return dbSelectPromise(db, sql1).then(function (thirdResult) {
console.log(thirdResult);
let sql2 = "select task_id form user_level_task where user_id = '" + secondResult[i].user_id + "' and level_id = '" + thirdResult[0].level + "' ";
return dbSelectPromise(db, sql2);
});
}
function getUsers() {
let sql = "select distinct(user_id) from user_level_task";
return dbSelectPromise(db, sql).then((users) => {
return users;
}).catch(() => {
return [];
});
}
cron.schedule('43 11 * * *', function () {
var now = moment();
var formatted = now.format('YYYY-MM-DD HH:mm:ss');
getUsers().then((users) => {
let batches = _.map(users, function (user) {
return process(user);
});
return Promise.all(batches);
}).then((fourthResult) => {
console.log('Your fourthResult [[],..]', fourthResult);
}).catch(() => {
console.log('err while processing', err);
});
});

nodejs get sqlite3 query result using promise or wait

This is my first personal project in Nodejs. I'm trying to get in live soon.
I have a Nodejs server that uses sqlite3. There are only 3000 rows with word, transform and a precalculated value each in a column of the table, which is already populated.
I need to just lookup the word in the DB to be sure it is valid.
var sqlite3 = require("sqlite3").verbose();
var db = new sqlite3.Database("validate.db");
db.get("SELECT * FROM tab WHERE w = ?", word, function(err, row) {
if(err) { console.log("Lookup:",word,", Error => ",err); return false; }
return true;
});
The problem is that the caller of this code has a lot of context and need the operation to wait. So, I tried this
function dbLookup(db, w) {
return function(cb) {
var rows = [];
db.exec('SELECT w FROM tab WHERE w = "'+w+'"')
.on('row', function(r) {
rows.push(r)
})
.on('result', function() {
cb(rows);
});
}
async.each([word], function(w) {
dbLookup(this.db, w);
}, function(err) {
if(err) {console.log("...ERROR..."); return false; }
else {console.log("...SUCCESS..."); return true; }
});
This doesn't solve the wait issue as the callback can fire at its own pace.
I read that promise using something like bluebird can solve my problem
but now I'm not able to get the value/result of the query out:
I've been pulling my hair for so long. Please help me either get the async working or get the result back from the promise approach.
var async = require('async');
var sqlite3 = require("sqlite3").verbose();
var db = new sqlite3.Database("validate.db");
function check(word, callback) {
db.get("SELECT count(1) cnt FROM tab WHERE w = ?", word, callback)
}
async.map(words, check, function(err, results) {
if (err)
return console.log('Query error')
var all_checked = results.filter(function(r) {
return r.cnt > 0
});
...
});
Or
var sqlite3 = require("sqlite3").verbose();
var db = new sqlite3.Database("validate.db");
db.all("SELECT distinct w FROM tab", function(err, rows) {
var all_checked = words.filter(function (w) {
return rows.indexOf(w) != -1;
})
...
})

Nodejs crashes when database connection fails

While my database server is not available and any function of my node-express rest service like hiExpress is called, Nodejs crashes the node server and console of node reports
sql server connection closed
I do not want this to happen because either it should go to err function or at least it must be cautht by catch block. What could i do to avoid the crash of nodejs when database server is not available I am using following code which is absolutely fine as long as database server is available.
var sqlServer = require('seriate');
app.get('/hiExpress',function(req, res)
{
var sr = {error:'',message:''};
var sql= 'select * from table1 where id=? and name=?';
var params = {id: 5, name:'sami'};
exeDB(res,sr,sql, params);//sent only 4 parameters (not 6)
});
function exeDB(res, sr, sql, params, callback, multiple) {
try {
var obj = {};
for (p in params) {
if (params.hasOwnProperty(p)) {
obj[p] = {
type: sqlServer.VARCHAR,
val: params[p]
};
}
};
var exeOptions = {
query: sql,
params: obj
};
if (multiple) {
exeOptions.multiple = true;
}
sqlServer.execute(sqlServerConfigObject, exeOptions).then(function (results) {
sr.data = results;
if (callback)
callback(sr);
else
res.json(sr); //produces result when success
}, function (err) {
//sr.message = sql;
console.log(11);
sr.error = err.message;
res.json(sr);
});
}
catch (ex) {
console.log(21);
sr.error = ex.message;
res.json(sr);
}
}
Why I preferred to use seriate
I had not been much comfortable with node-SQL, especially when when it came to
multiple queries option even not using a transaction. It facilitates easy go to parameterized queries.
You can use transaction without seriate but with async like below
async.series([
function(callback) {db.run('begin transaction', callback)},
function(callback) {db.run( ..., callback)},
function(callback) {db.run( ..., callback)},
function(callback) {db.run( ..., callback)},
function(callback) {db.run('commit transaction', callback)},
], function(err, results){
if (err) {
db.run('rollback transaction');
return console.log(err);
}
// if some queries return rows then results[query-no] contains them
})
The code is very dirty. Pass req and res params to db-layer is not a good idea.
Try change exeDB. I'm not sure, but probably you don't set error catcher to promise
function exeDB(res, sr, sql, params, callback, multiple) {
// It will execute with no error, no doubt
var obj = {};
for (p in params) {
if (params.hasOwnProperty(p)) {
obj[p] = {
type: sqlServer.VARCHAR,
val: params[p]
};
}
};
var exeOptions = {
query: sql,
params: obj
};
if (multiple) {
exeOptions.multiple = true;
}
// Potential problem is here.
// Catch is useless because code below is asynchronous.
sqlServer.execute(sqlServerConfigObject, exeOptions).then(function (results) {
sr.data = results;
if (callback)
callback(sr);
else
res.json(sr); //produces result when success
}).error(function(err){ // !!! You must provide on-error
console.log(err);
};
}

Resources