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.
Related
I'm having an issue getting a query to work.
I'm essentially trying to write something like the following SQL, with the literal 5 replaced with a variable:
SELECT *
FROM "my_table"
WHERE 5 BETWEEN "my_table"."minimum" AND "my_table"."maximum"
This is what I have at the moment:
MyModel.where(
Arel::Nodes::Between.new(
my_variable, (MyModel.arel_table[:minimum]).and(MyModel.arel_table[:maximum])
)
)
Please ignore the way I am using arel_table, the actual query has multiple joins and is more complex, but this is the most minimum reproducible example I have to demonstrate the problem.
The error, as in the subject of the question is as follows:
undefined method `and' for #<Arel::Attributes::Attribute:0x00007f55e15514f8>
and method is for Arel::Nodes::Node i.e. MyModel.arel_attribute[:name].eq(Arel::Nodes::Quoted.new('engineersmnky')) This is an Arel::Nodes::Equality and you can chain with and.
That being said you can construct an Arel::Nodes::And for yourself via
Arel::Nodes::And.new([left,right])
Then we can pass this to the Between class like so
Arel::Nodes::Between.new(
Arel::Nodes::Quoted.new(my_variable),
Arel::Nodes::And.new([
MyModel.arel_table[:minimum],
MyModel.arel_table[:maximum]])
)
The Arel::Nodes::Quoted (also: Arel::Nodes.build_quoted(arg)) is not needed in your case since your my_variable is an Integer which can be visited and will be treated as an Arel::Nodes::SqlLiteral but I find it best to let arel decide how to handle the quoting in case your my_variable ends up being some other un-visitable Object
There are other ways to create a Between and other ways to create an And depending on what objects you are dealing with.
between is a Arel::Predication and these predications are available to Arel::Nodes::Attribute objects e.g.
MyModel.arel_table[:minimum].between([1,6])
and as mentioned is available to Arel::Nodes::Node and instances of this class provides a convenience method (create_and) for creating an And so we could do the following:
Arel::Nodes::Node.new.create_and([
MyModel.arel_table[:minimum],
MyModel.arel_table[:maximum]])
There are a number of other ways to hack this functionality together by using other Arel classes but this should get you headed in the right direction.
i have the following delphi code:
FDQuery1.SQL.Clear;
FDQuery1.SQL.Add('SELECT * FROM :Tablename');
FDQuery1.ParamByName('Tablename').AsString := 'tasks';
ShowMessage(FDQuery1.sql.Text);
FDQuery1.Open;
(coppied from this link: http://www.delphigroups.info/2/da/237634.html)
it does not work because the parameter is not filled but stays the same.
does somebody know why it is not filled?
Because you cannot use parameters for table name substitution in SQL commands in general. You are lucky enough here though, FireDAC supports preprocessor macros to parametrize table names in SQL commands. So you can write for example this (note that if you want to see the command as you did in your code, it must be after macro preprocessing, that is e.g. after calling Prepare):
FDQuery1.SQL.Text := 'SELECT * FROM &TableName';
FDQuery1.MacroByName('TableName').AsIdentifier := 'tasks';
FDQuery1.Open;
For details about this kind of macros, see the substitution variables topic.
This works:
connection = get_connection()
cursor=connection.cursor()
cursor.execute('show application_name')
application_name_of_connection=cursor.fetchone()[0]
But why four lines? Is there no way to get this in one line?
No, there is not a way to do this in one line. Languages such as Python are designed to describe a set of instructions. There are four instructions here. There may even be helper methods or clever/inefficient arrangements of these statements that could lower this to three lines, but you are best to keep it how it is.
For example, if you are for some reason using this code frequently, you would encapsulate it in its own method
def get_application_name_of_connection()
connection = get_connection()
cursor=connection.cursor()
cursor.execute('show application_name')
return cursor.fetchone()[0]
And then simply:
get_application_name_of_connection()
This is how it works. You want less code? Hide the functionality.
It can be done with comprehension but on sqlite:
results = [row[0] for row in get_connection().cursor().execute('select * from mytable')]
If you are using postgresql then it doesn't work, you could try this for a more compact form:
with get_connection().cursor() as cur:
cur.execute('show all')
print cur.fetchone()
But only if you need the cursor thrown away after the block execution.
I didn't tried on other db managers, results may vary.
IC=IC
ACC=ACC
v_statement='ACC = '1052502',0.035,IC = 'IC130',0.0675'
v_decode_out=DECODE(TRUE,v_statement,0)
i am getting error
is the above expression correct.Is there anyway we can achieve this
There are two problems in your query
First, the v_statement variable you have written won't be validated. If you
really want to write a string in this format, then use pipes to append as
'ACC='||1052502||','||0.035||'IC='||'IC130'||','||'0.0675'
Note that you cannot loop quotes.
Second, the reason your decode statement wont work is because of the data type mismatch. True is a boolean value and v_statement is a string. Any variable expansion would happen during run time but not before that. So, informatica does not allow you this kind of decode statement, unless you are comparing some kind of string input/variable with another string or any other data type for that matter
Also, decide on your case
When it is If ACC else IC to be evaluated (this seems to be your case)
v_decode_out=DECODE(ACC,'1052502',0.035,DECODE(IC,'IC130',0.0675))
When it is both ACC and IC together
v_decode_out=DECODE(TRUE,ACC='1052502' and/or IC='IC130',0.035,0.0675)
These are fundamental concepts. It's advisable that you try out everything available on internet before you post a question here, because someone could easily down rate you if they feel that you have not put any effort at all to find an answer yourself.
Cheers!
the v_statement variable you have written won't be validated. If you really want to write a string in this format, then use pipes to append.
I have some code in Python that sets a char(80) value in an sqlite DB.
The string is obtained directly from the user through a text input field and sent back to the server with a POST method in a JSON structure.
On the server side I currently pass the string to a method calling the SQL UPDATE operation.
It works, but I'm aware it is not safe at all.
I expect that the client side is unsafe anyway, so any protection is to be put on the server side. What can I do to secure the UPDATE operation agains SQL injection ?
A function that would "quote" the text so that it can't confuse the SQL parser is what I'm looking for. I expect such function exist but couldn't find it.
Edit:
Here is my current code setting the char field name label:
def setLabel( self, userId, refId, label ):
self._db.cursor().execute( """
UPDATE items SET label = ? WHERE userId IS ? AND refId IS ?""", ( label, userId, refId) )
self._db.commit()
From the documentation:
con.execute("insert into person(firstname) values (?)", ("Joe",))
This escapes "Joe", so what you want is
con.execute("insert into person(firstname) values (?)", (firstname_from_client,))
The DB-API's .execute() supports parameter substitution which will take care of escaping for you, its mentioned near the top of the docs; http://docs.python.org/library/sqlite3.html above Never do this -- insecure.
Noooo... USE BIND VARIABLES! That's what they're there for. See this
Another name for the technique is parameterized sql (I think "bind variables" may be the name used with Oracle specifically).