JQuery phonegap app - compound database query string - javascript

I'm writing a quiz app using phonegap & jquery. I have a number of categories of question from which the user can select (via checkboxes), and want to build a database query to pull back the questions from the relevant categories based on their selection. The code below gives the gist of what I'm trying to achieve, but I cannot pass queryString into the executeSql() method. Is there a straightforward way of doing this that I'm missing? Thanks, Nick
function queryDB4(tx){
var queryString = "SELECT * FROM SBA_TABLE WHERE (";
if (toggle_cardiology == 1)
{
queryString += "cat_cardiology = 1 AND";
}
else if (toggle_respiratory == 1)
{
queryString += "cat_respiratory = 1"
}
// repeat for other categories
queryString += ") LIMIT 10;";
//alert(queryString);
tx.executeSql(queryString, [], querySuccess3, errorCB);
}

I think the problem is that your query string is invalid. Here's one example string that your code could produce:
SELECT * FROM SBA_TABLE WHERE (cat_cardiology = 1 AND) LIMIT 10;
There are a number of problems:
Append 1=1 (or any other statement that is always true) to handle the trailing AND.
Omit the else clause to allow combinations of checkboxes, not just the first one that is checked.
You need a space after AND to avoid producing ANDcat_respiratory.
Putting it together:
if (toggle_cardiology == 1)
{
queryString += "cat_cardiology = 1 AND ";
}
if (toggle_respiratory == 1)
{
queryString += "cat_respiratory = 1 AND ";
}
queryString += "1 = 1) LIMIT 10";

Related

Making a custom function in Google Sheets, the code works outside of sheets but not in sheets

So I'm writing a custom function for Google sheets which is supposed to take a single row or cells, produce a 1 dimensional array and use that data to create a URL. This is basically so I can help my friends track the prices of an item in a video game.
I have ran the code in a javascript environment outside of Google Sheets and everything acted as expected. But when I put the code in the script editor, it runs with unexpected behavior. The range of cells will always be 1 row by 13 columns but some of the columns may be void so the script is supposed to truncate the array of values so that there are no empty indexes. Then it is supposed to insert a "." between each value as it is concatenated into a string to produce the final URL. For some reason it does not remove any values and the "." are ","s when the URL is created in the cell.
Here is the code:
function STONKLINK(prices, premrkt) {
var webLink = "https://turnipprophet.io?prices=";
var priceLink = "";
for (i = (prices.length - 1); prices[i] == 0; i--){
prices.pop();
}
for (i = 0; i < prices.length; i++) {
priceLink = (priceLink + prices[i] + ".")
}
priceLink = priceLink.substring(0, priceLink.length - 1);
if (premrkt == "N/A") {
webLink = webLink + priceLink;
} else if (premrkt == "Fluctuating") {
webLink = webLink + priceLink + "&pattern=0";
} else if (premrkt == "Small Spike") {
webLink = webLink + priceLink + "&pattern=3";
} else if (premrkt == "Large Spike") {
webLink = webLink + priceLink + "&pattern=1";
} else if (premrkt == "Decreasing") {
webLink = webLink + priceLink + "&pattern=2";
}
return webLink;
}
Any help is very much appreciated. Thank you so much.
EDIT: While I still do not understand why this is happening, and I would like to understand, I have added a simple work around. By adding this line of code
webLink = webLink.replace(/,/g, ".");
before the return, all the commas will be replaced with dots. Still, any insight into the problem will be much appreciated. Thank you again.
When you store values in Spreadsheets, the values which have a , are considered to be strings whilst the ones which have a . will be considered to be numbers.
So for example, if you have these values stored in the B column:
If you log the typeof(val1) and typeof(val2) (where val1 and val2 are the values stored in B1 respectively B2), this is what you will get:
So the issue you were encountering is due to this fact. The values you have stored in your sheet are numbers and when you try to build the webLink string they are converted into strings - therefore, the . for a number becomes ,.
Reference
Date and Number Formats

Javascript SQLite for Cordova app - search using parameters where a string contains a substring case-insenstive

