Why does the gorm postgresql throws pq: syntax error at or near ")"? - postgresql

SELECT_QUERY = `SELECT * FROM events WHERE c_id = ? AND start_time > ? and
end_time < ?`
query := sr.db.Raw(SELECT_QUERY, request.GetCId(), startTime, endTime)
var v = request.GetVIds()
if len(v) > 0 {
query = query.Where(` v_id IN (?) `, v)
} //Only this block introduces first ) after end_time
var c = request.GetStatus().String()
if len(c) > 0 {
query = query.Where( " status = ? ", c) // this introduces the other opening brace //after AND
}
Following is the query generated and found in logs
SELECT * FROM events WHERE c_id = 1 AND start_time > '2020-04-16 18:42:00' and
end_time < '2020-04-16 18:45:50' ) AND ( v_id IN (1,2)) AND ( status = 'STATUS_MIDDLE_CLASS' ORDER BY start_time DESC LIMIT 5 OFFSET 1
The other solution in stackoverflow and internet article doesn't help.
PS: Is it because I mix db.Raw( ) and query.Where() ?

Changing ? to $1 doesn't fix the issue.
Basically a few things fixed the issue.
1) Mixing Raw and query.Where was one issue.
After making the Raw query to sr.db.Where
2)
SELECT_QUERY = `SELECT * FROM events WHERE c_id = ? AND start_time > ? and
end_time < ?`
already has select * from. And then using query := sr.db.Raw(SELECT_QUERY, request.GetCId(), startTime, endTime) introduces nested select *.
So, changed SELECT_QUERY as follows
SELECT_QUERY = `events WHERE c_id = ? AND start_time > ? and
end_time < ?`
solved the issue.

I found a workaround to the error which I received when I tried to add a timestamp filed in Go/Gorm solution with PostgreSQL equivalent to default: now() which is default: time.Now().Format(time.RFC3339)
I received the error because I use AutoMigrate() to create the tables in PostgreSQL. The one problem I found is when trying to use the default value of a function instead of a string (which one can use for a fixed timestamp).
So I had to go into DataGrid (since I use JetBrains, but you can use any PostgreSQL admin tool like pgAdmin) and manually add the timestamp field with default of now() or merely update the existing field to add the default of now(). Then the error goes away when doing your next build in Go.

Related

prisma $queryRaw doesn't work with single quotes in the string

i have a query that goes
select count(id), status, "createdAt"::date from "ProjectLog" where "projectId" = (select id from "Project" where slug = ${id}) and "createdAt" > current_date - interval '${interval} day' group by "createdAt"::date, status;
i've also tried user Prisma.sql to pass the value inside the quotes but it keeps throwing error that it expected 1 argument but fount 2.
i did not have this issue with prisma 2.20.1
this issue is only happening on version 3.3.0
Query: select count(id) as count, status, "createdAt"::date from "ProjectLog" where "projectId" = (select id from "Project" where slug = $1) and "createdAt" > current_date - interval '$2 day' and key notnull group by "createdAt"::date, status
Param: ["main","30"]
PrismaClientKnownRequestError:
Invalid `prisma.queryRaw()` invocation:
Your raw query had an incorrect number of parameters. Expected: `1`, actual: `2`.
code: 'P1016',
clientVersion: '3.3.0',
meta: { expected: 1, actual: 2 }
}
any suggestions ?
i'm not sure if this is a bug.
didn't find an elegant solution in the prism documentation, I couldn't even find one, but there is a way that works...you can try this ${'variable'}
Try to use:
const interval = num + ' days';
${interval}::TEXT::INTERVAL
instead of interval '${interval} day'
This is work for me!

How to detect overlapping time ranges in PostgreSQL

