I have a Javascript program that is querying a MySQL table and I can't figure out why the results of simultaneous queries are not well handled.
There are multiple instances of an object, Zone. When instanciating the objects, I query the database to get some info.
My problem is that when I instanciate two objects at the same time, the result of the query of the first one is written in the second object.
I tried to create two different connections using a pool, but it doesn't change anything.
Here is my code :
Getter into database :
getOrdresAchat = function(aConnection, aIdZone, aCallback){
aConnection.query("SELECT * FROM Ordre WHERE Entreprise_idEntreprise = "+aIdZone+" AND Sens = 'Achat' ORDER BY Valeur DESC;", aCallback);
}
Objects definition :
//No need to check that object
Ordre = function(aNumero, aJoueur, aEntreprise, aSens, aTypeOrdre, aQuantite, aPrix, aBorneInf, aBorneSup) {
this.numero = aNumero;
this.entreprise = aEntreprise;
this.joueur = aJoueur;
this.sens = aSens;
this.typeOrdre = aTypeOrdre; // 'cours_limite', 'meilleure_limite', 'seuil_declenchement' ou 'au_marche'
this.quantite = aQuantite; // nombre entier positif
this.prix = aPrix; //si le prix est nul il est considéré comme sans limite
this.borneInf = aBorneInf;
this.borneSup = aBorneSup;
}
//kinda an array of Ordre
Carnet_achat = function() {
this.liste = [];
this.addElement = function(aOrdre) {
this.liste.push(aOrdre);
};
this.display= function(){
console.log("begining carnet_achat.display | List.length : "+this.liste.length);
for(i in this.liste){
console.log("row "+i+" : " +this.liste[i].prix);
}
};
}
Zone = function(aIdZone, aConnection) {
var idZone = aIdZone;
this.setIdZone = function(aNewId){
idZone = aNewId;
}
this.getIdZone =function(){
return idZone;
}
this.getCarnetAchat = function(aConnection){
rCarnet_achat = new Carnet_achat(); //rCarnet is temporary object
//we query database and push every row into the temp object
getOrdresAchat(aConnection, idZone, function(err, rows){
if(err) throw err;
for(i in rows){
ordreToAdd = new Ordre(rows[i].idOrdre,
rows[i].Joueur_idJoueur,
rows[i].Entreprise_idEntreprise,
rows[i].Sens,
rows[i].Type,
rows[i].Quantite,
rows[i].Valeur,
rows[i].BorneInf,
rows[i].BorneSup);
rCarnet_achat.addElement(ordreToAdd);
}
});
return rCarnet_achat;
}
//init
this.carnet_achat = new this.getCarnetAchat(aConnection);
}
main :
var mysql = require('mysql');
var pool = mysql.createPool({
host : 'localhost',
user : 'Bibacoeur',
password : 'Bibacoeur2014',
database : 'bibacoeur'
});
pool.getConnection(function(err, connectionA) {
if(err) throw err;
GI = new Zone(1, connectionA); //connection is used to query database
//timeOut to wait the end of the query
setTimeout(function(){console.log("GI_ACHAT");GI.carnet_achat.display();},3000);
});
pool.getConnection(function(err, connectionB) {
if(err) throw err;
GE = new Zone(2, connectionB); //connection is used to query database
//timeOut to wait the end of the query
setTimeout(function(){console.log("GE_ACHAT");GE.carnet_achat.display();},3000);
});
DATABASE :
mysql> select Entreprise_idEntreprise, Sens, Valeur from ordre;
+-------------------------+-------+--------+
| Entreprise_idEntreprise | Sens | Valeur |
+-------------------------+-------+--------+
| 1 | Vente | 0 |
| 1 | Vente | 90000 |
| 1 | Vente | 91000 |
| 1 | Vente | 92000 |
| 1 | Vente | 95000 |
| 1 | Vente | 100000 |
| 1 | Achat | 88500 |
| 1 | Achat | 90500 |
| 1 | Achat | 90500 |
| 2 | Achat | 0 |
+-------------------------+-------+--------+
10 rows in set (0.00 sec)
Result log :
C:\Users\QuentinB\Google Drive\Desktop\temp>node app.js
GI_ACHAT
begining carnet_achat.display | List.length : 0
GE_ACHAT
begining carnet_achat.display | List.length : 4
row 0 : 90500
row 1 : 90500
row 2 : 88500
row 3 : 0
It should be :
C:\Users\QuentinB\Google Drive\Desktop\temp>node app.js
GI_ACHAT
begining carnet_achat.display | List.length : 3
row 0 : 90500
row 1 : 90500
row 2 : 88500
GE_ACHAT
begining carnet_achat.display | List.length : 1
row 0 : 0
It seems that the result of the query done from the first object, GI, is received by the second object GE.
I tried to delay the creation of the second object with : setTimeout(function(){GE = new Zone(2, connectionB);},10); and it worked.
But I don't want to have to delay every creation, because I have 40 more objects to instanciate.
What can I do if I want to be sure the results of my queries are received by the right object?
Thanks for reading !
Since you're not declaring rCarnet_achat with the var keyword, you're implicitly declaring it as a global variable. So, each time you call rCarnet_achat.addElement(ordreToAdd);, you're actually adding elements to the same Carnet_achat instance. This could be fixed by adding var rCarnet_achat; to the top of the Zone function.
p.s. your code is riddled with other problems, e.g.
You should use node-mysql's query string escaping to avoid SQL injection attacks, e.g. aConnection.query("SELECT * FROM Ordre WHERE Entreprise_idEntreprise = ? AND Sens = 'Achat' ORDER BY Valeur DESC;", aIdZone, aCallback)
Using a setTimeout to wait for your SQL query to finish is wrong. Just wait for the callback.
Since you have "40 more objects to instanciate", you might consider writing a single query to fetch them all at once, e.g. select * from foo where id in (1,2,3);
Related
I'm deleting a row from a table based on the where condition, but I don't understand where I'm going wrong
I have a table TABLE1 as follows
-------------------------------
| DB | SC | TB | COLUMNS |
-------------------------------
| DB1 | SC1 | TB1 | COL1 |
| DB2 | SC2 | TB2 | COL2 | <-- Delete this row
| DB3 | SC3 | TB3 | COL3 |
-------------------------------
Here is my stored procedure
CREATE OR REPLACE PROCEDURE DEL(COL VARCHAR) // taking column name as parameter to delete that row
RETURNS string
LANGUAGE JAVASCRIPT
AS
$$
var str = '';
var stmt = snowflake.createStatement({sqlText: "DELETE FROM DATA_QUALIT WHERE COLUMNS = +COL+";"});
stmt.execute();
return str;
$$;
CALL DEL('COL2'); //Calling the procedure
But, I'm getting an error
Execution error in store procedure DEL: SQL compilation error: error line 1 at position 40 invalid identifier 'COL2'
I believe you are simply missing the single quotes around the value:
var stmt = snowflake.createStatement({sqlText: "DELETE FROM DATA_QUALIT WHERE COLUMNS = '" + COL +"';"});
the following gs code is working well
function getData00(e) {
var id = "SHEET_ID";
var sheetname = "SHEET";
var data = SpreadsheetApp.openById(id).getSheetByName(sheetname).getDataRange().getValues();
var ar = [];
data.forEach(function(f) {
if (~f.indexOf(e.color)) {
ar.push(f);
}
});
return ar;
}
So i can search in column for specific "color" value and get the corresponding row values.
Now i need to add another criteria to search also in another column and get the combined row values.
my spreadsheet:
Number | color | level | price | size | type
1 | red | first | 25 | 4 | local
2 | blue | third | 30 | 3 | global
3 | green | second | 40 | 6 | local
4 | blue | second | 60 | 5 | global
i need to search for "blue" in column B and for "local" in column F to get the matching rows values.
Result i am looking for:
2,blue,third,30,3,global
4,blue,second,60,5,global
HTML:
<html>
<body>
<p id="demo"></p>
</body>
</html>
<script>
function dispData(ar) {
document.getElementById("demo").innerHTML = ar;
}
function getData00(e) {
google.script.run.withSuccessHandler(dispData).getData00(e);
}
</script>
Thanks in advance and appreciate any help
Array.filter would be more appropriate:
function getData01(e) {
var id = "SHEET_ID";
var sheetname = "SHEET";
var data = SpreadsheetApp.openById(id)
.getSheetByName(sheetname)
.getDataRange()
.getValues();
return data.filter(row => [e.color, e.type].every(prop => row.includes(prop)))
}
You could use Array.filter to filter the source array to get the rows you want.
var matchingRows = data.filter(function(row){
// check if column B equals "blue" and column F equals "local"
return row[1] == "blue" && row[5] == "local";
});
Column B is in the 2nd place, which is the 1st index in the array for each row. Column F is in the 6th place, which is the 5th index in the array for each row.
I have Table (Employees) A:
+----+---------+
| ID | NAME |
+----+---------+
| 1 | ROBERT |
| 2 | JAMES |
| 3 | RICHARD |
| 4 | KANYE |
| 5 | DYLAN |
| 6 | JOHN |
| 7 | JEAN |
| 8 | LOKI |
| 9 | ADAM |
+----+---------+
And Table (Employees) B:
+----+---------+
| ID | NAME |
+----+---------+
| 1 | ROBERT |
| 2 | JAMES |
| 3 | RICHARD |
| 4 | KANYE |
| 5 | DYLAN |
+----+---------+
Those people are my "employees". The names from table B are all the employees on my database and the names from table A are all the employees that I've assigned to project n°1.
I would like to HIDE all names in Table B that already appear in Table A because I don't want to re-assign the same employee to project n°1.
How can I resolve this using jQuery?
a clientside check would be:
function compareLists(listA, listB){
var resultList = [];
listA.forEach(function(itemA){
listB.forEach(function(itemB){
if (itemB.name !== itemA.name)resultList.push(itemB);
}
}
return resultList;
}
or at the serverside (database):
select * from table_b where name not in (select name from table_a)
greetings
Normally you should do that on the server side using SQL as already answered. However, since you ask about javascript. This is the way to filter it at client side:
//collect list of names in A
var table = document.getElementById("TableA");
var names = []
for (var i = 0, row; row = table.rows[i]; i++) {
names.push(row.celss[1]);
}
//check names in B
table = document.getElementById("TableB");
for (var i = 0, row; row = table.rows[i]; i++) {
if(jQuery.inArray(row.cells[1], names) !== -1){
//show row
}else{
//hide row
}
}
I dont have that much knowlwdge in Jquery..
But this query increases perfomance in a large DB.
SELECT
FROM TableB
LEFT JOIN TableA ON TableB.name=TableA.name // id will be better than name
WHERE TableB.name IS NULL
Hope this helps
I'm trying to figure out how to create a nested JSON object, something like this:
company: "Company 1",
pricing: {
term: "1 year",
price: "$4.95",
term: "2 years",
price: "3.95"
},
I have two tables in MySQL, one called plans which is structured in this fashion
| id | company |
------------------
| 2 | company 1 |
and another table plans_pricing to represent the pricing data
| id | plans_id | term | price |
--------------------------------
| 1 | 2 | 1 year | $4.95 |
| 2 | 2 | 2 years| $3.95 |
I am using Laravel 4 to query the database and create json to send back to my ajax request. Here is the query, which is currently sending a server 500 error.
public function results()
{
$answers = $_POST['answers'];
$data = DB::table('plans')
->join('plans_pricing', 'plans.id', '=', 'plans_pricing.plans_id')
->select('plans.company', 'plans_pricing.price', 'plans_pricing.term')
->whereIn('plans.id', $answers)
->get();
echo json_encode($data);
}
I'm not sure why this query isn't working, but that isn't even why i'm asking this question. I need to know how to get a nested JSON object, when I create the join, I believe that I'll receive a separate object for each, like here:
| company | price | term |
------------------------------------
| company 1 | 4.95 | 1 year |
| company 1 | 3.95 | 2 years|
How can I make this SQL query return a nested JSON object like the one I describe above? I have been stuck on this problem for two days now and could really use some guidance. Thanks
UPDATE:
The server 500 error was fixed by changing echo json_encode to return Response::json($data);
I've never used Laravel but I think this should work:
$output = array();
$currentCompany = "";
foreach ($data as $datum) {
if ($datum->company != $currentCompany) {
$output[] = array();
// get a reference to the newly added array element
end($output);
$currentItem = & $output[key($output)];
$currentCompany = $datum->company;
$currentItem['company'] = $currentCompany;
$currentItem['rates'] = array();
}
$currentItem['rates'][] = array("price" => $datum->price, "term" => $datum->term);
}
json_encoded result:
[{
"company":"company 1",
"rates":[{
"price":4.95,"term":"1 year"
},{
"price":3.95,"term":"2 years"
}]
}]
Having a problem, which occurs in Firefox and Safari, but in Chrome it works fine.
This javascript array contains quiz questions, which I display one at at a time. However, sometimes not all records are iterated. I used the console, and it is definitely loading all questions, but still sometimes skips a record (usually only the first one).
EDIT: I have noticed that on quizes this array works for, all questionids are in order, i.e 290,291,293 in the array. But in in an example of one not working, the quiz id's are in this order, 286,285,287,288 and 285 is the one that is skipped, this could be part of the problem.
Here is my Javascript array code, please help me solve this problem.
var currentquestion;
jQuery.ajax({
url:"quizajax.php",
dataType: "json",
data: {
quizidvalue: <?=$thisquizid?>
},
}).done(function(data) {
questions = data;
for(i in data){
console.log(data[i]);
}
});
function nextQuestion (){
for(i in questions) {
if(i<=currentquestion)
continue;
currentquestion = i;
for(y in questions[i]) {
console.log("CurrentA: "+ currentquestion);
console.log("I: " + i);
console.log(questions[i][y].answerid);
}
console.log("CurrentQ: "+ currentquestion);
console.log("I: " + i);
console.log(questions[i]);
questionVariables ();
break;
}
Example code from db,
questionid | quizid | questiontype | qdescription | qfilelocation | noofanswers | answertype
------------+--------+--------------+------------------+------------------------------------+-------------+------------
285 | 55 | text | 6 answer text | null | 6 | text
287 | 55 | text | 4ans text q | null | 4 | text
289 | 55 | text | 2 answers text q | null | 2 | text
286 | 55 | text | 5 answer text q | null | 5 | text
288 | 55 | text | 3 answer text q | null | 3 | text
290 | 55 | image | image q and a | image/55/712013a88298585d415c.jpeg | 4 | image
291 | 55 | video | video q and a | video/55/8efa10195f0c20d1254f.mp4 | 4 | video
The continue statement is causing the loop to skip part of its execution.
Try debugging so see where code logic has the bug.
for(i in questions) {
if(i<=currentquestion) {
console.log('Skipping question: ' + i); // add debugging
continue;
}
...
EDIT: (several comments based on update)
Its best to iterate through arrays using traditional for loops:
for (var i = 0, len = questions.length; i < len; i++) {
But the outer loop isnt event needed
If you initialize var currentquestion = 0; the outer loop can be replaced
function nextQuestion (){
for(y in questions[currentquestion]) {
console.log("CurrentA: "+ currentquestion);
console.log(questions[currentquestion][y].answerid);
}
console.log("CurrentQ: "+ currentquestion);
console.log(questions[currentquestion]);
questionVariables ();
currentquestion++; //update here
}
It looks like your code depends on order, so you can sort
.done(function(data) {
questions = data;
questions.sort(function(q1,q2){
//assuming questionid is the correct property
if (q1.questionid < q2.questionid) {
return -1;
} else if (q1.questionid > q2.questionid) {
return 1;
}
return 0;
});
...
You could have used jquery.getJSON or $.ajax( { success ....})
You should probably reset currentquestion = 0; in your done method.