Rails 4: column reference "updated_at" is ambiguous with Postgres - ruby

I am trying to query the database with a DateTime range for the 'updated_at' field. The front end sends queries in a JSON array:
["2015-09-01 00:00:00","2015-10-02 23:00:00"]
At the Rails controller, I parse the two strings to DateTime using:
start_date = DateTime.parse(params[:date_range_arr][0])
end_date = DateTime.parse(params[:date_range_arr][1])
#...
#events = #events.where('updated_at BETWEEN ? AND ?,
start_date, end_date
)
The queries show:
WHERE (updated_at BETWEEN '2015-09-01 00:00:00.000000' AND '2015-10-02 23:00:00.000000')
And the errors are:
ActionView::Template::Error (PG::AmbiguousColumn: ERROR: column reference "updated_at" is ambiguous
LINE 1: ...texts"."id" = "events"."context_id" WHERE (updated_at...

Do you have by any chance a default scope with a join or an include on the Event model or in the code above what's included in the original question?
Either way, you simply need to be more specific with your query as follow:
#...
#events = #events.where('events.updated_at BETWEEN ? AND ?,
start_date, end_date
)

Related

how to populate sysdate in apex_item.date_popup

i have created apex_item.datepopup() function to provide entry for user to select date from calendar, it should populate sysdate bydefault..
APEX_ITEM.DATE_POPUP (2,ROWNUM,ISSUED_DATE,'dd-mon-yyyy')
Try this:
APEX_ITEM.DATE_POPUP (2,ROWNUM, nvl(ISSUED_DATE, sysdate),'dd-mon-yyyy')
Directly copied from my code where I have it
APEX_ITEM.DATE_POPUP (p_idx => 2 , p_value => (CASE WHEN UPPER(cur_parameter.default) = 'SYSDATE' THEN SYSDATE WHEN UPPER(cur_parameter.default) != 'SYSDATE' AND cur_parameter.default IS NOT NULL THEN TO_DATE(cur_parameter.default) ELSE NULL END) , p_item_id => cur_parameter.name, p_date_format => cur_parameter.format , p_item_label => cur_parameter.name)
The CASE is because I keep the defaults stored in a table, and most of the time, the default date is sysdate, however, its viewed as a string and not SYSDATE. The cur_parameter is a row in a cursor.
If a call has more than one or two parameters, its always best to use named notation, avoids confusion and helps prevent mix ups.
APEX_ITEM.DATE_POPUP (p_idx =>2 , p_value => SYSDATE , p_item_id => ISSUED_DATE, p_date_format => 'DD-MON-YYYY') IssuedDate,

Laravel eloquent possible bug?

I want to join two tables and filter on a field in the joined table. I don't think the actual tables matter in this question, but it's a table with dates joined with a table with the event info, so there are more dates possible for 1 event.
I made this eloquent line:
Event_date::whereRaw('startdate >= curdate() OR enddate >= curdate()')->whereHas('Event', function($q){$q->where("approved",true );})->orderBy('startdate', 'asc')->orderBy('enddate', 'asc')->toSql());
the filter doesn't work though. So thats why i added the ->toSql() to the line.
I get the following back:
select * from `event_dates` where startdate >= curdate() OR enddate >= curdate() and exists (select * from `events` where `event_dates`.`event_id` = `events`.`id` and `approved` = ?) order by `startdate` asc, `enddate` asc
You see that the 'where("approved",true )' results in 'where ..... and and approved = ?)' Where does the questionmark come from??? I tried diferent things, like '1', 1, 'True', True, true, 'true'...everything comes back as a questionmark.
Any suggestions??
Thanks!
Erwin
This is expected behaviour. Laravel uses prepared statements. To get parameters that are put into placeholders, you can use
$query->getBindings();
so for example in your case you can use:
$query = Event_date::whereRaw('startdate >= curdate() OR enddate >= curdate()')->whereHas('Event', function($q){$q->where("approved",true );})->orderBy('startdate', 'asc')->orderBy('enddate', 'asc'));
and now
echo $query->toSql();
var_dump($query->getBindings());
to get both query with placeholders and values that will be put in place of placeholders.

