OrientDB function error when accessing query result - javascript

I have the following function in OrientDB studio, the functions saved with no problem:
var entities= db.query("select Name from F__Entity_Master");
getTemplate(0);
function getTemplate(index){
if (index >= entities.length){
return entities;
} else {
var sql = "select from F__Subjects where subjectCode='"+ entities[index]['#class']+"'";
var template = db.query(sql);
entities[index]['template']= template;
index += 1;
getTemplate(index);
}
}
Running the function in studio generates the following error:
Erroronparsingscriptatposition#0: ErroronexecutionofthescriptScript: GetEntities------^sun.org.mozilla.javascript.internal.EvaluatorException: Javaclass"com.orientechnologies.orient.core.record.impl.ODocument"hasnopublicinstancefieldormethodnamed"template".(#12)inatlinenumber12Javaclass"com.orientechnologies.orient.core.record.impl.ODocument"hasnopublicinstancefieldormethodnamed"template".(#12)
I used recursion to avoid using null values before fetching data from database. Using for loop generates similar error.
There are no relations between F__Subjects and F__Entity_Master as for every F__Subjects record a relevant class named with subjectCode field of F__Subjects record is generated and inherited from the F__Entity_Master. So the only way to detect relation is to use the subjectCode field to get the class meta information from he F__Subjects class.
Any ideas?
Solved
I used Lvca hint and here is the correct version of the function after few trials:
var entities= db.query("select from F__Entity_Master");
getTemplate(0);
return entities
function getTemplate(i){
if (i >= entities.length){
return ;
} else {
var sql = "select from F__Subjects where subjectCode='"+ entities[i].getClassName()+"'";
var template = db.query(sql);
entities[i].field('template', template[0].toMap());
i += 1;
getTemplate(i);
}
}

entities is an array of ODocument, so to get/set a field you should use respectively the field(name) and field(name,value) methods.

try field.getProperty()
this worked for me when writing functions in javascript for the orientdb server

Related

How to get the callback return value in sqlite3 in node.js?

function resumeID() {
let searchSQL = `SELECT * FROM students ORDER BY id DESC`;
db.get(searchSQL, (err, row) => row);
}
I am a newbie in javascript and I use sqlite3 in nodejs. I want to use the variable "row"(as shown in the code) as the return value of the function "resumeID". Is there any way to do that?
Note: the db variable is an database object created with new sqlite3.Database()
Well, actually I solved this problem by using another package called sqlite. It provides easy-to-use promise features. Now the function is as below.
async function resumeID(db) {
let searchSQL = `SELECT * FROM students ORDER BY id DESC`;
return ((await db.get(searchSQL)).id += 1);
}

How do I reject writing value to Firebase if have the same value in my DB? (Javascript)

