DevExtreme-PHP-Data working with complex sql query - odata

Working with DevExpress/DevExtreme need old style solution with MySql and Apache. Find DevExtreme-PHP-Data ( https://github.com/DevExpress/DevExtreme-PHP-Data ) . But ... seems it's working with tables? How to work with more complex sql queries with that module? I need to pass query something like that:
select sales_orders.*, items.item_name from sales_orders left join items force index (ItemsIdx) on sales_orders.item_id = items.item_id
Thanks for any help ...

Related

Snapshot of one model to another using ActiveRecord

I have 3 models: Project, MonthlySubscription (sti of Subscription), and MonthlyTransactionQueue (sti of TransactionQueue). Subscription and TransactionQueue both belong_to Project.
I want to create a copy of MonthlySubscription and place it into MonthlyTransactionQueue, for Projects that have a Release.released = false. How would I do this using AR?
My sql looks like this:
insert into transaction_queues
select a.*, b.id as release_id
from subscriptions a
left join releases b
on a.project_id = b.project_id
where b.released = false
and a.type = 'ReleaseSubscription'
For AR I have started with this ReleaseSubscription.joins(project: :releases) but it doesn't keep the Release.released field
You have a few options
Execute sql
ReleaseSubscription.connection.execute("insert into transaction_queues...")
Use AR inside of a transaction.
MonthlyTransactionQueue.transaction do
# I'm unsure what Release.released is and how it relates but this should work other than that.
MonthlySubscription.where(released: false).each do |sub|
MonthlyTransactionQueue.create(sub.attributes)
end
end
This creates multiple insert statements but runs them all in the same transaction.
Another good option would be to dump everything that matches your query into a sql file and use load data in file to add everything at once in sql.

Rails: Search for substring without getting SQL Injected

I'm trying to implement auto complete for Rails. I have something like the following in my code -
Location.where("name like ?", "%#{params[:location]}%")
I'm afraid this would lead to SQL injection. Something like the following -
SELECT * FROM Locations WHERE (name LIKE '%green%') OR 1=1--%'
When params[:location] is something like this green%') OR 1=1--
Is there any way, I can avoid SQLi for substring based search in Rails?
Dave is right. Try it and see what it outputs. It wraps the whole thing up as part of the condition. In my Courses model.
> x = "'') OR SELECT * FROM Users"
=> "'') OR SELECT * FROM Users"
> Course.where(["name like ?", "%#{x}%"])
Course Load (38.7ms) SELECT "courses".* FROM "courses" WHERE
(name like '%'''') OR SELECT * FROM Users%')
=> []
If you're using Postgres, I would suggest using trigram support in Postgres to do this.
Throw this in a migration to get things set up:
CREATE EXTENSION pg_trgm;
then run your query like this:
Location.select('*', "similarity(search_term, #{ActiveRecord::Base.sanitize(search_term)}) AS similarity").order('similarity DESC, search_term')
or, just do what you're doing but wrap the param in #{ActiveRecord::Base.sanitize(search_term)}

Rails postgreSQL GroupingError

So I'm struggling with what seems to be a common problem. I developed my rails app with SQLite and have now pushed it to Heroku (postgreSQL) and encountered this error:
GroupingError: ERROR: column "projects.id" must appear in the GROUP BY clause or be used in an aggregate function
as a result of my code:
#projects = #user.projects.select('MAX(id), *').group(:unique_id).all.paginate(page: params[:page])
where I pull all of a user's projects. unique_id identifies each project and I use MAX(id)as a way of pulling the most recent version of the project.
How can I change my code so that it works is both SQLite for development and postgreSQL for production? I've looked at several other questions that deal with this error but haven't found a great solution for what I'm doing. I'm inclined to use distinct instead of group but I'm not sure how. Thanks in advance.
I think your problem is the "*" in the select method. If you replace that with "unique_id", you should satisfy the SQL parser.
#projects = #user.projects.select('MAX(id), unique_id').group(:unique_id).all.paginate(page: params[:page])
It would look like this. Select max(id), unique_id, other_column1, other_column2, etc... You then will have to group by the other columns.

Change default finder select statement in Rails 3.1

I'd like to change the default statement that ActiveRecord uses to query a model's table. By default, it queries a table "cables" for example by...
this_cable = Cable.first
results in
SELECT "cables".* FROM "cables" LIMIT 1
I would like to find a way for it to wind up with
SELECT *,askml(wkb_geometry) as kml FROM "cables" LIMIT 1
This way i can call a database function and have that behave like a field on the object.
this_cable.kml
=> "<LineString><coordinates>-73.976879999999994,40.674999999999997 -73.977029999999999,40.674779999999998 -73.977170000000001,40.674770000000002 -73.97775,40.67501</coordinates></LineString>"
This can be accomplished by adding a scope
scope :with_kml, "*,askml(wkb_geometry) as kml"
But I figure that's kind of messy. I would like this "kml" column to always be there, without having to call the "with_kml" scope.
Any ideas?
Have you tried using default_scope for this, or do you actually want this to be present on all your models?
Something like this might solve your problem:
default_scope select("*, askml(wkb_geometry) as kml")
You might want to change that to cables.* for it to work properly with joins and such, though.

Do "like" queries with ActiveRecord in Rails 2.x and 3.x?

I'm doing queries like this in Rails 3.x
Speaker.where("name like '%yson%'")
but I'd love to avoid the DB specific code. What's the right way to do this?
If there's a way to do this in Rails 2.x too, that would help too.
In Rails 3 or greater
Speaker.where("name LIKE ?", "%yson%")
In Rails 2
Speaker.all(:conditions => ["name LIKE ?", "%yson%"])
Avoid to directly interpolate strings because the value won't be escaped and you are vulnerable to SQL injection attacks.
You can use .matches for it.
> t[:name].matches('%lore').to_sql
=> "\"products\".\"name\" LIKE '%lore'"
Actual usage in a query would be:
Speaker.where(Speaker.arel_table[:name].matches('%lore'))
Use a search engine like solr or sphinx to create indexes for the columns you would be performing like queries on. Like queries always result in a full table scan when you look at the explain plan so you really should almost never use them in a production site.
Not by default in Rails, since there are so many DB options (MySQL, Postgresql, MongoDB, CouchDB...), but you can check out gems like MetaWhere, where you can do things like:
Article.where(:title.matches => 'Hello%', :created_at.gt => 3.days.ago)
=> SELECT "articles".* FROM "articles" WHERE ("articles"."title" LIKE 'Hello%')
AND ("articles"."created_at" > '2010-04-12 18:39:32.592087')
In general though you'll probably have to have some DB specific code, or refactor your code (i.e redefine the .matches operator on symbols in MetaWhere) to work with a different database. Hopefully you won't be changing your database that often, but if you are you should have a centralized location where you define these operators for re-use. Keep in mind that an operator or function defined in one database might not be available in another, in which case having this generalized operation is moot since you won't be able to perform the search anyways.

Resources