Issue in date conversion in ruby

In my #query I am putting the date in MM-DD-YYYY format. e.g., 01-22-2016. Now I want to search the dates from messages table with that date how can I do. I had added the query:
Message.includes(:user)
.select('messages.*, users.name')
.where(
"users.name ilike ? OR messages.to ilike ? OR messages.created_at.srtftime(\"%Y-%m-%d\") = ?",
"%#{#query}%",
"%#{#query}%",
Date.strptime(#query, "%m-%d-%Y")
)
But I am getting the issue for that:
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column "%Y-%m-%d" does not exist
I had also added the query as:
Message.includes(:user)
.select('messages.*, users.name')
.where(
"users.name ilike ? OR messages.to ilike ? OR messages.created_at.srtftime("%Y-%m-%d") = ?",
"%#{#query}%",
"%#{#query}%",
Date.strptime(#query, "%m-%d-%Y")
)
But in that the error is coming as: unknown type of %string
From your comment on #Amadan's answer:
If I don't convert my message.created_at then I am getting blank result.
Message.includes(:user)
.select('messages.*, users.name')
.where(
"users.name ilike ? OR messages.to ilike ? OR messages.created_at = ?",
"%#{#query}%",
"%#{#query}%",
Date.strptime(#query, "%m-%d-%Y")
)
This will produce a query with (among others) a condition like this:
messages.created_at = '2016-01-29 00:00:00'
It should be apparent why this won't work.
messages.created_at is a timestamp, and unless the record just happens to have been created at midnight, that equality comparison is going to fail.
What you need to do is compare the date part of messages.created_at to the date from the query. To get the date part of a timestamp in PostgreSQL, you can use either the date() function or the ::date suffix:
Message.includes(:user)
.select('messages.*, users.name')
.where(
"messages.created_at::date = ?",
Date.strptime(#query, "%m-%d-%Y")
)
Hopefully, you don't have dates stored in the database in VARCHAR columns, but DATETIME or equivalent. Don't convert to String, let ActiveRecord handle dates for you: messages.created_at = ?.

Delete using active record

How to achieve below query in ActiveRecord ?
"delete from model where date(created_at)=#{some_date}"
where created_at is sql datetime field.
One option I can think is calculate
start_date = starting time of the day
end_date = end time of the day
and
Model.delete_all('created_at' >= start_date, 'created_at' < end_date)
Any other clean option ?
Assuming database you are using is MySql and start_date is a date object.
Use mysql DATE_FORMAT function
Model.delete_all("DATE_FORMAT(created_at, '%Y-%m-%d') >= ?",
start_date.strftime("%Y-%m-%d"))

Single table version controled data

So I have a table designed as such:
create_table "entries", :force => true do |t|
t.integer "id", :null => false, :autoincrement => true
t.text "text"
t.string "uuid"
t.datetime "created_at", :null => false
end
I have a similar problem to " Database - data versioning in single table" except that I have multiple sources (some of which do work offline) writing into this database, so the current bit doesn't really work well for me.
What I'm wondering is what is the best way to get the most recent of each UUID.
In sqlite: SELECT "entries".* FROM "entries" GROUP BY uuid ORDER BY updated_at DESC works great, but it's not valid syntax in postgres, and it kind of feels janky. Is there a good way to do this, or do I need to redo my schema?
One way to get the results you're after is to use a window function and a derived table. ActiveRecord doesn't understand either of those but there's always find_by_sql:
Entry.find_by_sql(%q{
select id, text, uuid, created_at
from (
select id, text, uuid, created_at,
row_number() over (partition by uuid order by created_at desc) as r
from entries
) as dt
where r = 1
})
The interesting part is this:
row_number() over (partition by uuid order by created_at desc)
partition by uuid is similar to group by uuid but it doesn't collapse the rows, it just modifies how the row_number() window function behaves so that row_number() is computed with respect to rows with matching uuids; the order by created_at desc similarly applies only to the window that row_number() will be looking at. The result is that r = 1 peels off the first row in each group.

Resources