I'm trying to create a query with variables from a map function, but the content stored in one of these fields does contain ' (quotes, like Barney's). So everytime it cracks since the ' will break the statement. How can I get around it?
I tried to use the .split function but no sucess.
No worries about SQL Injection since I'm just loading data from an API to my db.
Code:
query_values = activities.map do |activity|
'(' +
"#{activity['id']},
""'#{activity['type']}""'" #using ""' just to fill the column when empty cells are raised
+')'
end
query = "INSERT INTO pd_activities VALUES #{query_values.join(', ')}"
Thanks in advance.
How to do this properly is listed on the cheat sheet:
db[:pd_activities].insert(
id: activity['id'],
type: activity['type']
)
This takes care of all the escaping issues for you. If all activity has is those two keys you might even be able to do this:
db[:pd_activities].insert(activity)
Related
I have a problem which I have been trying to resolve since yesterday. I am trying to pass an SQL Query via $wpdb on wordpress but I keep getting an empty array when I try to echo the result.
I have tried print_r and var_dump and both are giving me empty values. I would appreciate if someone can help as I cannot seem to get this thing sorted.
I have also tried calling the table via the db prefix with still no success.
Below is the code I have been using
<?php
global $wpdb;
$results = $wpdb->get_results("SELECT CURRENT FROM upper_winds WHERE LVL=&level AND REGION=®ion AND VALID=&valid");
echo $results;
?>
P.S I have also tried get_var with the same problems.
Thanks
I noticed you weren't accounting for the wordpress database prefix, which could be why your results aren't showing up. You can prepend the prefix to your table name by using $wpdb->prefix.
I would suggest trying the following code:
global $wpdb;
$results = $wpdb->get_results("SELECT * FROM ".$wpdb->prefix."upper_winds WHERE LVL = 'level' AND REGION = 'region' AND VALID = 'valid'");
echo $results;
I also just wanted to point out that it's important to use $wpdb->prepare to protect against SQL Injection attacks. Any time you are writing your own SQL, you need to use $wpdb->prepare. However when you use methods like $wpdb->insert or $wpdb->update that don't require you to write any SQL, then you do not need to use $wpdb->prepare because those functions take care of SQL Escaping for you. I can't provide sample code without knowing which of your values are strings and which values are integers.
See: http://codex.wordpress.org/Class_Reference/wpdb#Protect_Queries_Against_SQL_Injection_Attacks
you need to prefix your table more than likely this is wp_ etc..
<?php
global $wpdb;
$results = $wpdb->get_results("SELECT * FROM `wp_upper_winds`
WHERE `LVL`='$level'
AND `REGION`='$region'
AND `VALID`='$valid'
");
var_dump ($results);
?>
you are looking for strings in your columns but using the &?
Thanks for your great advice and input. Eventually I got it to work.
The problem was not only in the code as I had been changing my code many times to try to find the solution. Eventually the main problem was nailed down to the table. Within one of the columns I had data which was something like this 'EU-VFR'. Apparently $wpdb did not pick up values with a '-'. Luckily with your help and some debugging I realised.
Here is what I got now http://howtoflyahelicopter.com/upper-winds-and-temp/
Thanks again :)
I'm using pg_search for some text searching within my model. Among other attributes, I have an url field.
Unfortuantelly Postgres doesn't seem to identify / and . as word separators, therefore I cannot search within the url.
Example: searching for test in http://test.com yields no results.
Is there a way to fix this problem, perhaps using another gem or some inline SQL ?
As stated in the documentation (and noticed by AJcodez), there is a solution in creating a dedicated column for tsvector index. Then define a trigger that catches insertions to index urls properly:
CREATE test_url (url varchar NOT NULL, url_tsvector tsvector NOT NULL);
This method will transorm any non alpha characters into single space and turn the string into a tsvector:
CREATE OR REPLACE FUNCTION generate_url_tsvector(varchar)
RETURNS tsvector
LANGUAGE sql
AS $_$
SELECT to_tsvector(regexp_replace($1, '[^\w]+', ' ', 'gi'));
$_$;
Now create a trigger that calls this function:
CREATE OR REPLACE FUNCTION before_insert_test_url()
RETURNS TRIGGER
LANGUAGE plpgsql AS $_$
BEGIN;
NEW.url_tsvector := generate_url_tsvector(NEW.url);
RETURN NEW;
END;
$_$
;
CREATE TRIGGER before_insert_test_url_trig
BEFORE INSERT ON test_url
FOR EACH ROW EXECUTE PROCEDURE before_insert_test_url();
Now, when url are inserted, the `url_tsvectorè field will be automatically populated.
INSERT INTO test_url (url) VALUES ('http://www.google.fr');
TABLE test_url;
id url url_tsvector
2 http://www.google.fr 'fr':4 'googl':3 'http':1 'www':2
(1 row)
To FT search on URLs you only need to query against this field.
SELECT * FROM test_url WHERE url_tsvector ## 'google'::tsquery;
I ended up modifying the pg_search gem to support arbitrary ts_vector expressions instead of just column names.
The changes are here
Now I can write:
pg_search_scope :search,
against: [[:title , 'B'], ["to_tsvector(regexp_replace(url, '[^\\w]+', ' ', 'gi'))", 'A']],
using: {tsearch: {dictionary: "simple"}}
Slightly simpler approach, add the protocol token type to the simple dictionary:
ALTER TEXT SEARCH CONFIGURATION simple
ADD MAPPING FOR protocol
WITH simple;
you can also add it to the english dictionary if you need stemming
https://www.postgresql.org/docs/13/textsearch-parsers.html
https://www.postgresql.org/docs/13/sql-altertsconfig.html
LuaSQL, which seems to be the canonical library for most SQL database systems in Lua, doesn't seem to have any facilities for quoting/escaping values in queries. I'm writing an application that uses SQLite as a backend, and I'd love to use an interface like the one specified by Python's DB-API:
c.execute('select * from stocks where symbol=?', t)
but I'd even settle for something even dumber, like:
conn:execute("select * from stocks where symbol=" + luasql.sqlite.quote(t))
Are there any other Lua libraries that support quoting for SQLite? (LuaSQLite3 doesn't seem to.) Or am I missing something about LuaSQL? I'm worried about rolling my own solution (with regexes or something) and getting it wrong. Should I just write a wrapper for sqlite3_snprintf?
I haven't looked at LuaSQL in a while but last time I checked it didn't support it. I use Lua-Sqlite3.
require("sqlite3")
db = sqlite3.open_memory()
db:exec[[ CREATE TABLE tbl( first_name TEXT, last_name TEXT ); ]]
stmt = db:prepare[[ INSERT INTO tbl(first_name, last_name) VALUES(:first_name, :last_name) ]]
stmt:bind({first_name="hawkeye", last_name="pierce"}):exec()
stmt:bind({first_name="henry", last_name="blake"}):exec()
for r in db:rows("SELECT * FROM tbl") do
print(r.first_name,r.last_name)
end
LuaSQLite3 as well an any other low level binding to SQLite offers prepared statements with variable parameters; these use methods to bind values to the statement parameters. Since SQLite does not interpret the binding values, there is simply no possibility of an SQL injection. This is by far the safest (and best performing) approach.
uroc shows an example of using the bind methods with prepared statements.
By the way in Lua SQL there is an undocumented escape function for the sqlite3 driver in conn:escape where conn is a connection variable.
For example with the code
print ("con:escape works. test'test = "..con:escape("test'test"))
the result is:
con:escape works. test'test = test''test
I actually tried that to see what it'd do. Apparently there is also such a function for their postgres driver too. I found this by looking at the tests they had.
Hope this helps.
The data what i have is
kiran#test.com - first record
kiran1#test.com - second record
I need to search using the email address. I have forums and users indexed in my web app.
First scenario
I kept the '#' symbol in the charset table which is working fine problem is for example if the search keyword as 'kiran#test.com' it is giving me the exact result but if i user only 'test' no results found.
Second scenario
If i won't keep '#' symbol in the charset table. If the i use 'kiran#test.com' i am getting both the results and for 'test' also i am getting both the results
Expected Scenario
If i use the entire email 'kiran#test.com' - I need to get only first record
If i use only 'test' - I need to get both the records
In plain mysql something like "select users where email like '%search-key%'"
I use the following code for searching
ThinkingSphinx.search params[:search_key],:star => Regexp.new('\w+#*\w+', nil, 'u') (I don't want to treat '#' as the separator)
Please suggest me any options i can pass to achieve the expected result.
Thanks
Kiran
Take a look at blended char support
http://sphinxsearch.com/docs/current.html#conf-blend-chars
Or if you really what [ email like '%search-key%'" ] style support maybe min_infix_len. (leaving . and # in charset table)
To search for full email you could use Phrase Search operator.
http://sphinxsearch.com/docs/current.html#extended-syntax
So, if you could determine search query as email use "phrase search" otherwise use general search.
I have the following query to one of my database tables:
select count(*) as mycount
from mytable
where fieldone = :fieldone
and fieldtwo = :fieldtwo
Parameters are correctly loaded into the query (both of type String).
When I run this query outside the app (for instance, through the dbexplore) and replace the parameters with the actual values, I get the correct result. But when running it in the app, I get a Field 'fieldtwo' not found error, right on the Query.Open call.
Why would the BDE not find this field, when it actually exist?
Update: The following query, executed right after the first one (the one that fails), works fine in the app:
select *
from mytable
where fieldone = :fieldone
order by fieldone, fieldtwo
The best guess is that you have populated the field list in the query, this overrides any concept of the underlying fields that are in the query and is a cause of countless confusion.
Right click on the query, pick the fields editor clear all the values that are there and then choose 'add all fields' that should cause the missing field to appear once the query is executed.
I think it should auto-populate the fields if there are no defined fields when the query is executed, so you may not need to choose 'add all fields' after clearing the fields.
Whenever we come across a problem like this we tend to remove the query from the form and create it dynamically at run time... It depends how ingrained into the form it is...
E.g. If you have a data aware control looking at "fieldtwo" which tries to fetch some data when the underlying data set gets updated then it'll trigger an error like this, but it's more obvious when you've written code such
SomeEdit.Text = Query.FieldByName("fieldtwo").AsString;
That way it falls over on the relevant line instead of the open (triggering a related event)
Clear the query content using Query1.SQL.Clear; statement before opening it.
Other reason can be you are opening other database which may not have the specified field. Be sure that both the DatabaseName's in your app and dbexplore are same
I used to face porblems with BDE when i have SQLExplorer open and the app accesses the DB at the same time (but i had errors like ), try closing the Explorer it may help, if not i would build the SQL as text without the Parameters and try if it works then (if its possible in your situation).
I don't use parameters, so I'm just grabbing at straws here. I still use the BDE regularly, but am no expert. I find I shy away from more complex expressions (which yours is not!) because of the little "surprises" like this that the BDE throws at you.
Perhaps adding parentheses:
where (fieldone = :fieldone)
and (fieldtwo = :fieldtwo)
Or, single or double quote signs (this probably will make it worse?)
where (fieldon = ":fieldone")
and (fieldtwo = ":fieldtwo")
Or, to explore the problem, remove the "and fieldtwo = :fieldtwo" line and see if it runs.
Would it be possible for you to do your own parameter substitution with a StringReplace as in
Query1.SQL.Text := StringReplace(Query1.SQL.Text, ":fieldone", "MyVarName",[rfReplaceAll ]);
If you are creating a ClienDataSet in memory by the Create DataSet method, you should check the TFieldDefs property, which must have a different field name or not created
I was having a weird but small problem, I'll post in case it will help someone in some day.
uRegPeople.pas
with frmEditPerson do
begin
PersonID := qryPerson.FieldByName(ID).AsInteger;
...
end;
I had qryPerson both in frmRegPeople and in frmEditPerson, by using with I was referencing to frmEditPerson.qryPerson, however I wanted to reference to frmRegPeople.qryPerson. Then I need to change to the following code.
with frmEditPerson do
begin
PersonID := Self.qryPerson.FieldByName(ID).AsInteger;
...
end;
// Explanation
// qryPerson --> frmEditPerson.qryPerson;
// Self.qryPerson --> frmRegPeople.qryPerson;