I am trying to write a code to connect with snowflake inside the azure function app using nodejs stack. Here is the code I have writtern.
async function af2snf()
{
console.log("starting connection");
var snowflake = require('snowflake-sdk');
// Create a Connection object that we can use later to connect.
console.log("prep conn");
var connection = snowflake.createConnection( {
account: "myaccountname",
username: "myusername",
password: "mypass",
database: "dbname",
schema: "schemaname"
}
);
console.log("making connection");
var conn_id = connection.connect(
function(err, conn) {
if (err) {
console.error('Unable to connect: ' + err.message);
}
else {
console.log('Successfully connected to Snowflake.');
// Optional: store the connection ID.
connection_ID = conn.getId();
}
}
)
return conn_id.getId();
}
console.log("outside fucntion");
console.log(af2snf());
console.log("executed fucntion");
The output I am getting is :
outside fucntion
starting connection
prep conn
making conn
Promise { <pending> }
executed fucntion
Successfully connected to Snowflake.
But What I need is :
outside fucntion
starting connection
prep conn
making conn
Successfully connected to Snowflake.
Promise { <pending> }
executed fucntion
I am very new to nodejs. Please help me out on this
af2nsf needs to return a promise :
async function af2snf() {
return new Promise((resolve,reject)=>{
console.log("starting connection");
var snowflake = require('snowflake-sdk');
// Create a Connection object that we can use later to connect.
console.log("prep conn");
var connection = snowflake.createConnection( {
account: "myaccountname",
username: "myusername",
password: "mypass",
database: "dbname",
schema: "schemaname"
});
console.log("making connection");
connection.connect( async function(err, conn) {
if (err) {
console.error('Unable to connect: ' + err.message);
return reject(err);
}
else {
console.log('Successfully connected to Snowflake.');
// Optional: store the connection ID.
var conn_id = await conn.getId();
return resolve(conn_id);
}
})
});
}
console.log("outside fucntion");
af2snf().then(conn_id=>{
console.log(conn_id);
console.log("executed fucntion");
}).catch(err=>{
console.error(err);
});
So I have done C++ Java and PHP and wanted to give a crack at Node.js. Below I have a very simple and unsecured SQL query.
module.exports = {
LoginCheck: function(data,cb){
console.log(data.password);
console.log(data.username);
if(data.username && data.password){
console.log('we have arrived');
var config = require(__dirname+'/../Config/config.json');
var mysql = require('mysql');
var con = mysql.createConnection({
host: config.LoginDBhost,
port: config.LoginDBport,
user: config.LoginDBusername,
password: config.LoginDBpassword,
database: config.LoginDB
});
con.connect(function(err) {
if (err) throw err;
console.log('we have connected');
con.query("SELECT * FROM `Users` WHERE `Username` = '"+data.username+"'", function (err, result) {
if (err) console.log(err);
if(result.Password){
if(result[0].Password){
if(result[0].Password == data.password){
console.log('true');
cb(true);
}
}
}
});
});
}
//either password is null or didnt match on file... if we are this far its a fail
console.log('false');
cb(false);
},
bar: function () {
// whateverss
}
};
The code does not wait for the sql connection and skips to being false. I been banging my head on a desk for days trying to figure out how promises and callbacks works after years of having my code follow steps layed.
Could someone convert this and explain how to force my code to be synchronous when I need it to be?
Try this code :
module.exports = {
LoginCheck: function(data,cb){
console.log(data.password);
console.log(data.username);
if(data.username && data.password){
console.log('we have arrived');
var config = require(__dirname+'/../Config/config.json');
var mysql = require('mysql');
var con = mysql.createConnection({
host: config.LoginDBhost,
port: config.LoginDBport,
user: config.LoginDBusername,
password: config.LoginDBpassword,
database: config.LoginDB
});
con.connect(function(err) {
// I think cb(false) here but you use throw err.
if (err) throw err;
console.log('we have connected');
con.query("SELECT * FROM `Users` WHERE `Username` = '"+data.username+"'", function (err, result) {
if (err) console.log(err);
if(result.Password){
if(result[0].Password){
if(result[0].Password == data.password){
console.log('true');
cb(true);
}
}
}
//either password is null or didn't match on file... if we are this far its a fail
console.log('false');
cb(false);
});
});
}
},
bar: function () {
// whateverss
}
};
I am trying to connect to my Azure SQL DB from an azure function written in nodeJS. I have set the connection strings in the application settings and it still does not work. I used ODBC key for connection settings. Did anyone try this? Below is the sample code for my function
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
// Create connection to database
const config = process.env["sqldb_connection"];
var connection = new Connection(config);
// Attempt to connect and execute queries if connection goes through
connection.on('connect', function(err)
{
if (err)
{
console.log(err)
}
else
{
queryDatabase()
}
}
);
function queryDatabase()
{ console.log('Reading rows from the Table...');
// Read all rows from table
request = new Request(
"SELECT ORG_ID,ORG_NAME FROM org",
function(err, rowCount, rows)
{
console.log(rowCount + ' row(s) returned');
process.exit();
}
);
request.on('row', function(columns) {
columns.forEach(function(column) {
console.log("%s\t%s", column.metadata.colName, column.value);
});
});
connection.execSql(request);
}
I am getting an error saying
Exception while executing function: Functions.HttpTriggerJS2. mscorlib: The given key was not present in the dictionary.
Run the npm install tedious command in the Kudu remote execution console under D:\home\site\wwwroot.
In Azure Functions, all of your code should be put inside the module.exports function.
You should use context.log() instead of console.log().
You really don't have to set the connection settings string in Application settings of the function.
You should inform the runtime when your code has finished by calling context.done().
The following code works for me:
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
module.exports = function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
var config = {
userName: '<userName>',
password: '<password>',
server: '<AzureSQLDBName>.database.windows.net',
// If you're on Windows Azure, you will need this:
options:
{
database: 'your DB',
encrypt: true
}
};
var connection = new Connection(config);
connection.on('connect', function(err) {
if (err) {
context.log(err);
context.res = {
status: 500,
body: "Unable to establish a connection."
};
context.done();
} else {
executeStatement();
}
});
function executeStatement() {
request = new Request("select 42, 'hello world'", function(err, rowCount) {
if (err) {
context.log(err);
context.res = {
status: 500,
body: "Failed to connect to execute statement."
};
context.done();
} else {
context.log(rowCount + ' rows');
}
});
request.on('row', function(columns) {
columns.forEach(function(column) {
context.log(column.value);
});
context.done();
});
connection.execSql(request);
}
};
For more information, see Azure Functions JavaScript developer guide.
I am using oracledb npm package to establish connection with the DB when creating a node.js backend API. I am able to obtain the result when I do console.log(result.rows)
Below is the function code
getDbConnection: function(query) {
var connectInfo= [EnvConfig.getConnectionHostName(), EnvConfig.getConnectionPort()]; // Array of hostname and port
var connectHost = connectInfo.join(':'); // join hostname and port with ':'
var connectionAttr = [connectHost, EnvConfig.getConnectionSID()]; // hostname:port and SID
var connectString = connectionAttr.join('/'); // creating the connection string like 'hostname:port'
console.log(connectString);
// creating a oracle connection
oracledb.getConnection(
{
user: EnvConfig.getConnectionUserName(),
password: EnvConfig.getConnectionPassword(),
connectString: connectString
},
function (err, connection) {
if(err) {
console.log(err.message);
return;
}
connection.execute(
query, function(err, result) {
if(err) {
console.log(err.message);
return;
}
console.log(result.rows); // I get result here
return result.rows; // return result on success
}
);
}
);
}
I call the getDbConnection function from other file and when I console.log() like console.log(getDbConnection(query)) . I get the result as undefined. How do I solve this.
you can't get your data like this. Return like this will not gonna work here
Since it works in async nature, you can do one thing to use a callback function to get that result like this
DbConnection: function(query,callback) {//pass callback as parameter
var connectInfo = [EnvConfig.getConnectionHostName(), EnvConfig.getConnectionPort()]; // Array of hostname and port
var connectHost = connectInfo.join(':'); // join hostname and port with ':'
var connectionAttr = [connectHost, EnvConfig.getConnectionSID()]; // hostname:port and SID
var connectString = connectionAttr.join('/'); // creating the connection string like 'hostname:port'
console.log(connectString);
// creating a oracle connection
oracledb.getConnection({
user: EnvConfig.getConnectionUserName(),
password: EnvConfig.getConnectionPassword(),
connectString: connectString
},
function(err, connection) {
if (err) {
console.log(err.message);
return callback(err);
}
connection.execute(
query,
function(err, result) {
if (err) {
console.log(err.message);
return callback(err);
}
console.log(result.rows); // I get result here
return callback(null,result.rows); // return result on success
}
);
}
);
}
And call like this
//Use your function with callback
getDbConnection(query,function(err,result){
if(!err){
console.log(result)
}
})
I am having trouble understanding node.js.
Example, MongoDB access, here's what I've got (mydb.js):
var mongodb = require('mongodb'),
server = new mongodb.Server('staff.mongohq.com', 10030, {
auto_reconnect: true
}),
db = new mongodb.Db('mydb', server);
function authenticateAndGo(db, handle) {
db.authenticate('username', 'password', function(err) {
if (err) {
console.log(err);
return;
}
console.log('Database user authenticated');
var collection = new mongodb.Collection(db, 'test');
handle(collection);
});
}
function query(handle) {
db.open(function(err, db) {
if( err ) {
console.log(err);
return;
}
console.log('Database connected');
authenticateAndGo(db, handle);
});
};
exports.query = query;
So, if I want to use it later, I would
var mydb = require('./mydb');
mydb.query(function(collection) {
collection.find({}, {
limit: 10
}).toArray(function(err, docs) {
console.log(docs);
});
});
But, If I do multiple calls, like so:
var mydb = require('./mydb');
mydb.query(function(collection) {
collection.find({}, {
limit: 10
}).toArray(function(err, docs) {
console.log(docs);
});
});
mydb.query(function(collection) {
collection.find({}, {
limit: 10
}).toArray(function(err, docs) {
console.log(docs);
});
});
I get an exception:
Error: db object already connecting, open cannot be called multiple times
I think that there is really something fundamental that I do not understand about all this and it is probable that this question is stupid ...
Anyway, all help is welcome.
Thanks in advance.
mydb.js:
var mongodb= require('mongodb'),
server = new mongodb.Server('staff.mongohq.com', 10030, {
auto_reconnect: true
}),
db1 = new mongodb.Db('mydb', server);
// callback: (err, db)
function openDatabase(callback) {
db1.open(function(err, db) {
if (err)
return callback(err);
console.log('Database connected');
return callback(null, db);
});
}
// callback: (err, collection)
function authenticate(db, username, password, callback) {
db.authenticate(username, password, function(err, result) {
if (err) {
return callback (err);
}
if (result) {
var collection = new mongodb.Collection(db, 'test');
// always, ALWAYS return the error object as the first argument of a callback
return callback(null, collection);
} else {
return callback (new Error('authentication failed'));
}
});
}
exports.openDatabase = openDatabase;
exports.authenticate = authenticate;
use.js:
var mydb = require('./mydb');
// open the database once
mydb.openDatabase(function(err, db) {
if (err) {
console.log('ERROR CONNECTING TO DATABASE');
console.log(err);
process.exit(1);
}
// authenticate once after you opened the database. What's the point of
// authenticating on-demand (for each query)?
mydb.authenticate(db, 'usernsame', 'password', function(err, collection) {
if (err) {
console.log('ERROR AUTHENTICATING');
console.log(err);
process.exit(1);
}
// use the returned collection as many times as you like INSIDE THE CALLBACK
collection.find({}, {limit: 10})
.toArray(function(err, docs) {
console.log('\n------ 1 ------');
console.log(docs);
});
collection.find({}, {limit: 10})
.toArray(function(err, docs) {
console.log('\n------ 2 ------');
console.log(docs);
});
});
});
Result:
on success:
Database connected
Database user authenticated
------ 1 ------
[ { _id: 4f86889079a120bf04e48550, asd: 'asd' } ]
------ 2 ------
[ { _id: 4f86889079a120bf04e48550, asd: 'asd' } ]
on failure:
Database connected
{ [MongoError: auth fails] name: 'MongoError', errmsg: 'auth fails', ok: 0 }
[Original Answer]:
You're opening the db multiple times (once in each query). You should open the database just once, and use the db object in the callback for later use.
You're using the same variable name multiple times, and that might've caused some confusion.
var mongodb = require('mongodb'),
server = new mongodb.Server('staff.mongohq.com', 10030, {
auto_reconnect: true
}),
db1 = new mongodb.Db('mydb', server);
function authenticateAndGo(db, handle) {
db.authenticate('username', 'password', function(err) {
if (err) {
console.log(err);
return;
}
console.log('Database user authenticated');
var collection = new mongodb.Collection(db, 'test');
handle(collection);
});
}
function query(handle) {
db1.open(function(err, db2) {
if( err ) {
console.log(err);
return;
}
console.log('Database connected');
authenticateAndGo(db2, handle);
});
};
exports.query = query;
I've changed the above code a little (db1 for the original db, db2 for the opened db). As you can see, you're opening db1 multiple times, which is not good. extract the code for opening into another method and use it ONCE and use the db2 instance for all your queries/updates/removes/...
You can only call "open" once. When the open callback fires, you can then do your queries on the DB object it returns. So one way to handle this is to queue up the requests until the open completes.
e.g MyMongo.js
var mongodb = require('mongodb');
function MyMongo(host, port, dbname) {
this.host = host;
this.port = port;
this.dbname = dbname;
this.server = new mongodb.Server(
'localhost',
9000,
{auto_reconnect: true});
this.db_connector = new mongodb.Db(this.dbname, this.server);
var self = this;
this.db = undefined;
this.queue = [];
this.db_connector.open(function(err, db) {
if( err ) {
console.log(err);
return;
}
self.db = db;
for (var i = 0; i < self.queue.length; i++) {
var collection = new mongodb.Collection(
self.db, self.queue[i].cn);
self.queue[i].cb(collection);
}
self.queue = [];
});
}
exports.MyMongo = MyMongo;
MyMongo.prototype.query = function(collectionName, callback) {
if (this.db != undefined) {
var collection = new mongodb.Collection(this.db, collectionName);
callback(collection);
return;
}
this.queue.push({ "cn" : collectionName, "cb" : callback});
}
and then a sample use:
var MyMongo = require('./MyMongo.js').MyMongo;
var db = new MyMongo('localhost', 9000, 'db1');
var COL = 'col';
db.query(COL, function(collection) {
collection.find({}, {
limit: 10
}).toArray(function(err, docs) {
console.log("First:\n", docs);
});
});
db.query(COL, function(collection) {
collection.find({}, {
limit: 10
}).toArray(function(err, docs) {
console.log("\nSecond:\n", docs);
});
});
I simply call the open function once directly after the db init:
var mongodb = require('mongodb');
var server = new mongodb.Server('foo', 3000, {auto_reconnect: true});
var db = new mongodb.Db('mydb', server);
db.open(function(){});
After that I do not have to care about that anymore because of auto_reconnect is true.
db.collection('bar', function(err, collection) { [...] };