In my Cordova app, I need to query a SQLite database and select rows where the value of the column EventName contains a substring. I want to be able to use ? to hold values to avoid SQL injection. I tried this query:
SELECT * FROM EventName WHERE 1 = 1 AND lower(EventName) LIKE lower('%?%');
This is my JavaScript code that I use to query the database:
function searchEvent(onSearch, eventName) {
// First create the query string
var params = [];
var query = "SELECT * FROM Event WHERE 1 = 1";
if (eventName != null && eventName != "") {
query += " AND lower(EventName) LIKE lower('%?%')";
params.push(eventName);
}
query += ";";
console.log(query); // Log the query
console.log(params); // Log the parameters
// Then execute query statement
db.transaction(function(tx) {
tx.executeSql(query, params, function(tx, rs) {
onSearch(rs);
});
}, function(err) {
console.log(err); // This statement was executed
});
}
This is the logged query:
SELECT * FROM Event WHERE 1 = 1 AND lower(EventName) LIKE
lower('%?%');
This is the logged paramaters:
[ 'myInput' ]
This is the error the was returned:
{
code: 5,
messsage: 'number of \'?\'s in statement string does not match argument count'
}
As you can see there is 1 ? placeholder and 1 input parameter so the numbers DO match. I think it is because the ? is between the single quotes ('') so it is thought to be a part of the searched string. How do I fix this?
EDIT:
The JavaScript statement "SELECT * FROM Event WHERE 1 = 1" + " AND lower(EventName) LIKE lower('%" + eventName + "%')" is ok, but I wanna use a method that can protect me against SQL injection
In order to prevent the eventName from SQL injection, check it with regEx validation to include only alphanumneric and whitelist specific special characters /^[ A-Za-z0-9_#./#&+-]*$/. Also try this regEx /^[a-zA-Z0-9!##\$%\^\&*)(+=._-]+$/g. I do not believe that ? would work with SQL SELECT statement, so you need to pass +eventname+
Hope it helps.

check if a string array element is a sub string of a URL

I am working on a URL whitelist in a browser extension. What I have currently works but I need to check the list in two places and I want to try to make it more efficient so as to reduce the chances of increased page load times.
I have to check the list in two places. The first check is in a page mod with an attached content script which is applied to all sites, the content script is changed if the url is in the whitelist. The second check is in a request observer to send different headers if the url is whitelisted.
I have tried to only check it once and pass the result from the page mod to the requst observer or from the request observer to the page mod, it results in timing issues with either the headers not being correct or the modifictaions to the content script are not applied, when they should be.
Is there a way I can improve on the substring checking code below to make it faster
I have a list of user entered sites which are sorted alphabetically before saving.
For now the format of the list is simple.
example1.com
b.example2.com/some/content.html
c.exampleN.com
and the url could be
http://example1.com/some/site/content.html
I am currently checking the if the url contains a substring with the value of each array element
//check if a url is in the list
function listCheck(list,url){
for (var i=0; i<list.length; i++){
if (url.indexOf(list[i]) > -1)
return true;
}
return false;
};
You can use binary search with the first letter of the URL. This will come handy because whitelists can grow pretty fast. However you cannot do this with patterns. (e.g.: *.somedomain.com)
Consider about using a hashtable to store the whitelist. You can make it efficient and specialized by writing your own hash function.
Regex will make things easier, but will also make things slow at times. If you use regex, make sure you know what you are doing. You can shrink the comparison list first by one of the methods described above.
Edit: Here's the binary search I was talking about. This is applicable only if wildcards are not used.
function binarySearch(needle, haystack, startIndex, endIndex) {
//console.log("\ttrying to find " + needle + " between " +
// haystack[startIndex] + "(" + startIndex + ") and " +
// haystack[endIndex] + "(" + endIndex + ")");
// the basic case, where the list is narrowed down to 1 or 2 items
if (startIndex == endIndex || endIndex - startIndex == 1) {
if (haystack[startIndex] == needle)
return startIndex;
if (haystack[endIndex] == needle)
return endIndex;
return -1;
}
var midIndex = Math.ceil((startIndex + endIndex) / 2);
//console.log("\t\tgot " + haystack[midIndex] + "(" + midIndex +
// ") for middle of the list.");
var comparison = haystack[midIndex].localeCompare(needle);
//console.log("\t\tcomparison: " + comparison);
if (comparison > 0)
return binarySearch(needle, haystack, startIndex, midIndex);
if (comparison < 0)
return binarySearch(needle, haystack, midIndex, endIndex);
return midIndex; // (comparison == 0)
}
var sitelist = [ // the whitelist (the haystack).
"alpha.com",
"bravo.com",
"charlie.com",
"delta.com",
"echo.com",
"foxtrot.com",
"golf.com",
"hotel.com",
"india.com",
"juliet.com",
"kilo.com",
"lima.com",
"mike.com",
"november.com",
"oscar.com",
"papa.com",
"quebec.com",
"romeo.com",
"sierra.com",
"tango.com",
"uniform.com",
"victor.com",
"whiskey.com",
"xray.com",
"yankee.com",
"zulu.com"
];
function testBinarySearch(needle) {
console.log("trying to find " + needle);
var foundIndex = binarySearch(needle, sitelist, 0, sitelist.length - 1);
if (foundIndex < 0)
console.log(needle + " not found");
else
console.log(needle + " found at: " + foundIndex);
}
// note that the list is already sorted. if the list is not sorted,
// haystack.sort();
// we can find "uniform.com" using 5 comparisons, instead of 20
testBinarySearch("uniform.com");
// we can confirm the non-existance of "google.com" in 4 comparisons, not 26
testBinarySearch("google.com");
// this is an interesting (worst) case, it takes 5 comparisons, instead of 1
testBinarySearch("alpha.com");
// "zulu.com" takes 4 comparisons instead of 26
testBinarySearch("zulu.com");
When your list grows, binary search can scale very well. I would not go to other pros and cons of binary search since they are very well documented in large number of places.
More SO questions on JavaScript binary search:
Binary Search in Javascript
Searching a Binary Tree in JavaScript
Binary Search Code
Binary search in JSON object
javascript binary search tree implementation
Using a regexp will make things easier. Whit this code you just need to make ONE comparison.
function listCheck(list, url) {
var exp = new RegExp('(' + list.join('|') + ')');
if (exp.test(url)) return true;
else return false;
}
EDIT: you can get errors with symbols . or / or - in urls, so this code works better:
function listCheck(list, url) {
var exp = new RegExp('(' + list.join('|').replace(/(\/|\.|\-)/g, '\\$1') + ')');
if (exp.test(url)) return true;
else return false;
}

Concatenation of string in javascript

I'm looking to add to a string's value based on the output for multiple if statements but I don't seem to be having much success. I've declared comp_string="" at the beginning of the script then tried += so that for each condition that is true it adds a section on.
For the code example below if I submitted the value of www.facebook.com and www.twitter.com I would like comp_string to return 'fb=www.facebook.com&tw=www.twitter.com'
How would I go about concatenating/adding the string together and how do I add the & if more than one link is provided. I could add it to each string for any value thats not blank, but would an & on the end of the url with nothing following mess things up?
if (facebook_url != "") {
comp_string += "fb="+facebook_url;
}
if (twitter_url != "") {
comp_string += "tw="+twitter_url;
}
alert(comp_string);
A simple approach would be to add each string to an array, then join the array elements to produce the end result you are looking for.
var params = [];
if (facebook_url !== "") {
params.push("fb=" + facebook_url);
}
if (twitter_url !== "") {
params.push("tw=" + twitter_url);
}
alert(params.join("&"));
Reference

Javascript (and JSP) won't create table properly with if statement

So i'm using multiple if statements to draw data from a database based on the users search criteria.
What i'm struggling with is
if(request.getParameter("searchProperty")!= ""){
SearchStatement = "town_city = '" + request.getParameter("searchProperty") + "'";
if(request.getParameter("bedrooms") != "0"){
SearchStatement += " AND bedrooms = '" + request.getParameter("bedrooms") + "'";
}
}
with the idea that this concatenates a string to use as a query in the database, and bring back the results the user is searching for (this is a property searching website). I thought i'd done the if statement correctly. From what i understand, from what i've put, if the user were to select 0 in bedrooms it should return ALL results, but instead it returns NONE (who wants a house without a bedroom..) Can somebody explain what's going wrong please?
here's where the SQL statement is built and input
MyProperties = bookSQL.executeQuery("SELECT * FROM PROPERTIES WHERE " + SearchStatement);
with the expected outcome being, for example
SELECT * FROM PROPERTIES WHERE Location = 'input' AND Bedrooms = 'value'
unless value = 0 where it should just be
SELECT * FROM PROPERTIES WHERE Location = 'input'
i think the problem is with this statement,
request.getParameter("bedrooms") != "0"
should be something like this ,
(!request.getParameter("bedrooms").isEmpty())
Remember you are comparing the strings
so if is "0"
if(request.getParameter("bedrooms").equals("0")){
return SearchStatement ;
}
else {
SearchStatement += " AND bedrooms = '" + request.getParameter("bedrooms") + "'"
}
Hope this helps!!

Categories

Resources