How to use from_statement with pagination in SQLalchemy? - sqlalchemy

I have a complex query sql = "SELECT title, name, country FROM ...", which I execute using
results = db.session.query("title", "name", "country").from_statement(text(sql)).all()
This works and produces the desired results. I would like to paginate this query, but
results = db.session.query("title", "name", "country").from_statement(text(sql)).paginate(1,10, False)
gives me the error AttributeError: 'Query' object has no attribute 'paginate'. I have successfully used paginate() elsewhere in my code, but never with the from_statement(). How can I do this?

Related

How to print query of Django ORM

I am using Django ORM query with Extra params. when I try to print the SQL query relevant to that ORM Query,i am getting the below Error message.
ORM Query:
Record = SAMPLE_TABLE.objects.extra(where=["REPLACE(Message,' ','') "+whereCaseSensitive+" like %s "+query],params=[duplicateCheckMessage]).filter(~Q(iStatus=2),~Q(iAppStatus=2),iEntityID=entityId,iTemplateType=1).first()
Message - FieldName ,
whereCaseSensitive - '',
query - ( FIND_IN_SET("test",Testfield))
I am trying to fetch the sql query related to this using
print(Record.query)
when i run this i am getting Exception as 'NoneType' object has no attribute 'query'
Can any one help on this ?
You can't print the query for the first (or any) element of a queryset because it is an instance, not a query. To print .query you need to do it on the queryset
Try this
my_query = SAMPLE_TABLE.objects.extra(*some_extra).filter(*some_filter)
print(my_query.query)
record = my_query.first()

How can I use Django.db.models Q module to query multiple lines of user input text data

How would I go about using the django.db.models Q module to query multiple lines of input from a list of data using a <textarea> html input field? I can query single objects just fine using a normal html <input> field. I've tried using the same code as my input field, except when requesting the input data, I attempt to split the lines like so:
def search_list(request):
template = 'search_result.html'
query = request.GET.get('q').split('\n')
for each in query:
if each:
results = Product.objects.filter(Q(name__icontains=each))
This did not work of course. My code to query one line of data (that works) is like this:
def search(request):
template = 'search_result.html'
query = request.GET.get('q')
if query:
results = Product.objects.filter(Q(name__icontains=query))
I basically just want to search my database for a list of data users input into a list, and return all of those results with one query. Your help would be much appreciated. Thanks.
Based on your comments, you want to implement OR-logic for the given q string.
We can create such Q object by reduce-ing a list of Q objects that each specify a Q(name__icontains=...) constraint. We reduce this with a "logical or" (a pipe in Python |), like:
from django.db.models import Q
from functools import reduce
from operator import or_
def search_list(request):
template = 'search_result.html'
results = Product.objects.all()
error = None
query = request.GET.get('q')
if query:
query = query.split('\n')
else:
error = 'No query specified'
if query:
results = results.filter(
reduce(or_, (Q(name__icontains=itm.strip()) for itm in query))
)
elif not error:
error = 'Empty query'
some_context = {
'results' : results,
'error': error
}
return render(request, 'app/some_template.html', some_context)
Here we thus first check if q exists and is not the empty string. If that is the case, the error is 'No query specified'. In case there is a query, we split that query, next we check if there is at least one element in the query. If not, our error is 'Empty query' (note that this can not happen with an ordinary .split('\n'), but perhaps you postprocess the list, and for example remove the empty elements).
In case there are elements in query, we perform the reduce(..) function, and thus filter the Products.
Finally here we return a render(..)ed response with some_template.html, and a context that here contains the error, and the result.

Rails SQL query on unknown (dynamic) number of queries using LIKE

