Can someone show me a web SQL select query that returns the results as an object rather than alerting or logging to the console.
I want to centralize my select queries rather than repeating the select / execute and process results code in the specific functions.
If we presume that the question relates to the API required under Web SQL to execute the query and obtain a result set you can proceed as shown below. I've not given much detail as the question is a tad vague and shows little evidence of homework...
Initiate a readTransaction (you did say 'query' so I'll presume "select") on an open database:
db.readTransaction(onStartTransaction); // less locking overhead with a readTransaction
The onStartTransaction function looks like this:
function onStartTransaction(tx) {
tx.executeSql(sql, params, onExecuteSqlOk, onExecuteSqlFail);
}
Just pass your sql and a [] for params if you don't need any.
Your results will be returned to your 'onExecuteSqlOk' function:
function onExecuteSqlOk(tx, result) {
//
// tx: an SqlTransaction object
// results: an SqlResultSet object
//
The goodies are in the SqlResultSet object.
it has a structure with a 'rows' property. Each row contains the fields specified in the sql select statement.
var len = results.rows.length; // how many rows did we get
var firstRow = results.rows.item(0);
Thus you get an "object" back as the results from a Web Sql query. Note that the api shown is asynchronous so you will probably want to use a further callback function....
Related
I'm trying to make a MySQL query to filter data from a table. Effectively what I want to do is:
SELECT data FROM table WHERE column IN ?
The filter is coming from checkboxes in a form on a webpage, so I can pass an array or object fairly easily, but it'll be a varying number of parameters for the IN each time, so I can't us multiple ?. I tried making a for loop to make multiple queries concatenate the arrays that the queries returned, but I ran into scope issues with that. I also tried passing an array directly to the query, but that throws a syntax error. I'm sure there's a straightforward answer to this but I'm not sure how to do it.
Edit: source code added:
Here's where I'm at:
const filterShowQuery = `SELECT sl_Show.showId, sl_Band.BandName,
sl_Show.date, sl_Venue.venueName,
sl_Show.length, sl_Show.attendance, sl_Show.encore FROM sl_Show
JOIN sl_Band on sl_Show.BandID = sl_Band.BandId
JOIN sl_Venue on sl_Show.VenueId = sl_Venue.VenueId
WHERE sl_Band.BandName IN (?)
ORDER BY sl_Band.BandName;`;
Trying to get an array into the ? in WHERE sl_Band.BandName IN
const getShows = (req, res,next) =>{
var {bands, venues} = req.body;
var i = 0; //left over from previous attempt
var data = [];
for (b in bands){
mysql.pool.query(filterShowQuery, bands[b], (err, result) => {
if(err){
console.log('filter band error');
next(err);
return;
}
data = data.concat(result);
console.log(data); //data concatenates property and increases through for loop
})
// same action to be performed with venues once solved
// for (v in venues){
// conditions[i] = venues[v];
// i++;
console.log(data); //data is empty when logging from here or using in res
res.json({rows:data});
}
}
SECURITY WARNING!
I must to say: NEVER, NEVER PASS DATA DIRECTLY TO YOUR SQL!
If you don't know why, just google for SQL Injection. There are lots of examples on how it is done, how easily it can be done, and how to protect your application from this sort of attack.
You should always parametrize your queries. But in the very rare case which you really need to insert data concatenating a string into your sql, validate it before.
(E.g.) If it's a number, than use a Regex or some helper method to check if the value you are inserting into your SQL String is really and only a number and nothing else.
But aside that, you did not provide any source code, so it's really hard to give any help before you do that.
I am new in database systems and what I am trying to do is to check whether the e-mail entered by the user during login exists in the database or not. I use Firebase Databse. So, the code I have written is this:
function login(){
var e_mail = document.getElementById("e-mail").value;
rootRef = firebase.database().ref();
rootRef.orderByChild("E_mail").on("child_added", function(snapshot){
lst.push(snapshot.val().E_mail);
//console.log(lst);
})
console.log(lst);
}
let lst = [];
login_btn.onclick = function() {login()};
I want to fetch all e-mails from the database, add them in the list and then loop through that list. Maybe this is not the best way, but that's what I'm working on. I could also just say if (snapshot.val().E_mail == e_mail){alert("there is such a user");}but the problem I have encountered and want to deal with is not that, it's the "callback" function inside login function. When I console the list in the outer function it shows an empty list as it does not run the inner function until it is done with the outer one. I understand this. But how can I avoid or fix this. I want to get the full list of e-mails to be able to loop through it then. Also, I don't know how to end the "loop" in Firebase, because it is sort of looping when it gets the e-mails. So I would like to stop at the moment when it finds a matching e-mail.
You're downloading all users to see if one name exists already. That is a waste of bandwidth.
Instead you should use a query to match the email you're looking for, and only read that node:
rootRef.orderByChild("E_mail").equalTo(e_mail).once("value", function(snapshot){
if (snapshot.exists()) {
// A node with the requested email already exists
}
})
In general, if you need to process all nodes, you'll want to use a value event, which executes for all matching nodes at once. So to get all users from the database, add them to a list, and then do something with that list:
rootRef.orderByChild("E_mail").once("value", function(snapshot){
var list = [];
snapshot.forEach(function(childSnapshot) {
list.push(childSnapshot.val());
});
console.log(list); // this will display the populated array
})
Note that you won't be able to access the list outside of the callback. Even if you declare the variable outside of the callback, it will only be properly populated inside the callback. See Xufox' comment for a link explaining why that is.
I'm trying to query an API to get some data then I want to upsert all of it into my table.
But for some reason I'm not having any luck.
What's the best way to go about this?
I don't think my method of doing a query in a loop is best.
var coin = new Parse.Object.extend("Coins");
axios.get('https://api.coinmarketcap.com/v1/ticker/')
.then(response => {
let data = response.data;
// Put into database
data.map(entry => {
let q = new Parse.Query(Model.Coins.className());
q.equalTo('symbol', entry.symbol);
q.first()
.then(record => {
record.set('symbol', entry.symbol);
record.set('price_usd', entry.price_usd);
return record.save(null, {useMasterKey: true});
});
});
res.success(response);
});
you should avoid fetching and updating objects in a loop. In order to make it better you need to use 2 things:
In your query, instead of using equalTo and first you need to use containedIn for query all the records in one call. Then you need to iterate on the query results, for each record in the loop you need to do the following:
record.set('symbol', entry.symbol);
record.set('price_usd', entry.price_usd);
Finally you need to use saveAll to save all the objects in one call (please notice that saveAll is static function of Parse.Object and you should pass an array into it. Please review the docs before doing it)
Check your data. You may find you have unexpectedly updated records.
Assuming that's the entire body of a cloud function, your function initiates an asynchronous server call, then immediately tells the requestor that the operation was successful, but response isn't populated yet so you pass back undefined. However, parse-server will still run that asynchronous code.
The solution is to put the res.success call inside another .then chain, so the function won't return a response until after the server call + save finishes.
You're also going to get an uncaught error if the symbol doesn't exist on your table, though. You don't check to make sure the query returned a response to the first() call.
So I'm trying to go through one Firebase database to find entries in the database matching a criteria. Therefore I'm using the deferred object of jQuery to handle the database calls.
Once I get a return value from this first database I want to get the user info from a second database for each of those values in the first db. Then the results are added to a JSON array
so its:
<search for value, find one>
<<<search other db for oher info>>>
<continue search for outer value>
But this only returns one value - although everything else is running fine (and the console logs all the info correct).
Here's the code:
function find(searchLocation, profileID) {
var requestUserData = {
data: []
};
var def = $.Deferred();
//This will be executed as long as there are elements in the database that match the criteria and that haven't been loaded yet (so it's a simple loop)
Ref.orderByChild("location").equalTo(searchLocation).on("child_added", function(snapshot) {
def.ressolve(snapshot.val().ID);
});
return def.promise();
};
I hope you guys have any ideas on what to do or how I could solve this. Thanks in advance!
Edit: upon further testing I discovered that this problem already exists in the outer loop - so only the first value is being returned. I think this is related to the posission of the resolve() method but I didn't find a posibility on how to change this behaviour.
Firebase is a real-time database. The events stream as changes occur at the server. You're attempting to take this real-time model and force it into CRUD strategy and do a GET operation on the data. A better solution would be to simply update the values in real-time as they are modified.
See AngularFire, ReactFire, or BackboneFire for an example of how you can do this with your favorite bindings framework.
To directly answer the question, if you want to retrieve a static snapshot of the data, you want to use once() callback with a value event, not a real-time stream from child_added:
Ref.orderByChild("location").equalTo(searchLocation).once("value", function(snapshot) {
def.resolve(snapshot.val());
});
I was searching for an easy and simple database for a little highscore system for a some games I'm developing in javascript.
I saw Orchestrate.io in github's student developer pack. I found a suitable drivermodule nodejs orchestrate and have integrated them.
The problem comes with querying orchestrate for my data. I have managed saving scores and querying them with db.list('collection'), but this seems to not responding with all data. It appered to me that some values are not returned.
I read about the db.search('collection','query') function. But I don't really understand how I could return all data because I don't want to query in a specific way.
My objects are as simple as follows:
{"name":"Jack","score":1337}
As I understand, one has to send a key, when putting such values to an orchestrate-collection. But I'd like to query the whole collection and get the values in a descendant order in regard to the score.
As for now I end up sorting the result on the client-side.
I hope you guys can give me some hints for a query that can sort for specific values!
You have the option to use a SearchBuilder
db.newSearchBuilder() //Build a search object
.collection('collection') //Set the collection to be searched
.sort(score, 'desc') //Set the order of the results
.query("*") //Empty search
.then(function (res) { //Callback function for results
//Do something with the results
})
Source
By default, .list uses a pagination limit of 10. You can either increase that, e.g.:
db.list('collection', { limit: 100 })
Or use .links, .links.next (from the docs):
db.list('collection', { limit: 10 })
.then(function (page1) {
// Got First Page
if (page1.links && page1.links.next) {
page1.links.next.get().then(function (page2) {
// Got Second Page
})
}
})