I'm creating my custom order id with auto-increment generator function for my project. I will state my question here, if you want to know the whole story please read below.
As written in the title, I need a way to reject my set to Firebase and it has to be done in 1 query. Currently, it will write my orderID to Firebase without rejecting it. But I need to reject if there is the same ID in the table.
The short version of my code will be posted here, the whole function will be posted below.
firebase.database().ref('orderCounter/orderIDsChecker/'+orderID).set({
id: orderID,
}, function(error) {
if (error) {
console.log('Order ID fail to generate. Regenerating new ID')
createOrderID(orderCounterRef);
} else {
console.log('Order ID created!')
}
});
}
The story,
I'm creating my own custom order id with auto-increment generator function for my project. The problem is that if multiple users creating order at the same time, it will generate the same id. Yes, I can use transaction() to solve the problem but I have no idea how to use it. Therefore, I have created my own version of the "transaction". With my method, I am able to prevent duplicates id unless 2 or more users create order within 1 second of gap. Or if anyone is kind enough to show me an example of how to write a transaction for my function, I thank you in advance.
The flow of the code is,
Get "currentMonth" and "orderIdCounter" from Firebase -> orderIdCounter +1 and update to Firebase -> start the process of generating order id -> Send the generated id to firebase -> If return success "order ID created", If not "got duplicate id" Re-run the whole process.
Below is the code for my order id generator function.
function createOrderID(orderCounterRef){
var childData = [];
var orderID;
//Get the Current Month and Order ID Counter from Firebase
orderCounterRef.on('value', function(snap) { childData = snapshotToArrayWithoutID(snap); });
var currentMonth = childData[0];
var orderIDCounter = childData[1];
if (orderIDCounter !== undefined){
//Update orderIDCounter on Firebase.
//This is to prevent duplicate orderID when multiple users is creating order at the same time.
var IDCounter = parseInt(orderIDCounter) + 1;
//Set IDCounter to 3 digits
IDCounter = ('00' + IDCounter.toString()).slice(-3);
firebase.database().ref('orderCounter/orderIDCounter').set(IDCounter);
//Handle the process to generate Order ID. Return in YYMMxxx(auto increment) format.
orderID = handleCreateOrderID(currentMonth, (parseInt(orderIDCounter) - 1));
//Check if duplicate ID on firebase
firebase.database().ref('orderCounter/orderIDsChecker/'+orderID).set({
id: orderID,
}, function(error) {
if (error) {
console.log('Order ID fail to generate. Regenerating new ID')
createOrderID(orderCounterRef);
} else {
console.log('Order ID created!')
}
});
}
return orderID;
}
My DB:
You should indeed use a transaction as you have mentioned in your question.
The following should do the trick:
//Declare a function that increment a counter in a transaction
function createOrderID() {
var orderIdRef = firebase.database().ref('orderId');
return orderIdRef.transaction(function(currentId) {
return currentId + 1;
});
}
//Call the asynchronous createOrderID() function
createOrderID().then(function(transactionResult) {
console.log(transactionResult.snapshot.val());
});
If you want to start the counter at a specific value, just create an orderId node in your database and assign a specific value to it, e.g; 1912000.
If you just want to start at 1, you don't need to create a node, it will be automatically created with the first call to the createOrderID() function.
Thank you, #samthecodingman & #Renaud Tarnec for your advice.
I took #samthecodingman's code and change a bit to fit my project. But I use generateOrderID() only to call the result and it works well. But you won't get any value with just the code. I call out another function (connectToFirebase) whenever users enter the page. I am not sure why it works or if this is the right way, but it works for me and that's good enough.
export function generateOrderID(){
var orderId;
var childData = [];
const orderCounterRef = firebase.database().ref('orderCounter/');
//Get the Current Month from Firebase
orderCounterRef.on('value', function(snap) { childData = snapshotToArrayWithoutID(snap); });
//Check ID format YYMMXXX (XXX=auto_increment). Hanlde auto_increment for Year and Month
handleOrderIdFormat(childData[0], orderCounterRef)
//transaction
orderCounterRef.child('orderId').transaction(function(currentId) {
orderId = (currentId||0) +1;
return orderId;
}, function(err) {
if( err ) {
console.log(err)
}
});
return orderId;
}
export function connectToFirebase(){
//Connection Firebase Database
const orderCounterRef = firebase.database().ref('orderCounter/');
orderCounterRef.on('value', function(snap) { });
}

kendo grid template js with remote datasource

I got a table with remote datasource. in one cell I got the userID. Because I want to show the username instead of the user ID I made a custom template function:
function getUserName(pmcreator){
var user = '';
var data = ''
ds_userList.fetch(function(){
var data = this.data();
for(var i = 0, length = data.length; i < length; i++){
if(data[i].uID == pmcreator){
console.log(data[i].uLastname)
user = data[i].uLastname
}
}
});
return user
}
But its not working as it should, the cells stay empty. I got no errors but I see that the remote request to fetch the usernames is not completed before the grid is filled out. I thought the custom function of fetch is waiting for the results to return but it don't seems so.
Any Idea? I find thousends of examples but all with static local data. I need one with both remote, the grid conent and the template data.
This is probably due the fact that when yuo call the dataSource.fetch it fires off an async function, which causes the thread running the template to continue on. According to kendo you will need to return a control, then set the content of that control inside the callback.
Quick sample using Northwind categories...
Here is the template function
function getDetails(e) {
$.getJSON("http://services.odata.org/V3/Northwind/Northwind.svc/Categories", null, function(data) {
var category = data.value.filter(function(item, i) {
return item.CategoryID === e.CategoryID;
});
$("#async_" + e.CategoryID).html(category[0].Description);
});
return "<div id='async_" + e.CategoryID + "'></div>";
}
http://jsbin.com/ODENUBe/2/edit
I kept getting a recursive error maximum call stack when I just tried to fetch the dataSource, so I switched to a simple getJSON, but it should work pretty much the same.