I have a Rails search form that performs a dynamic query. That is, the user enters a search like:
(hobby="skiing") OR (gender="male" AND hobby="jogging")
So, I don't know how many queries I will be searching by until runtime.
I parse the search query by converting it into a valid SQL query, so the above search would be converted to the following format:
query = "hobby LIKE ? OR (gender LIKE ? AND hobby LIKE ?)"
queries = ["skiing", "male", "jogging"]
For the following query:
where(query, queries)
However, the general syntax of the Rails search query is very limiting:
where(query, query_1, query_2, query_3)
I cannot replace the 'query_n' arguments with an array like I want to, without Rails throwing an error.
NoMethodError (undefined method `where' for ["a", "b", "c"]:Array)
Attempting to splat the array yields the same error:
where(query, *queries)
Again:
NoMethodError (undefined method `where' for ["a", "b", "c"]:Array)
So what can I do?
EDIT:
The full search function looks like this:
def self.search(search)
query = "%#{search}%"
if search
includes(:games, :jobs)
strngs = ["hobby = ? OR name = ? OR gender = ?", "dsfgdsfg", "dsgsdfgsd", "sdfsfsdf"]
.where(strngs)
What you'll want to do is pass an array as a single argument to where which contains both the query AND the dynamic values. For example:
where(["att_1 LIKE ? OR att_2 LIKE ?", "value1", "value2"])
If an array is passed as the first and only argument, then the first element of the array is treated as a template. The following array values are treated as the dynamic values for the query template.
For your example, instead of having two separate variables queries and query, combine them into one query variable:
# A single array with the query AND values
query = ["hobby LIKE ? OR (gender LIKE ? AND hobby LIKE ?)", "skiing", "male", "jogging"]
# Run the `where` with a single array as the argument
YourModel.where(query)
This will allow you to query the DB with an unknown number of values using LIKE.
For reference: Rails where() docs

Get SQL array from ActiveRecord::Relation

I'm building up a query like this:
scope = User.select(:name).where("name = ?", 'test')
In another part of my code, I'm trying to convert scope, which is an ActiveRecord::Relation object into a SQL array like ["SELECT name FROM users WHERE name = ?", 'test']. Is there any way to accomplish this? Thanks in advance.
It doesn't appear to be possible to get the array you want back from an ActiveRecord::Relation object.
Say that we're just using where. When we call User.where("name = ?", "test") we enter the where method in ActiveRecord::QueryMethods. This calls where! which calls build_where. Since we passed in the query as a String we end up here:
# ActiveRecord::QueryMethods#build_where
when String, Array
[#klass.send(:sanitize_sql, other.empty? ? opts : ([opts] + other))]
sanitize_sql combines the SQL query with the values and the result is stored in where_values:
> User.where("name = ?", "test").where_values
=> ["name = 'test'"]
ActiveRecord::Relation only holds onto this combined version, not the query and values separately.

How to get Ruby MySQL returning PHP like DB SELECT result

So I use the PDO for a DB connection like this:
$this->dsn[$key] = array('mysql:host=' . $creds['SRVR'] . ';dbname=' . $db, $creds['USER'], $creds['PWD']);
$this->db[$key] = new PDO($this->dsn[$key]);
Using PDO I can then execute a MySQL SELECT using something like this:
$sql = "SELECT * FROM table WHERE id = ?";
$st = $db->prepare($sql);
$st->execute($id);
$result = $st->fetchAll();
The $result variable will then return an array of arrays where each row is given a incremental key - the first row having the array key 0. And then that data will have an array the DB data like this:
$result (array(2)
[0]=>[0=>1, "id"=>1, 1=>"stuff", "field1"=>"stuff", 2=>"more stuff", "field2"=>"more stuff" ...],
[1]=>[0=>2, "id"=>2, 1=>"yet more stuff", "field1"=>"yet more stuff", 2=>"even more stuff", "field2"=>"even more stuff"]);
In this example the DB table's field names would be id, field1 and field2. And the result allows you to spin through the array of data rows and then access the data using either a index (0, 1, 2) or the field name ("id", "field1", "field2"). Most of the time I prefer to access the data via the field names but access via both means is useful.
So I'm learning the ruby-mysql gem right now and I can retrieve the data from the DB. However, I cannot get the field names. I could probably extract it from the SQL statement given but that requires a fair bit of coding for error trapping and only works so long as I'm not using SELECT * FROM ... as my SELECT statement.
So I'm using a table full of State names and their abbreviations for my testing. When I use "SELECT State, Abbr FROM states" with the following code
st = #db.prepare(sql)
if empty(where)
st.execute()
else
st.execute(where)
end
rows = []
while row = st.fetch do
rows << row
end
st.close
return rows
I get a result like this:
[["Alabama", "AL"], ["Alaska", "AK"], ...]
And I'm wanting a result like this:
[[0=>"Alabama", "State"=>"Alabama", 1=>"AL", "Abbr"=>"AL"], ...]
I'm guessing I don't have the way inspect would display it quite right but I'm hoping you get the idea by now.
Anyway to do this? I've seen some reference to doing this type of thing but it appears to require the DBI module. I guess that isn't the end of the world but is that the only way? Or can I do it with ruby-mysql alone?
I've been digging into all the methods I can find without success. Hopefully you guys can help.
Thanks
Gabe
You can do this yourself without too much effort:
expanded_rows = rows.map do |r|
{ 0 => r[0], 'State' => r[0], 1 => r[1], 'Abbr' => r[1] }
end
Or a more general approach that you could wrap up in a method:
columns = ['State', 'Abbr']
expanded_rows = rows.map do |r|
0.upto(names.length - 1).each_with_object({}) do |i, h|
h[names[i]] = h[i] = r[i]
end
end
So you could collect up the rows as you are now and then pump that array of arrays through something like what's above and you should get the sort of data structure you're looking for out the other side.
There are other methods on the row you get from st.fetch as well:
http://rubydoc.info/gems/mysql/2.8.1/Mysql/Result
But you'll have to experiment a little to see what exactly they return as the documentation is, um, a little thin.
You should be able to get the column names out of row or st:
http://rubydoc.info/gems/mysql/2.8.1/Mysql/Stmt
but again, you'll have to experiment to figure out the API. Sorry, I don't have anything set up to play around with the MySQL API that you're using so I can't be more specific.
I realize that php programmers are all cowboys who think using a db layer is cheating, but you should really consider activerecord.