I'm using Rails to get data from Postgresql by passing dynamic column and table name.
I cannot use ActiveRecord because the shape data that is imported from shapefile is dynamic both table and column name.
I have to use double quote with a column name in the query to avoid problem such column name: "addr:city" for example.
def find_by_column_and_table(column_name, shape_table_name)
sql = "SELECT \"#{column_name}\" FROM \"#{shape_table_name}\" WHERE \"#{column_name}\" IS NOT NULL"
ActiveRecord::Base.connection.select_one(sql)
end
2 examples of generated sql statement:
SELECT "place" FROM "shp_6c998258-32a6-11e0-b34b-080027997e00"
SELECT "addr:province" FROM "shp_6c998258-32a6-11e0-b34b-080027997e00"
I want to make sure there is no sql injection in the query.
Could anyone point me how to solve this issue?
The recommended way to prevent injection, speed up your query and catch errors is to use positional parameters or stored proceedures. Anything less is asking for trouble.
http://nasir.wordpress.com/2007/12/03/stored-procedures-and-rails/
http://www.postgresql.org/docs/9.0/static/sql-expressions.html#AEN1834
Related
A fragment of SQL in the Informix dialect
SELECT INSUREDNAME
FROM sc5100car3gdb#idp_5100_cb:PRPCINSURED P
WHERE P.PROPOSALNO = A.PROPOSALNO
What does this grammar mean?
The SQL fragment is:
SELECT INSUREDNAME
FROM sc5100car3gdb#idp_5100_cb:PRPCINSURED P
WHERE P.PROPOSALNO = A.PROPOSALNO
This means that there is a table PRPCINSURED in database sc5100car3gdb hosted on Informix server idp_5100_cb; inside the query, the table will be referred to by the alias P. It has columns INSUREDNAME and PROPOSALNO. Further, this must be a fragment of an SQL statement. The WHERE clause uses the alias P, but also references another table with the alias (or perhaps name) A. However, the context defining A is not shown; as it stands, the A will trigger an error. (When I ran an analogous query, I got the error SQL -217: Column (a) not found in any table in the query (or SLV is undefined).)
See the Informix Guide to SQL: Syntax manual on database object names for more information about the notation used for the table name.
I'm having a problem with a .first query in Rails 4 ActiveRecord. New behavior in Rails 4 is to add an order by the id field so that all db systems will output the same order.
So this...
Foo.where(bar: baz).first
Will give the query...
select foos.* from foos order by foos.id asc limit 1
The problem I am having is my select contains two sum fields. With the order by id thrown in the query automatically, I'm getting an error that the id field must appear in the group by clause. The error is right, no need for the id field if I want the output to be the sum of these two fields.
Here is an example that is not working...
baz = Foo.find(77).fooviews.select("sum(number_of_foos) as total_number_of_foos, sum(number_of_bars) as total_number_of_bars").reorder('').first
Here is the error...
ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: column "foos.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: ...bars FROM "fooviews" ORDER BY "...
Since the select is an aggregate expression, there is no need for the order by id, but AR is throwing it in automatically.
I found that I can add a reorder('') on to the end before the .first and that removes the order by id, but is that the right way to fix this?
Thank you
[UPDATE] What I neglected to mention is that I'm converting a large Rails 3 project to Rails 4. So the output from the Rails 3 is an AR object. If possible, the I would like the solution to keep in that format so that there is less code to change in the conversion.
You will want to use take:
The take method retrieves a record without any implicit ordering.
For example:
baz = Foo.find(77).fooviews.select("sum(number_of_foos) as total_number_of_foos, sum(number_of_bars) as total_number_of_bars").take
The commit message here indicates that this was a replacement for the old first behavior.
I'd like to have a basic table summing up the number of occurence of values inside arrays.
My app is a Daily Deal app built to learn more Ruby on Rails.
I have a model Deals, which has one attribute called Deal_goal. It's a multiple select which is serialized in an array.
Here is the deal_goal taken from schema.db:
t.string "deal_goal",:array => true
So a deal A can have deal= goal =[traffic, qualification] and another deal can have as deal_goal=[branding, traffic, acquisition]
What I'd like to build is a table in my dashboard which would take each type of goal (each value in the array) and count the number of deals whose deal_goal's array would contain this type of goal and count them.
My objective is to have this table:
How can I achieve this? I think I would need to group each deal_goal array for each type of value and then count the number of times where this goals appears in the arrays. I'm quite new to RoR and can't manage to do it.
Here is my code so far:
column do
panel "top of Goals" do
table_for Deal.limit(10) do
column ("Goal"), :deal_goal ????
# add 2 columns:
'nb of deals with this goal'
'Share of deals with this goal'
end
end
Any help would be much appreciated!
I can't think of any clean way to get the results you're after through ActiveRecord but it is pretty easy in SQL.
All you're really trying to do is open up the deal_goal arrays and build a histogram based on the opened arrays. You can express that directly in SQL this way:
with expanded_deals(id, goal) as (
select id, unnest(deal_goal)
from deals
)
select goal, count(*) n
from expanded_deals
group by goal
And if you want to include all four goals even if they don't appear in any of the deal_goals then just toss in a LEFT JOIN to say so:
with
all_goals(goal) as (
values ('traffic'),
('acquisition'),
('branding'),
('qualification')
),
expanded_deals(id, goal) as (
select id, unnest(deal_goal)
from deals
)
select all_goals.goal goal,
count(expanded_deals.id) n
from all_goals
left join expanded_deals using (goal)
group by all_goals.goal
SQL Demo: http://sqlfiddle.com/#!15/3f0af/20
Throw one of those into a select_rows call and you'll get your data:
Deal.connection.select_rows(%q{ SQL goes here }).each do |row|
goal = row.first
n = row.last.to_i
#....
end
There's probably a lot going on here that you're not familiar with so I'll explain a little.
First of all, I'm using WITH and Common Table Expressions (CTE) to simplify the SELECTs. WITH is a standard SQL feature that allows you to produce SQL macros or inlined temporary tables of a sort. For the most part, you can take the CTE and drop it right in the query where its name is:
with some_cte(colname1, colname2, ...) as ( some_pile_of_complexity )
select * from some_cte
is like this:
select * from ( some_pile_of_complexity ) as some_cte(colname1, colname2, ...)
CTEs are the SQL way of refactoring an overly complex query/method into smaller and easier to understand pieces.
unnest is an array function which unpacks an array into individual rows. So if you say unnest(ARRAY[1,2]), you get two rows back: 1 and 2.
VALUES in PostgreSQL is used to, more or less, generate inlined constant tables. You can use VALUES anywhere you could use a normal table, it isn't just some syntax that you throw in an INSERT to tell the database what values to insert. That means that you can say things like this:
select * from (values (1), (2)) as dt
and get the rows 1 and 2 out. Throwing that VALUES into a CTE makes things nice and readable and makes it look like any old table in the final query.
In my application I use sqlite as a Backing store.For my use I create Two tables for Surgeon and Schedule with surgeon having columns Name(VARCHAR),id(int) and Schedule having id(int),Surgeon(int),Values(VARCHAR).
The Surgeon column in Schedule table is pointing to the id column in Surgeon table. I use The Below query to select values from the Schedule table for the Surgeon with id=1
SELECT Schedule.Values,Name from Schedule,Surgeon where Schedule.Surgeon==Surgeon.id and Surgeon.id=2
But I got error as below
SQLiteManager: Likely SQL syntax error: SELECT Schedule.Values,Name from Schedule,Surgeon where Schedule.Surgeon==Surgeon.id and Surgeon.id=2 [ near "Values": syntax error ]
I don't know where it went wrong, I have't used the database before so forgive me if the question is much basic
You have named one of the columns in Schedule as values Change it to something else that is not a key word for sqlite. you should not use key string to name the column First you have to take a look at the keys in sqlite
If u want to take the Name, then try Surgeon.Name
I'm just beginning with ruby on rails and have a question regarding a bit more complex query. So far I've done simple queries while looking at rails guide and it worked really well.
Right now I'm trying to get some Ids from database and I would use those Ids to get the real objects and do something with them. Getting those is a bit more complex than simple Object.find method.
Here is how my query looks like :
select * from quotas q, requests r
where q.id=r.quota_id
and q.status=3
and r.text is not null
and q.id in
(
select A.id from (
select max(id) as id, name
from quotas
group by name) A
)
order by q.created_at desc
limit 1000;
This would give me 1000 ids when executing this query from sql manager. And I was thinking to obtain the list of ids first and then find objects by id.
Is there a way to get these objects directly by using this query? Avoiding ids lookup? I googled that you can execute query like this :
ActiveRecord::Base.connection.execute(query);
Assuming Quota has_many :requests,
Quota.includes(:requests).
where(status:3).
where('requests.text is not null').
where("quotas.id in (#{subquery_string_here})").
order('quotas.created_at desc').limit(1000)
I'm by no means an expert but most basic SQL functionality is baked into ActiveRecord. You might also want to look at the #group and #pluck methods for ways to eliminate the ugly string subquery.
Calling #to_sql on a relationship object will show you the SQL command it is equivalent to, and may help with your debugging.
I would use find_by_sql for this. I wouldn't swear that this is exactly right, but as I recall you can pretty much plonk an SQL statement into a find_by_sql and the resulting columns will be returned as attributes of an array of objects of the class you call it on:
status = 3
Quota.find_by_sql('
select *
from quotas q, requests r
where q.id=r.quota_id
and q.status= ?
and r.text is not null
and q.id in
(
select A.id from (
select max(id) as id, name
from quotas
group by name) A
)
order by q.created_at desc
limit 1000;', status)
If you come to Rails as someone used to writing raw SQL, you're probably better off using this syntax than stringing together a bunch of ActiveRecord methods - the result is the same, so it's just a matter of what you find more readable.
Btw, you shouldn't use string interpolation (i.e. #{variable} syntax) inside an SQL query. Use the '?' syntax instead (see my example) to avoid SQL injection potential.