I have a table like this
CREATE TABLE public.userlocation
(
datetime timestamp with time zone,
location geometry,
locationtype integer,
buffer double precision,
timebuffer double precision,
"userID" numeric,
"ID" integer NOT NULL DEFAULT nextval('"userlocation_ID_seq"'::regclass),
"time" time with time zone
)
each row has a time and then a value to make a dynamic time range, in fact If time=8 and timebuffer=15so time range would be endTime= 8+15min and startTime= 8-15 min.I can do this simply using this query
select f1.*,f1.time +(f1.timebuffer::text||' minute')::INTERVAL as startTime,f1.time-(f1.timebuffer::text||' minute')::INTERVAL as endTime
everything work fine, After this stage I want to query rows that their time period is between startTime and endTime in other word they overlap. I have already found this question
PostgreSQL query to detect overlapping time ranges
But there is a difference here,I don't have start time and endtime so I have to create them using above method. so hare is my query
select f1.*,f1.time -(f1.timebuffer::text||' minute')::INTERVAL as startTime,f1.time+(f1.timebuffer::text||' minute')::INTERVAL as endTime
from userlocation f1
where exists (select f2.time -(f2.timebuffer::text||' minute')::INTERVAL as startTime,f2.time+(f2.timebuffer::text||' minute')::INTERVAL as endTime
from userlocation f2
where tsrange(f2.startTime, f2.endTime, '()') && tsrange(f1.startTime, f1.endTime, '()')
and f2.locationtype = f1.locationtype
and f2.locationtype=1
and f2."ID" <> f1."ID");
But I get this error
[2016-08-27 23:42:45] [42703] ERROR: column f2.starttime does not exist
Position: 372
I think At first I should create F2 table but I dont know how,Can you please give me some hints?
First: The column-alias (select expression AS somename) is not usable from within its query, it is only visible from outside the query. You can solve this by wrapping it into a (subquery) xx or a view or a CTE
Second: don't repeat yourself: if you need to compute the same expression(s) twice, you could be doing too much ...
CREATE TEMP VIEW omg AS
SELECT fx.*,fx.time -(fx.timebuffer::text||' minute')::INTERVAL as startTime
,fx.time+(fx.timebuffer::text||' minute')::INTERVAL as endTime
, fx.locationtype
, fx.ID
-- ... maybe more columns and expressions ...
FROM userlocation fx
;
SELECT f1.startTime, f1.endTime
-- ... maybe more columns and expressions ...
FROM omg f1
WHERE EXISTS (
SELECT 1
FROM omg f2
WHERE tsrange(f2.startTime, f2.endTime, '()') && tsrange(f1.startTime, f1.endTime, '()')
AND f2.locationtype = f1.locationtype
AND f2.locationtype=1
AND f2."ID" <> f1."ID")
;
instead of a view you could use a CTE (the view probably performs better)
you could probably pull the tsrange into the view or CTE, too
I didn't check the logic
For completeness, the CTE version (which almost looks the same)
WITH omg AS (
SELECT fx.*,fx.time -(fx.timebuffer::text||' minute')::INTERVAL as startTime
,fx.time+(fx.timebuffer::text||' minute')::INTERVAL as endTime
, fx.locationtype
, fx.ID
-- ... maybe more columns and expressions ...
FROM userlocation fx
)
SELECT f1.startTime, f1.endTime
-- ... maybe more columns and expressions ...
FROM omg f1
WHERE EXISTS (
SELECT 1
FROM omg f2
WHERE tsrange(f2.startTime, f2.endTime, '()') && tsrange(f1.startTime, f1.endTime, '()')
AND f2.locationtype = f1.locationtype
AND f2.locationtype=1
AND f2."ID" <> f1."ID")
;

How to create an Update statement from a subquery in TSQL

