So essentially I am using a transaction in my nodejs server with mysql to pull the first row and then delete that row from the table.
the code for this looks like:
app.get('/', (req, res) => {
connection.query("START TRANSACTION; SELECT * FROM data.train_data LIMIT 1; DELETE FROM data.train_data LIMIT 1; COMMIT;",(err,rows) => {
if(err){
console.log('Error selecting tweets from Database...');
return;
}
console.log('Successfully recieved tweets from database');
res.render('index', {
title: 'Tweet Labeler',
data: rows[1]
});
});
The problem is that even though the query is working correctly, when I reroute to the page in my client side javascript like this:
function relClick(){
var xhr = new XMLHttpRequest();
var newData = {'tweet':data[0].tweet,'relevant':1};
var jsonData = JSON.stringify(newData);
xhr.open("POST","/",true);
xhr.setRequestHeader('Content-type','application/json');
xhr.send(jsonData);
console.log("Clicked Relevant");
xhr = new XMLHttpRequest();
xhr.open("GET","/",true);
xhr.send();
nextItem();
}
I essentially want to repeat this process and grab the new top row from the table but by using print statements I have deduced that it is somehow not realizing that the row has been deleted even though when I use mysql workbench I can see the row has been deleted.
As you can see with this screenshot it continues to grab the row with the id 24 even though it has been deleted?
I am really confused on why this is. Hopefully someone with more experience can assist me because I am very new to this. Thanks in advance!
Related
I'm developing a mobile app and use the following command to build and run a version that works in a browser (pulling in all necessary hooks, which ionic serve does not)
ionic build browser --desktop --testing && http-server platforms/browser/www/
Yesterday, and for weeks, this works perfectly. I stop and start that same command, it builds/compiles everything, everything is great.
Then I updated Google Chrome. Now, no matter what I do, Chrome keeps pulling all of these resources from disk cache, even after I delete and re-create them. Any ideas how I can solve? I don't want to have to clear my cache out every time I reload, and it seems this'll cause additional issues down the road.
I don't know why or how this changed, no project or config settings are different in my Ionic2 app.
Using cmd-shift-R instead of just cmd-R to reload seems to force Chrome to not load from disk cache but I'm confused and want to understand what happened here...
Chrome caches a lot but you can force it to load resources from your server instead of taking them out of cache by using cache busting:
Load templates:
var timestamp = (new Date()).getTime();
$ionicPopup.show({
scope: $scope,
title: 'Work!',
templateUrl: '/templates/roll-timer-popup.html?update='+timestamp
});
Load scripts/stylesheets:
<script src="myscripts.js?update=123..."></script>
<link rel="stylesheet" type="text/css" href="theme.css?update=123...">
For script/stylesheets you might create them along with the timestamps dynamically and insert them afterwards.
Or when your scripts-files get bundelt together, you could use a script to write timestamps into your finally index.html file for deployment by using a nodejs-script, for I made this script for one of my projects:
const fs = require('fs');
var filename = process.argv[2];
var regExp = /[.|\w]+[.]js/;
var contentToAttach = ['<!-- CONTENT ATTACHED BY '+process.argv[1]+' -->','you can put other content in here that is put into at the end of your file'];
fs.readFile(filename, {
flag : 'r',
encoding: 'utf-8'
},(err, oldFileContent) => {
if (err) throw err;
var fileContent = oldFileContent;
var oldScriptName;
var now = (new Date()).getTime();
var lastIndexPos = 0;
while (oldScriptName = oldFileContent.match(regExp)) {
var newScriptName = oldScriptName + '?update=' + now;
var newIndexPos = fileContent.indexOf(oldScriptName);
if (newIndexPos !== lastIndexPos) {
fileContent = fileContent.replace(oldScriptName, newScriptName);
lastIndexPos = newIndexPos;
}
else {
// same filename found
var fildContentSlice = fileContent.slice(newIndexPos+oldScriptName.length);
fildContentSlice = fildContentSlice.replace(oldScriptName, newScriptName);
fileContent = fileContent.slice(0,newIndexPos+oldScriptName.length)+fildContentSlice;
}
oldFileContent = oldFileContent.replace(oldScriptName, '');
}
var wholeContent = fileContent+'\n\r'+contentToAttach.join('\n\r');
fs.writeFile(filename,wholeContent, (err) => {
if (err) throw err;
console.log('File: '+filename+' is updated!');
});
});
It inserts ?update=123... in every script-tag it can find in a file.
To execute this script in the shell write:
node updateScript.js path_to_your_html_file
Hope it helps.
I am using LocomotiveJS(MVC) based on ExpressJS for developing my first simple API.. I am still in learning phase.. I am using mysql as my database..
My question is, do i need to initiate a connection to mysql everytime there's a controller request?
Here's my code :
SongsController.show = function() {
//this.title = 'Locomotive';
console.log("nice imbasss");
var contacts = SongsModel.foo("GOOD");
var dbConnection = DBUtilities.connectMysql();
var contactsArr = [];
dbConnection.query('select * from contacts', function(err, rows, fields) {
//console.log(err);
console.log(rows);
//console.log(fields);
//contactsArr = rows;
});
DBUtilities.endMysql(dbConnection);
};
As you can notice, everytime songs/show is called, connectMysql() is called.. Am i doing right?
You should connect MySQL everytime when you fire a query to MySQL and should close your connection after that because mysql injection may occur by third party.
I am trying to end my mysql connection in my node program. I can successfully do that using something like connection.end(). However, when I do that it doesn't seem to run the queries before that. If I leave the end statement out my insert queries before this seem to run, however the program then hangs and it just never ends.
Here is my code
var mysql = require('mysql');
var connection = mysql.createConnection({'...'});
connection.connect(function(err){
});
for(var a=0; a<ticker.length;a++){
if(result[i].tweetText.indexOf(ticker[a]) > -1){
for(var j=0; j<positive.length;j++){
if((result[i].tweetText.indexOf(positive[j]) > -1) && check > -1){
console.log(result[i].tweetText + "\n")
plus++;
console.log(ticker[a] + "plus"+plus +"\n")
check = -1;
connection.query("insert into....", function(err, result) {
});
}
}
}
}
connection.end();
Having the end successfully terminates connection, but then all my insert statements do not run; when I remove the end connection statement, my insert statement runs but the program hangs.
You can do what I did and use a mysql pool. Store your connection settings in an object, create the pool using your config variable, and then pass around the con however you want, and then just grab the connection, query your db, and it takes care of everything for you. No hangups.
var db_config = {
user:"",
password:"",
database:"",
port:80
};
var con = mysql.createPool(db_config);
And then use the getConnection function to open and release the connection.
con.getConnection(function(err){
con.query("SELECT * FROM tableName",function(err,result) {
});
});
You can read more about pool connections via the github mysql source
According with documentation when you use conn.query, the connection automatically is open, so you don't need
connection.connect(function(err){
});
Answering your question, the problem is because when you insert into db, node doesn't wait for and continues with the loop. You can push the data into an array and after the loop you can insert bulk data. like this:
How do I do a bulk insert in mySQL using node.js
var bulk = data; //
connection.query("insert into table (columns) values ?", bulk, function(err, result) {
connection.destroy();
});
A simple question, I use nodejs for HTTP restful API service. Now I want query some mysql data before http server start, the code snippet:
var price = -1;
var userId = 'some user provided value';
var sql = 'SELECT max(price) FROM users WHERE id = ' + connection.escape(userId);
connection.query(sql, function(err, results) {
price = results.price;
});
server = http.createServer(function (request, response) {
handler(request); //response depend on price
}).listen(8012);
So how to combine mysql query and http server code?
Although this is a simple question the size of the answer is huge! Tim Ruffles gave a whole lecture on the subject at the London Node Users Group this week (July 2013) which is available as a video lecture [http://www.youtube.com/watch?v=nHXKA82M-LY].
The problem here is the fundamental one of how to handle something that needs to be done synchronously (in sequence) while working in an asynchronous (no order guaranteed) programming environment.
Of the list of ways Tim uses to deal with this problem there are three which seem to be able to help you here.
As suggested in other posts, you could use a callback from your code:
var price = -1;
var userId = 'some user provided value';
var sql = 'SELECT max(price) FROM users WHERE id = ' + connection.escape(userId);
connection.query(sql, function(err, results) {
price = results.price;
//start the server afer the sql connection has called back
server = http.createServer(function (request, response) {
handler(request); //response depend on price
}).listen(8012);
});
However this leads to what is called 'pyramid code' and can become unmanageable quite quickly.
My personal preference to solve this problem would be to use the async library [https://github.com/caolan/async]which contains an arsenal of tools for dealing with sequencing problems in node. I choose this because it seems the most intuitive way to me.
var async = require('async');
functon query(callback){
var price = -1;
var userId = 'some user provided value';
var sql = 'SELECT max(price) FROM users WHERE id = ' + connection.escape(userId);
connection.query(sql, function(err, results) {
price = results.price;
callback();
});
}
function boot(callback){
server = http.createServer(function (request, response) {
handler(request); //response depend on price
callback();
}).listen(8012);
}
async.series([query,boot]);
You can install async with npm install async.
Or the third approach that might reasonably be used for this problems is to use promises. These are well accepted, by while learning node coming from a language other javascript, I found this quite hard to adapt to coming from a language other then javascript, but programmers who use JQuery seem to favour this approach. There is a tutorial of how use promises in node.js here : http://howtonode.org/promises
Tim of course provides a much more in-depth analysis and comparison in his lecture of these approaches and supplies a few insights of how we might do this in the future.
You might also find the modules Express, Restify and Restler useful as a way to create a Restful api.
*disclaimer I haven't run this code as I don't have mysql installed - opportunity for an edit here :)
You just add the server inside of the return callback for the connection query, like so:
var price = -1;
var userId = 'some user provided value';
var sql = 'SELECT max(price) FROM users WHERE id = ' + connection.escape(userId);
connection.query(sql, function(err, results) {
price = results.price;
server = http.createServer(function (request, response) {
console.log(price);
handler(request, price, response); //response depend on price
}).listen(8012);
});
UPDATE
I discovered the issue is that it's blocked. Despite the database always being created and upgraded by the same extension, it does not get closed. So now I'm getting the "onblocked" function called.
How do I "unblock" currently blocked databases? And how do I prevent this in the future? This is an app, so no tabs are using it. And since I can't open those databases to even delete them (this also gets blocked), how do I close them?
(For anyone wondering, to avoid this issue from the start, you HAVE to do the folllowing:)
mydb.onversionchange = function(event) {
mydb.close();
};
Original Post
IndexedDB dies and becomes unopenable if I (accidentally) try to open and upgrade with the wrong version. As far as I can tell, there's no way to ask indexedDB for the latest version of a DB. So if I try to run the following code twice, it destroys the database and it becomes unopenable:
And it never throws an error or calls onerror. It just sits silently
var db = null;
//Note, no version passed in, so the second time I do this, it seems to cause an error
var req = indexedDB.open( "test" );
req.onsuccess = function(event) { console.log( "suc: " + event.target.result.version ); db = event.target.result; };
req.onerror = function(event) { console.log( "err: " + event ); };
req.onupgradeneeded = function(event) { console.log( "upg: " + event.target.result.version ); };
//We're doing in interval since waiting for callback
var intv = setInterval(
function()
{
if ( db === null ) return;
clearInterval( intv );
var req2 = indexedDB.open( "test", db.version + 1 );
req2.onsuccess = function(event) { console.log( "suc: " + event.target.result.version ); };
req2.onerror = function(event) { console.log( "err: " + event ); };
req2.onupgradeneeded = function(event) { console.log( "upg: " + event.target.result.version ); };
},
50
);
All of that code is in my chrome.runtime.onInstalled.addListener. So when I update my app, it calls it again. If I call indexedDB.open( "test" ) without passing in the new version and then again run the setInterval function, it causes everything to become unusable and I'm never able to open "test" again. This would be solved if I could query indexedDB for the version of a database prior to attempting to open it. Does that exist?
Maybe this helps?
function getVersion(callback) {
var r = indexedDB.open('asdf');
r.onblocked = r.onerror = console.error;
r.onsuccess = function(event) {
event.target.result.close();
callback(event.target.result.version);
};
}
getVersion(function(version) {
console.log('The version is: %s', version);
});
Ok, based on the convo, this little util function might set you on the path:
var DATABASE_NAME_CONSTANT = 'whatever';
// Basic indexedDB connection helper
// #param callback the action to perform with the open connection
// #param version the version of the database to open or upgrade to
// #param upgradeNeeded the callback if the db should be upgraded
function connect(callback, version, upgradeNeeded) {
var r = indexedDB.open(DATABASE_NAME_CONSTANT, version);
if(upgradeNeeded) r.onupgradeneeded = updateNeeded;
r.onblocked = r.onerror = console.error;
r.onsuccess = function(event) {
console.log('Connected to %s version %s',
DATABASE_NAME_CONSTANT, version);
callback(event.target.result);
};
}
// Now let us say you needed to connect
// and need to have the version be upgraded
// and need to send in custom upgrades based on some ajax call
function fetch() {
var xhr = new XMLHttpRequest();
// ... setup the request and what not
xhr.onload = function(event) {
// if response is 200 etc
// store the json in some variable
var responseJSON = ...;
console.log('Fetched the json file successfully');
// Let's suppose you send in version and updgradeNeeded
// as properties of your fetched JSON object
var targetVersion = responseJSON.idb.targetVersion;
var upgradeNeeded = responseJSON.idb.upgradeNeeded;
// Now connect and do whatever
connect(function(db) {
// Do stuff with the locally scoped db variable
// For example, grab a prop from the fetched object
db.objectStore('asdf').put(responseJSON.recordToInsert);
// If you feel the need, but should not, close the db
db.close();
console.log('Finished doing idb stuff');
}, targetVersion, upgradeNeeded);
}
}
I think it is best to provide the version number always. If you don't how are you going to manage upgrades on the db structure? If you don't its a good chance you will get in a situation where same db versions on a client will have an other database structure, and I don't think that is the thing you want. So I would suggest to keep the version number in a variable.
Also when working with indexeddb you will have to provide an upgrade plan from al previous versions to the current. Meaning version 4 has a certain structure, but you will have to be able to get that same structure from scratch as from version 1,2 and 3