ruby on rails prepared statement for oracle view/function - sql

I have the following code which executes an oracle view as follows:
def run_query
connection.exec_query(
"SELECT * FROM TABLE(FN_REQRESP(#{type_param},
#{search_type_param},
#{tid_param},
#{last_param},
#{key_param},
#{tran_id_param},
#{num_param},
#{start_date_param},
#{end_date_param}))")
end
The output of the above query is as follows:
SELECT * FROM TABLE(FN_REQRESP('ALL',
'ALL_TRAN',
'100007',
'',
'',
'',
'',
TO_DATE('27-January-2017','dd-MON-yy'),
TO_DATE('31-January-2017','dd-MON-yy')))
The problem is that above query has a SQL injection vulnerability.
So, i tried to add a prepare statement as follows:
connection.exec_query('SELECT * FROM TABLE(FN_REQRESP(?,?,?,?,?,?,?,?,?))','myquery',[type_param,search_type_param,tid_param,last_param,key_param,tran_id_param,num_param,start_date_param,end_date_param])
I get the following error now:
NoMethodError: undefined method `type' for "'ALL'":String: SELECT *
FROM TABLE(FN_REQRESP(?,?,?,?,?,?,?,?,?))
It's the single quotes that messing it up I beleive. Is there a way to overcome this?
EDIT:
I tried NDN's answer and the error below:
OCIError: ORA-00907: missing right parenthesis: SELECT * FROM TABLE(FN_REQRESP('\'ALL\'',
'\'ALL_TRAN\'',
'\'100007\'',
'\'\'',
'\'\'',
'\'\'',
'\'\'',
'TO_DATE(\'01-February-2017\',\'dd-MON-yy\')',
'TO_DATE(\'10-February-2017\',\'dd-MON-yy\')'))

Looking at the source, binds gets cast in some magical way and you have to pass a named prepare: true argument as well.
It also used to work differently in older versions.
To save yourself the trouble, you can simply use #sanitize:
params = {
type: type_param,
search_type: search_type_param,
tid: tid_param,
last: last_param,
key: key_param,
tran_id: tran_id_param,
num: num_param,
start_date: start_date_param,
end_date: end_date_param,
}
params.each do |key, param|
params[key] = ActiveRecord::Base.sanitize(param)
end
connection.exec_query(
"SELECT * FROM TABLE(FN_REQRESP(#{params[:type]},
#{params[:search_type]},
#{params[:tid]},
#{params[:last]},
#{params[:key]},
#{params[:tran_id]},
#{params[:num]},
#{params[:start_date]},
#{params[:end_date]}))"
)

This is called Prepared Statement. In doc you can find an example how to use it.

Related

Prisma PostgreSQL queryRaw error code 42P01 table does not exist

I am trying to run a query that searches items in the Item table by how similar their title and description are to a value, the query is the following:
let items = await prisma.$queryRaw`SELECT * FROM item WHERE SIMILARITY(name, ${search}) > 0.4 OR SIMILARITY(description, ${search}) > 0.4;`
However when the code is run I receive the following error:
error - PrismaClientKnownRequestError:
Invalid `prisma.$queryRaw()` invocation:
Raw query failed. Code: `42P01`. Message: `table "item" does not exist`
code: 'P2010',
clientVersion: '4.3.1',
meta: { code: '42P01', message: 'table "item" does not exist' },
page: '/api/marketplace/search'
}
I have run also the following query:
let tables = await prisma.$queryRaw`SELECT * FROM pg_catalog.pg_tables;`
Which correctly shows that the Item table exists! Where is the error?
After doing some light research, It looks like you possibly need double-quotes. Try
let items = await prisma.$queryRaw`SELECT * FROM "Item" ... blah blah
I say this because PostgreSQL tables names and columns default to lowercase when not double-quoted. If you haven't built much of your db, it may be worth wild to make all the tables and columns lowercase so that you won't have to keep adding double quotes and escaping characters.
References:
PostgreSQL support
Are PostgreSQL columns case sensitive?

Remove double quotes from query codeigniter 3

When I use the get() method in codeigniter I get following query as result:
SELECT * FROM "table_users" WHERE "mail" = 'test#test.com'
instead of:
SELECT * FROM table_users WHERE mail = 'test#test.com'
This causes it to not work correctly with Oracle 11g as the double quotes should not go with the table name.
I got the following error:
Error Number: 942
ORA-00942: table or view does not exist
SELECT * FROM "table_usuarios" WHERE "correo" = 'test#test.com'
Filename: C:/xampp/htdocs/Tecnologico/system/database/DB_driver.php
Line Number: 691
I solved it, at least temporarily.
Editing the file system/database/DB_driver.php
into the query() function we add the following line:
$sql = str_replace('"',"",$sql);
Just before the comment:
// Run the Query

How to print sqlite.swift statement as SQL?

I'm trying to debug some sqlite.swift statements that aren't delivering the results I expect.
The documentation shows examples of SQL in comments.
for user in try db.prepare(users.select(id, email)) {
print("id: \(user[id]), email: \(user[email])")
// id: 1, email: alice#mac.com
}
// SELECT "id", "email" FROM "users"
How do I get the statement to print that SQL?
print("\(users.select(id, email))") does not give me SQL. Am I overlooking something in the documentation?
If you want to see the SQL being executed then print(query.asSQL())
let query = dbTable
.filter(dbSourceKey == Int64(minElement))
.filter(dbTargetKey == Int64(maxElement))
print(query.asSQL())//Will show SQL statement
The following command will print all SQL statements:
db.trace(print)
See https://github.com/stephencelis/SQLite.swift/blob/master/Documentation/Index.md#logging

How to add a custom variable in a custom SQL call

I am trying to query against an array of strings. The me_topics_users table is an auto-generated table by Rails so to query it, I must use custom SQL.
#topics = self.distributions.map(&:me_topic).compact
ActiveRecord::Base.find_by_sql("SELECT * FROM `me_topics_users` WHERE (me_topic_id IN (#{#topics.join(', ')}))")
But this returns :
NoMethodError: undefined method `abstract_class?' for Object:Class
from /Users/macuser/Sites/hq_channel/vendor/rails/activerecord/lib/active_record/base.rb:2207:in `class_of_active_record_descendant'
from /Users/macuser/Sites/hq_channel/vendor/rails/ac
What am I doing wrong here?
Updated with Substitution but still get the same error
ActiveRecord::Base.find_by_sql(["SELECT * FROM `me_topics_users` WHERE (me_topic_id IN (?) )", #topics.join("', '")])
A simpler version:
ActiveRecord::Base.connection.execute(["SELECT * FROM me_topics_users WHERE me_topic_id= ?", '4'])
returns:
ActiveRecord::StatementInvalid: TypeError: wrong argument type Array (expected String): SELECT * FROM me_topics_users WHERE me_topic_id= ?4
from /Users/macuser/Sites/hq_channel/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:212:in `log'
from /Users/macuser/Sites/hq_channel/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:320:in `execute'
from (irb):51
from :0
you can use string replacement techniques as you can with ActiveRecord#find
find_by_sql(["SELECT * FROM `me_topics_users` WHERE (me_topic_id IN (?))",#topics.join(', ')])
ActiveRecord::Base.connection.execute("SELECT * FROM `me_topics_users` WHERE (me_topic_id IN ('#{#topics.join("', '")}') )")

dynamically set the db in a sql query

I try to run the same query in several dbs in mysql:
def m='xxx'
def dbs = ['DB05DEC05','DB06DEC06','DB07DEC07','DB08DEC08','DB09DEC09','DB10DEC10']
def sql =Sql.newInstance("jdbc:mysql://localhost:3306", "root","", "org.gjt.mm.mysql.Driver")
dbs.each{
db-> sql.eachRow("select * from ${db}.mail where mid=$m", { println "\t$db ${it.mid}"} );
}
This gives an error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''DBJAN05DEC05'.mail where mid='xxx'
Groovy apparently does some custom stuff with quotes and asks you not to use quotes in the sql (notice mid=$m, if you use mid='$m' it warns you against using the quotes).
The problem is that in the first $ I dont know want quotes at all, the quotes are the problem...
groovy 1.7 on vista.
thanks
editing: I have found a similar question, but it does not have an accepted answer either... Groovy GString issues
The problem is that the SQL query method sees the GString, with its embedded variable references, and turns each reference into a ? in a prepared statement.
So:
sql.query("select * from table where col = ${value}")
... is equivalent to:
sql.query("select * from table where col = ?", [ value ])
But also:
sql.query("select * from ${db}.table where col = ${value}")
is equivalent to:
sql.query("select * from ?.table where col = ?", [ db, value ])
... which fails at the DB layer because the select statement is not valid.
The obvious workaround is to use the explicit prepared statement version of query().
dbs.each{ db->
sql.eachRow("select * from ${db}.mail where mid=?", m, {
println "\t$db ${it.mid}"
});
}
However, the Sql class gives you an expand() method, that appears to be designed for this purpose.
dbs.each{ db ->
sql.eachRow(
"select * from ${Sql.expand(db)}.mail where mid=${m}",
{ println "\t$db ${it.mid}"} );
}