I need to update all records that match my criteria. But the Sql below is giving this error:
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
-- Set MasterAccountId = NULL where there is no Receivable with equivalent BillingAccountId and TaskAccountId
UPDATE R
SET R.MasterAccountId = NULL
FROM Receivable R
WHERE EXISTS ( SELECT * FROM MasterAccount M
WHERE (ISNULL(M.BillingAccountId, 0) > 0 AND M.BillingAccountId = R.BillingAccountId) OR
(ISNULL(M.TaskAccountId, 0) > 0 AND M.TaskAccountId = R.TaskAccountId))
Basically, I need to update all records that return in that subquery.
Does any one know how to fix it?
Can you give a try on this. This is base from the repond of https://stackoverflow.com/users/40655/robin-day on this link How do I UPDATE from a SELECT in SQL Server?.
UPDATE
R
SET
R.MasterAccountId = NULL
FROM
Receivable R
INNER JOIN
MasterAccount M
ON
(ISNULL(M.BillingAccountId, 0) > 0 AND M.BillingAccountId = R.BillingAccountId) OR
(ISNULL(M.TaskAccountId, 0) > 0 AND M.TaskAccountId = R.TaskAccountId))
I don't think you are getting the said error in posted query May be somewhere else. Again in your EXISTS subquery, instead of saying select * ... it's always better to say WHERE EXISTS ( SELECT 1 FROM MasterAccount M
Also try using the JOIN version of this query instead like
UPDATE R
SET R.MasterAccountId = NULL
FROM Receivable R
JOIN MasterAccount M ON M.BillingAccountId = R.BillingAccountId
OR M.TaskAccountId = R.TaskAccountId
WHERE ISNULL(M.BillingAccountId, 0) > 0
OR ISNULL(M.TaskAccountId, 0) > 0;

TemporalTipe.Time parameter in jpql

I want filter by Time in jpql but I think that I´m not doing well.
SELECT e FROM Pedido e WHERE e.fechaEntrega = :fechaInicio AND e.horaEntrega < :horaEntrega and que.setParameter("horaEntrega", horaEntrega, TemporalType.TIME); but when i see return this not filter by horaEntrega. I'm using eclipselink 2.5 any idea???
I tryed use SELECT e FROM Pedido e WHERE e.fechaEntrega = :fechaInicio AND CAST(e.horaEntrega AS TIMESTAMP) < :horaEntrega and doesn´t work and if i try cast to Time says me that expected NUMBER and got DATE
It´s weird when I write SELECT in sql im using cast(cast(etretst as timestamp) as time) < '08:00:00' and this works fine. And when I write this say me that expected TIME not a DATE
I resolved SELECT SELECT e FROM Pedido e WHERE e.fechaPedido = :fechaInicio AND CAST(CAST(e.horaPedido AS TIMESTAMP) AS TIME) < :horaZona and parameter is que.setParameter("horaZona", new Time(horaPedido.getTime()).toString());

TSQL CTE Error: Incorrect syntax near ')'

I am developing a TSQL stored proc using SSMS 2008 and am receiving the above error while generating a CTE. I want to add logic to this SP to return every day, not just the days with data. How do I do this? Here is my SP so far:
ALTER Proc [dbo].[rpt_rd_CensusWithChart]
#program uniqueidentifier = NULL,
#office uniqueidentifier = NULL
AS
DECLARE #a_date datetime
SET #a_date = case when MONTH(GETDATE()) >= 7 THEN '7/1/' + CAST(YEAR(GETDATE()) AS VARCHAR(30))
ELSE '7/1/' + CAST(YEAR(GETDATE())-1 AS VARCHAR(30)) END
if exists (
select * from tempdb.dbo.sysobjects o where o.xtype in ('U') and o.id = object_id(N'tempdb..#ENROLLEES')
) DROP TABLE #ENROLLEES;
if exists (
select * from tempdb.dbo.sysobjects o where o.xtype in ('U') and o.id = object_id(N'tempdb..#DISCHARGES')
) DROP TABLE #DISCHARGES;
declare #sum_enrollment int
set #sum_enrollment =
(select sum(1)
from enrollment_view A
join enrollment_info_expanded_view C on A.enrollment_id = C.enroll_el_id
where
(#office is NULL OR A.group_profile_id = #office)
AND (#program is NULL OR A.program_info_id = #program)
and (C.pe_end_date IS NULL OR C.pe_end_date > #a_date)
AND C.pe_start_date IS NOT NULL and C.pe_start_date < #a_date)
select
A.program_info_id as [Program code],
A.[program_name],
A.profile_name as Facility,
A.group_profile_id as Facility_code,
A.people_id,
1 as enrollment_id,
C.pe_start_date,
C.pe_end_date,
LEFT(datename(month,(C.pe_start_date)),3) as a_month,
day(C.pe_start_date) as a_day,
#sum_enrollment as sum_enrollment
into #ENROLLEES
from enrollment_view A
join enrollment_info_expanded_view C on A.enrollment_id = C.enroll_el_id
where
(#office is NULL OR A.group_profile_id = #office)
AND (#program is NULL OR A.program_info_id = #program)
and (C.pe_end_date IS NULL OR C.pe_end_date > #a_date)
AND C.pe_start_date IS NOT NULL and C.pe_start_date >= #a_date
;WITH #ENROLLEES AS (
SELECT '7/1/11' AS dt
UNION ALL
SELECT DATEADD(d, 1, pe_start_date) as dt
FROM #ENROLLEES s
WHERE DATEADD(d, 1, pe_start_date) <= '12/1/11')
The most obvious issue (and probably the one that causes the error message too) is the absence of the actual statement to which the last CTE is supposed to pertain. I presume it should be a SELECT statement, one that would combine the result set of the CTE with the data from the #ENROLLEES table.
And that's where another issue emerges.
You see, apart from the fact that a name that starts with a single # is hardly advisable for anything that is not a local temporary table (a CTE is not a table indeed), you've also chosen for your CTE a particular name that already belongs to an existing table (more precisely, to the already mentioned #ENROLLEES temporary table), and the one you are going to pull data from too. You should definitely not use an existing table's name for a CTE, or you will not be able to join it with the CTE due to the name conflict.
It also appears that, based on its code, the last CTE represents an unfinished implementation of the logic you say you want to add to the SP. I can suggest some idea, but before I go on I'd like you to realise that there are actually two different requests in your post. One is about finding the cause of the error message, the other is about code for a new logic. Generally you are probably better off separating such requests into distinct questions, and so you might be in this case as well.
Anyway, here's my suggestion:
build a complete list of dates you want to be accounted for in the result set (that's what the CTE will be used for);
left-join that list with the #ENROLLEES table to pick data for the existing dates and some defaults or NULLs for the non-existing ones.
It might be implemented like this:
… /* all your code up until the last WITH */
;
WITH cte AS (
SELECT CAST('7/1/11' AS date) AS dt
UNION ALL
SELECT DATEADD(d, 1, dt) as dt
FROM cte
WHERE dt < '12/1/11'
)
SELECT
cte.dt,
tmp.[Program code],
tmp.[program_name],
… /* other columns as necessary; you might also consider
enveloping some or all of the "tmp" columns in ISNULLs,
like in
ISNULL(tmp.[Program code], '(none)') AS [Program code]
to provide default values for absent data */
FROM cte
LEFT JOIN #ENROLLEES tmp ON cte.dt = tmp.pe_start_date
;