Inserting multiple values in Mysql using Nodejs and notifying user with a response

I am making a new webservice where i send a curl command with JSON and the JSON contains a array as
[{tempid:1,email:abc#123,address:asd},{tempid:2,email:abc#12345,address:asd45},{tempid:3,email:abc#1234,address:asd4}]
Now when i pass and insert the array in a mysql table tempid is just to show a mapping to the user to the contact id generated in the database as tempid:1 is now inserted and in database it has cid 120 , like this for tempid2 and 3 ,
But when i am trying to show the client the updated values it shows only one value , last last change not the whole updated Array. Its becuase of the async nature of the connection.querry function , so i need help in this , here is my webservice
contactadd webservice -->
for(var i=0;i<=request.body.contact.length-1;i++)
{
if(request.body.contact[i].tempid)
{ var ardata=new Array();
var o=request.body.contact[i];
pair=Object.keys(o).map(function(a){ return [a, o[a]] });
AM.addcontact(pair,request.session.user,request.body.contact.length,function(e,o){
if(!o)
{
response.send('something went wrong'+e);
}
else
{
//response.send(o);
}
});
}
}
Here is the update function in the database.js script -->
//ContactSync-addcontact module for database
exports.addcontact=function (arr,email,addnum,callback)
{
var counter=0;
var uid;
var data=new Array();
var showinsert=new Array();
var values=new Array();
var datatable=new Array();
var inserting=new Array();
var tempid=0;
connection.query('SELECT UID FROM user where email1="'+email.email+'"',function(err,rows,fields){
if(err)
{
throw err;
}
else
{
if(rows[0]!=undefined)
{
uid=rows[0]['UID'];
}
else
{
uid="no id in database";
}
}
});// get the UID of the inserting user
// make array of user provided data
for(var j=0;j<=arr.length-1;j++)
{
if(arr[j][0]!='tempid')
{
data.push(arr[j][0]);
}
else
{
tempid=arr[j][1];
}
}
connection.query('SELECT column_name FROM information_schema.columns where table_schema="webservice" AND table_name="usercontacts"',function(err,rows,fields){
if(err)
{
throw err;
}
else
{
for(var i=0;i<=rows.length-1;i++)
{
datatable.push(rows[i]['column_name']);
}
}
for(var k=0;k<=datatable.length-1;k++)
{
if(inArray(data[k],datatable))
{
inserting.push(data[k]);
}
}
if(inserting.length>0)
{
for(var z=0;z<=arr.length-1;z++)
{
if(inArray(arr[z][0],inserting))
{
values.push('"'+arr[z][1]+'"');
}
}
// Insert tempid values and data in the usercontacts table with inserting and values
connection.query('INSERT INTO usercontacts (cid,uid,'+inserting+') VALUES("","'+uid+'",'+values+')',function(err,rows,fields){
if(err)
{
throw err;
}
else
{
connection.query('SELECT * FROM usercontacts WHERE uid="'+uid+'" ORDER BY cid DESC LIMIT 0,'+addnum+'',function(err,rows,fields){
if(err)
{
throw err;
}
else
{ showinsert.push('temp-id: '+tempid+',cid:'+rows[0].cid+',uid:'+uid);
//for(var i=0;i<=inserting.length-1;i++)
forEach(inserting,function(row,index)
{
showinsert.push(inserting[index]+":"+values[index]);
counter+=1;
});
callback(null,showinsert);
}
});
}
});
//insertion finished
}
else
{
callback("Please Provide atleast one field to enter with tempid");
}
});
}
I just need to insert all the callback in a array which has been inserted and show user that array ,please help , completely stuck and then only i am trying StackOverflow.
Thank you for reading till the end BTW
I'm not sure what the specific problem is, but there are some problems with the code you've shared that will bite you sooner or later. One of these may be causing your problem.
Race conditions
If the query SELECT UID FROM user where email1= for any reason takes longer than the SELECT column_name FROM information_schema.columns just below it then you won't have a value for the variable uuid and your logic will fail. Remember that these calls are non-blocking, so you can't rely on one finishing before the other one unless they're nested or use another flow-control mechanism (As #Tracker points out, async is popular).
Catching edge cases
In the line below you're assigning a string value to the uid variable and then continuing to use that variable even though it now contains an error message.
uid="no id in database";
Doing that means that your code later on will have trouble reacting. Instead use a different variable, leave the uid = undefined or immediately return the callback with an error, e.g.
return callback(new Error("user not found"));
Reporting errors
Don't throw errors in Node unless you want to kill the process, e.g. dependency problems during server startup. It doesn't work like Java, async errors are not caught by try/catch and will kill your process or leave you in a state that's hard to reason about. Instead make the error object your first parameter to the callback and return it immediately, like this:
if ( err ) return callback(err);
Then in your client code you can always check the first parameter to see if there was a problem.
Security problem
As #Tracker mentioned, don't ever do the this:
connection.query('SELECT UID FROM user where email1="'+email.email+'"', ...
If the value of the variable is passed through as "; drop table user; or similar then you're in trouble. Instead you can use node-mysql's build in escaping like this:
connection.query('SELECT UID FROM user where email1=?', [email.email], ...
Whitelist
You're querying information_schema.columns in order to detect which fields are valid then inserting them into usercontacts. This is a clever trick, but increases a 3 query process to 4 queries, and raises questions if there are any fields that a user shouldn't be inserting data into. Using a column whitelist may seem like more code to maintain, but would actually be simpler than all the code required to match columns dynamically.
Arrays
I don't see the source for the function inArray() but it looks like it does the same as Array.prototype.indexOf() so it may be better to use that. e.g.
if ( datatable.indexOf(data[k]) > -1 ) inserting.push(data[k]);
Every line of custom code you can delete is a line of code you don't have to maintain.

Re-write Async JS process (Possibly to use JQuery Promise)

I am having trouble with two functions because they rely on chaining Async Tasks. The clearAll is a click event which should empty the database then reload the page. Clear is a function from the database module (database.clear).
I would like to use JQuery Promises/Deffered if they are appropriate but I cant quite grasp them for this use case.
I have re-written the code following #Larry K's answer
clearAll: function()
{
var refresh = function()
{
localStorage.clear();
sessionStorage.clear();
window.location.href = window.location.pathname;
console.log("feeling refreshed");
};
database.open();
//This is what I'd like to be able to do
//With Jquery or callbacks
$.when(database.clear()).then(refresh);
},
clear: function (callback, errorCallback)
{
var sql = "SELECT name FROM sqlite_master WHERE type='table' AND name != ?",
args = ["__WebKitDatabaseInfoTable__"];
var dbTableNamesResult = function (tx, result)
{
var dropSql = "";
for (var i = 0; i < result.rows.length; i++)
{
dropSql = "DROP TABLE IF EXISTS " + result.rows.item(i).name + "; ";
execute(dropSql);
}
};
execute(sql, args, dbTableNamesResult);
},
The big issue is that you have two layers of callbacks including a loop for the second layer.
You're using the db to queue multiple drop table calls since you're immediately calling many database.dropTable methods (without waiting for the prior one to complete.)
That's fine but an easier way to solve the problem is to drop all of the tables at once. The SQLite manual says that multiple table drop sql statements are supported. But you'd probably want to test it.
It appears that you're using a wrapper library around the sql calls, yes? Use the appropriate call for the execSQL method shown in my code.
Also, your refresh function is being called both for success and failure of the drop table statement. AFAIK, you're never going to call your errorCallback. I'd try:
var clearDatabase = function (successCallback, errorCallback) {
var dbTableNamesResult = function (tx, result) {
var sql1 = '',
rows = result.rows;
for (var i = 0; i < rows.length; i++) {
sql1 = sql1 + " DROP TABLE " + rows.item(i).name + ";";
}
//now make one call to drop multiple tables...
database.execSQL(sql1, successCallback, errorCallback);
// pseudo function, update as appropriate
}
database.open();
database.query(
"SELECT name FROM sqlite_master WHERE type='table' AND name != ?",
['__WebKitDatabaseInfoTable__'], dbTableNamesResult);
};
added
The function which calls clearDatabase should provide both the successCallback and errorCallback. In case of error, either try again or just log it...
updated
I see that that the successCallback and errorCallback functions can be called directly by the db. Updated the code.
Resources used in this answer
HTML5 Rocks: Client-Side Storage
Getting Started with HTML5 Local Databases
SQLite SQL As Understood By SQLite
Having attempted to implement jQuery deferred myself the answer I was looking for was provided by zerkms's answer to How can I write this as a jQuery deffered function

Categories