How can I use the sql function CAST in rust, diesel? - mysql

I'm developing a new endpoint using Rocket and am trying to return a Vec<> made of various structs.
The raw query I want to replicate in diesel is:
select location.id, location.name, w.datetime, t.temp, w.compass, w.speed, r.probability, s.height
from location
inner join rainfall r on location.id = r.location
inner join temperature t on location.id = t.location
inner join wind w on location.id = w.location
inner join swell s on location.id = s.location
where t.datetime = w.datetime
and s.datetime = t.datetime
and CAST(t.datetime as date) = CAST(r.datetime as date)
and t.datetime > now() and t.datetime < NOW() + INTERVAL 1 HOUR;
and I recognize, that in order to use the CAST function I need to use the sql_function! macro:
sql_function! {
#[sql_name="CAST"]
fn cast(x: sql_types::Nullable<sql_types::Datetime>) -> sql_types::Date;
}
which allows me to create the following query:
let summaries: Vec<(Location, Swell, Wind, Temperature, Rainfall)> = location::table
.inner_join(swell::table)
.inner_join(wind::table)
.inner_join(temperature::table)
.inner_join(rainfall::table)
.filter(temperature::datetime.eq(wind::datetime))
.filter(temperature::datetime.eq(swell::datetime))
.filter(temperature::datetime.gt(utilities::today()))
.filter(temperature::datetime.lt(utilities::future_hour(1)))
.filter(cast(temperature::datetime).eq(cast(rainfall::datetime)))
.load(&conn.0)?;
However, when I run this query I get a SQL Query error:
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near \') = CAST('rainfall'.'datetime')\' at line 1"
As illustrated in the raw SQL statement it should read CAST('rainfall'.'datetime' as date).
My question is, how can I add the 'as date' component to my diesel query? Is something missing in the sql_function definition?
Thanks for your help.

I found the answer after digging a little deeper into similar questions.
Turns out you can enter a raw sql string into the .filter method after adding: use diesel::expression::sql_literal::sql;.
So the final snippet becomes:
let summaries: Vec<(Location, Swell, Wind, Temperature, Rainfall)> = location::table
.inner_join(swell::table)
.inner_join(wind::table)
.inner_join(temperature::table)
.inner_join(rainfall::table)
.filter(temperature::datetime.eq(wind::datetime))
.filter(temperature::datetime.eq(swell::datetime))
.filter(temperature::datetime.gt(utilities::today()))
.filter(temperature::datetime.lt(utilities::future_hour(1)))
.filter(sql("CAST(`temperature`.`datetime` as date) = CAST(`rainfall`.`datetime` as date)"))
.load(&conn.0)?;
I hope this helps someone else!

Related

How to use momentJS with nodejs and mysql custom query

I want to implement the following sql query:
date_count = await customQuery(
`
SELECT
COUNT(org.name
OR c.name
OR co.name
OR seg.arrival_details
OR seg.departure_details
OR seg.segment_airline_id
OR seg.segment_arrival_airport_code
OR seg.segment_departure_airport_code
OR seg.segment_flight_number
OR seg.trip_id
OR b.trip_id
OR bf.pnr_no
OR bf.airline_pnr_no
OR b.booking_status
OR b.created
OR org.organisation_id
OR org.name
) AS total_count
FROM
segment_details AS seg
LEFT JOIN trip_details AS tr ON seg.trip_id = tr.trip_id
LEFT JOIN bookings_flight AS bf ON tr.bookings_flight_id = bf.booking_flight_id
LEFT JOIN bookings AS b ON bf.booking_id = b.booking_id
LEFT JOIN organisation AS org ON b.organisation_id = org.organisation_id
LEFT JOIN city AS c ON org.city_id = c.city_id
LEFT JOIN country AS co ON org.country_id = co.country_id
WHERE
seg.segment_departure_date BETWEEN
${moment(date.startDate).startOf('day').format("YYYY-MM-DD HH:mm:ss") }
AND ${moment(date.endDate).endOf('day').format("YYYY-MM-DD HH:mm:ss")}
`)
But I am getting the following error:
UnhandledPromiseRejectionWarning: Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '00:00:00
my date result comes as :
'2021-10-01T08:00:00.000Z'
and when I apply moment js to it my result is as follow:
'2021-10-01 00:00:00'
I am using MySQL, SQL Yog
How can I fix this error? Any help or suggestion will be appreciated.
Try to surround your dates with single quotes:
...
seg.segment_departure_date BETWEEN
'${moment(date.startDate).startOf('day').format("YYYY-MM-DD HH:mm:ss")}'
AND '${moment(date.endDate).endOf('day').format("YYYY-MM-DD HH:mm:ss")}'
Try it out. You need to add single quotes
const startDate = moment(date.startDate).startOf('day').format("YYYY-MM-DD HH:mm:ss");
const endDate = moment(date.endDate).endOf('day').format("YYYY-MM-DD HH:mm:ss");
...
WHERE
seg.segment_departure_date BETWEEN '${startDate}' AND '${endDate}'

