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("', '")}') )")
Related
Say I have a class variable restemail which stores the email id I need to use to sort out from the select statement in SQLite (Python). Whenever I refer to that variable after my WHERE clause, SQLite treats it as a column and returns an error saying that such a column doesn't exist. Something like this:
restemail=StringVar()
Password=StringVar()
def database(self):
conn = sqlite3.connect('data.db')
with conn:
cursor=conn.cursor()
strrest = self.restemail
cursor.execute('SELECT * FROM Restaurant3 WHERE restemail = strrest')
Can someone tell me how to use a variable inside my SQL queries without it being treated as a column name?
Any help will be appreciated.
Try the sqlite3 variable substitution syntax:
cursor.execute('SELECT * FROM Restaurant3 WHERE restemail = ?', (strrest,))
How do I exactly write the following query using entityManager.
Select * from TABLE_NAME where column_name in ('A', 'B');
I tried with the setParametrList() method. However, it says that this method is not available for type Query.
Query query = entityManager.createQuery(
"Select t from TableEntity t WHERE t.name =:bd AND t.staus in (:statuses)", TableEntity .class)
.setParameter("bd", bd)
.setParameterList("statuses", statuses);
Error: The method setParameterList(String, List<String>) is undefined for the type TypedQuery<TableEntity >
The same method seems to work fine while using session.createQuery. Any suggestions on this.
Just use setParameter("statuses", statuses) with the list. The method checks if the parameter is a collection and expands it.
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.
I am running this hibernate query from my java class.But i am getting QuerySyntaxException.But i didnt find any thing went wrong.
Query
SELECT count(contact.id)
FROM Contact contact
WHERE contact.id IN (
SELECT DISTINCT action.contact
FROM Action action
WHERE action.status = 'O'
AND action.currentAssignee = :currentAssignee)
AND contact.contactStatus IN :contactStatus
AND CAST(contact.id as char(12)) like :id --Note this line
AND contact.issue.productGroup IN :productGroup
But the problem is in using CAST.
The error is :
expecting CLOSE, found '('
Error While getting countOpenContacts. java.lang.IllegalArgumentException: org.hibernate.hql.ast.QuerySyntaxException: expecting CLOSE, found '('
The following java code has been used to set the id.(contact.id is Long value and contactId is string.)
query.append("AND CAST(contact.id as char(12)) like :id ");
params.put("id",(contactId+ "%"));
Can we CAST in hibernate query?
As documentation says, we can use
cast(... as ...), where the second argument is the name of a Hibernate type
So you should try
AND CAST(contact.id as string) like :id
I've been trying this for a while, and can't seem to get it right in Activerecord.
Given an array of asset_id and asset_type pairs, query a class that has both those attributes, only where both asset_id and asset_type match.
So given the array
[[4,"Logo"],[1,"Image"]]
I want to generate the SQL
SELECT "asset_attachments".* FROM "asset_attachments" WHERE ((asset_id,asset_type) IN ((4,'Logo'),(1,'Image')))
I can do this by manually entering a string using where like this:
AssetAttachment.where("(asset_id,asset_type) IN ((4,'Logo'),(1,'Image'))")
But I'm trying to use it with an array of any length and asset type/id.
So far I've tried
AssetAttachment.where([:asset_id, :asset_type] => [[4,"Logo"],[1,"Image"]])
NoMethodError: undefined method `to_sym' for [:asset_id, :asset_type]:Array
and
AssetAttachment.where("(asset_id,asset_type)" => [[4,"Logo"],[1,"Image"]])
ActiveRecord::StatementInvalid: PG::Error: ERROR: column asset_attachments.(asset_id,asset_type) does not exist
and
AssetAttachment.where("(asset_id,asset_type) IN (?,?)",[[4,"Logo"],[1,"Image"]])
ActiveRecord::PreparedStatementInvalid: wrong number of bind variables (1 for 2) in: (asset_id,asset_type) IN (?,?)
Does anyone know how to do this? Thanks in advance
set vs. array
The core of the problem is: you are mixing sets and arrays in an impossible way.
elem IN (...) .. expects a set.
elem = ANY(...) .. expects an array.
You can use unnest() to transform an array to a set.
You can use the aggregate function array_agg() to transform a set to an array.
Errors
Here, you are trying to form an array from (asset_id, asset_type):
AssetAttachment.where([:asset_id, :asset_type] => [[4,"Logo"],[1,"Image"]])
.. which is impossible, since arrays have to consist of identical types, while we obviously deal with a numeric and a string constant (you kept the actual types a secret).
Here, you force "(asset_id, asset_type)" as single column name by double-quoting it:
AssetAttachment.where("(asset_id,asset_type)" => [[4,"Logo"],[1,"Image"]])
And finally, here you try provide a single bind variable for two ?:
AssetAttachment.where("(asset_id,asset_type) IN (?,?)",[[4,"Logo"],[1,"Image"]])
Valid SQL
In pure SQL, either of these work:
SELECT * FROM asset_attachments
WHERE (asset_id, asset_type) IN ((4, 'Logo'), (1, 'Image'));
SELECT * FROM asset_attachments
WHERE (asset_id, asset_type) IN (VALUES(4, 'Logo'), (1, 'Image'));
SELECT * FROM asset_attachments
WHERE (asset_id, asset_type) = ANY (ARRAY[(4, 'Logo'), (1, 'Image')]);
If you have a long list of possible matches, an explicit JOIN would prove faster:
SELECT *
FROM asset_attachments
JOIN (VALUES(4, 'Logo'), (1, 'Image')) AS v(asset_id, asset_type)
USING (asset_id, asset_type)
Valid syntax for AR
I am an expert with Postgres, with AR not so much. This simple form might work:
AssetAttachment.where("(asset_id,asset_type) IN ((?,?),(?,?))", 4,"Logo",1,"Image")
Not sure if this could work, not sure about single or double quotes either:
AssetAttachment.where((:asset_id, :asset_type) => [(4,'Logo'),(1,'Image')])