How to use SQL alias within query

I have a sql query (below) to insert records into a database. The goal is to insert only new / unique entries in the database. So it will insert the row if the row doesn't already exist in the entire database. I would like to have it evaluate that row against ONLY the rows that have the symbol in the instrumentSymbol, rather than evaluating against every row in the entire database.
I am running into this syntax error which I have pinpointed to be due to the use of an alias in line SELECT 1 FROM instrumentsHistory WHERE instrumentSymbol = 'ZYME' AS f
This query works fine if removing the WHERE instrumentSymbol = {SYMBOL} conditional, but I need to this to refine the set of records the query compares itself to (thus reducing time to complete task.
I have looked through the documentation which leads me to believe there is nothing wrong with this query. Can someone pls point me in the right direction?
The Error:
(sqlite3.OperationalError) near "AS": syntax error
[SQL: INSERT INTO instrumentsHistory (datetime, instrumentSymbol, observation, observationColName)
SELECT t.datetime, t.instrumentSymbol, t.observation, t.observationColName
FROM tempTable t
WHERE NOT EXISTS
(SELECT 1 FROM instrumentsHistory WHERE instrumentSymbol = 'ZYME' AS f
WHERE t.datetime = f.datetime
AND t.instrumentSymbol = f.instrumentSymbol
AND t.observation = f.observation
AND t.observationColName = f.observationColName)]
EDIT 1:
Adding complete query...
sql = f"""INSERT INTO instrumentsHistory (datetime, instrumentSymbol, observation, observationColName)
SELECT t.datetime, t.instrumentSymbol, t.observation, t.observationColName
FROM tempTable t
WHERE NOT EXISTS
(SELECT 1 FROM instrumentsHistory WHERE instrumentSymbol = '{symbol}' AS f
WHERE t.datetime = f.datetime
AND t.instrumentSymbol = f.instrumentSymbol
AND t.observation = f.observation
AND t.observationColName = f.observationColName)"""
This code:
WHERE NOT EXISTS (SELECT 1 FROM instrumentsHistory WHERE instrumentSymbol = 'ZYME' AS f
WHERE t.datetime = f.datetime
has multiple errors. There are two WHERE clauses in a row. And as is being used in a WHERE clause. I am guessing this is a copy-and-past error, but it is unclear what you intend.

Why did this query change work?

I ended up scrapping the part of the WHERE clause that was giving me issues, but initially I got this query working by doing something that didn't make sense to me at all, and was hoping someone could shine some light on what is going on here. The entire query and function are below, but I'm not sure all of that is necessary
So this query was previously working and this WHERE clause is still being used successfully in another query. Now multiple functions are used in this line of the where clause, however if I just use the portion starting with ModifiedStartDate the query works fine. So it seems like the issue is with ModifiedDate. The portion of the WHERE clause that was giving us issues was:
and ModifiedDate(r.EXPIRATION_DATE, ModifiedStartDate(r.COMMENCEMENT_DATE,
PaySched_MaxFreq(r.RE_CONTRACT_KEY))) > #1/1/2019#
The query was failing with the error "Data type mismatch in criteria expression". So just doing some testing I ended up adding the following portion to the WHERE clause:
and r.RE_CONTRACT_KEY NOT IN (1)
And then the query worked?!?! I really don't get how adding this line magically resolved a data type mismatch error. There is no RE_CONTRACT_KEY = 1 so it's not bad data or something.
I did some testing and took the ModifiedDate function and put that into the select clause and it worked fine. I also added another field to the SELECT clause using the DATEADD function to make sure the function result was still being treated as a date, and it was. Query is below and the function is below that.
SELECT DISTINCT ....
FROM ((((((PAYMENT_LINE_ITEM AS pli
INNER JOIN PAYMENT_SCHEDULE AS tps ON pli.PAYMENT_SCHEDULE_KEY =
ps.PAYMENT_SCHEDULE_KEY)
INNER JOIN RECONTRACT AS r ON pli.RE_CONTRACT_KEY = r.RE_CONTRACT_KEY)
INNER JOIN Conversion_ProductCategory AS cpc ON cpc.Value = pli.PAYMENT_TYPE)
INNER JOIN ManualEntry AS me ON me.LeaseID = r.RE_CONTRACT_ID)
LEFT JOIN Mapping_CostCenter AS mcc ON mcc.CostCenter = me.CostCenter)
INNER JOIN PIW_Exclusions AS pe ON pe.RE_CONTRACT_ID = r.RE_CONTRACT_ID)
LEFT JOIN FacilityCode_Address_xRef AS fca ON fca.[Facility Code] =
mcc.placecode & "-" & mcc.placecodedescription
WHERE pli.PAYMENT_TYPE in ("rent","storage","parking")
and ModifiedDate(r.EXPIRATION_DATE,
ModifiedStartDate(r.COMMENCEMENT_DATE,
PaySched_MaxFreq(r.RE_CONTRACT_KEY))) > #1/1/19#
and PE.Reason = "rent extension"
and r.RE_CONTRACT_KEY NOT IN (1) 'New line added that made query work
And the function:
Public Function ModifiedDate(DateToModify As Date, DateToCompare As Date) As
Date
Select Case DateToModify
Case #2/28/2000#, #2/28/2004#, #2/28/2008#, #2/28/2012#, #2/28/2016#,
#2/28/2020#, #2/28/2024#, #2/28/2028#, #2/28/2032#, #2/28/2036#, #2/28/2040#,
#2/28/2044#, #2/28/2048#
DateToModify = DateAdd("d", 1, DateToModify)
End Select
If DatePart("d", DateAdd("d", 1, DateToModify)) = DatePart("d",
DateToCompare) Then
ModifiedDate = DateAdd("d", 1, DateToModify)
Else
ModifiedDate = DateToModify
End If
End Function
If you're curious the final working WHERE clause is:
WHERE pli.PAYMENT_TYPE in ("rent","storage","parking")
and r.EXPIRATION_DATE > #1/1/19#
and PE.Reason = "rent extension"

SQL 1064 Error, Syntax going unseen

SELECT
i.*,
ii.file_location
FROM group_shop_item i, group_shop_itemimage ii, group_shop_brand b
WHERE
i.brand_id = b.id
AND
b.brand_status_id = 1
AND
i.is_deleted = 0
AND
i.is_displayed = 1
AND
i.id = ii.item_id
AND
ii.is_main = 1
AND
i.deal_participate = 1
AND
i.brand_label_id IS NOT NULL
ORDER BY i.datetime_modified DESC;
This SQL query keeps throwing me a 1064. It seems to be on the last line which I've tried with and without the i table variable. I can't for the life of me catch the error, anyone can lend me another pair of eyes?
I'm throwing this as a RAW query into the in built Django function and building this query with string concatenation. This copy paste is directly from a print I've done from the command line. It's outputting neatly but isn't reading when I run the view on my browser.
Over 25 years ago ANSI Standard join syntax was adopted. You need to cease using comas between table names in the from clause.
SELECT
i.*
, ii.file_location
FROM group_shop_item i
INNER JOIN group_shop_itemimage ii ON i.id = ii.item_id
INNER JOIN group_shop_brand b ON i.brand_id = b.id
WHERE i.is_deleted = 0
AND i.is_displayed = 1
AND ii.is_main = 1
AND i.deal_participate = 1
AND i.brand_label_id IS NOT NULL
AND b.brand_status_id = 1
;
Regarding the 1064 error, please read this without the exact error message and the exact/full query we can't offer much insight into that.
The other thing you need to be careful of is that "select *" isn't good practice either.

unknown class: Fixnum Rails MySQL query - inserting variable breaks my search

I had a query which was working just fine:
#schedule = Schedule.find(params[:id])
#schedule_tasks = ScheduleTask.select("s.*, t.*, t.*, d.*, st.*").from("schedule_tasks st").
joins("left join schedules s ON s.id = st.schedule_id").
joins("left join tasks t ON t.id = st.task_id").
joins("right join days d ON d.id = st.day_id").
order("d.number, t.name").
group_by{|d| d.number}
I had to refine my search to only schedule_tasks with a specific schedule_id, so I edited the second line to:
joins("left join schedules s ON s.id = st.schedule_id AND s.id = ?", #schedule.id).
This has cause the following error:
unknown class: Fixnum
The error goes away if I take out the group_by - but I need that, and I have tried hard coding in the number instead of #schedule.id and that does not work either, a google search does not reveal a lot of details on this error.
For anyone coming here from Google, I used plain string interpolation to fix this issue. This method is vulnerable to SQL Injection, so make sure you type check your variables before using them.
In this case I would do
#schedule_id = #schedule.id
.
.
.
joins("left join schedules s ON s.id = st.schedule_id AND s.id = #{#schedule_id}")
Rather than following learning_to_swim's answer, which as noted is at risk of SQL injection, couldn't you cast your #schedule_id to a string?
#tasks = ScheduleTask.joins("left join [...] s.id = ?", #schedule.id.to_s)