JDBC setDate not working with preparedstatement - date

I am pretty new to Java JDBC. I am trying to create a JDBC preparedstatement to do a SELECT between two Oracle DATE values.
I know that data exists between these two times, as I can do the query directly.
When I execute the prepared statement from within my JDBC code, however, it returns 0 rows.
My input start and times are Long Unix time values in milliseconds.
I have tried to pare down the code to the bare minimum:
public static List<Oam1731Sam5Data> getData(Long startTime, Long endTime) {
try {
String query = "SELECT timecaptured from oam1731data5 " +
"WHERE timecaptured between ? and ?";
pstmt = conn.prepareStatement(query); // create a statement
Date javaStartDate = new Date(startTime);
Date javaEndDate = new Date(endTime);
pstmt.setDate(1, javaStartDate);
pstmt.setDate(2, javaEndDate);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
String serviceId = rs.getString("SERVICEID");
String recordSource = rs.getString("RECORDSOURCE");
Date timeCaptured = rs.getDate("TIMECAPTURED");
Long oneWayMaxDelay = rs.getLong("ONEWAYMAXDELAY");
Long twoWayMaxDelay = rs.getLong("TWOWAYMAXDELAY");
Long twoWayMaxDelayVar = rs.getLong("TWOWAYMAXDELAYVAR");
Long packetLoss = rs.getLong("PACKETLOSS");
}
} catch (SQLException se) {
System.err.println("ERROR: caught SQL exception, code: " + se.getErrorCode() +
", message: " + se.getMessage());
}
The issue is that this returns 0 rows, where the same query returns data:
select insert_date, recordsource, serviceid, timecaptured, onewaymaxdelay, twowaymaxdelay, twowaymaxdelayvar, packetloss from oam1731data5
where timecaptured between to_date('2012-01-18 07:00:00','YYYY-MM-DD HH24:MI:SS')
and to_date('2012-01-18 08:00:00','YYYY-MM-DD HH24:MI:SS')
order by insert_date
DBMS_OUTPUT:
INSERT_DATE RECORDSOURCE SERVICEID TIMECAPTURED ONEWAYMAXDELAY TWOWAYMAXDELAY TWOWAYMAXDELAYVAR PACKETLOSS
1/18/2012 10:43:36 AM EV TAMP20-MTRO-NID1SYRC01-MTRO-NID1 1/18/2012 7:25:24 AM 40822 79693 343 0
1/18/2012 10:43:36 AM EV SYRC01-MTRO-NID1TAMP20-MTRO-NID1 1/18/2012 7:25:13 AM 39642 79720 334 0
1/18/2012 10:43:36 AM EV TAMP20-MTRO-NID1SYRC01-MTRO-NID1 1/18/2012
I have seen and ready many posts about problems somewhat like this, but have not been
able to find the key yet!
I thought about trying to make my query use a string and simply convert my dates to strings to be able to insert them for the Oracle TO_DATE function, but it seems like I should not have to do this.
And here is the output from my println statements. Is it an issue that the dates that print do NOT show the time portion?
SQL query: SELECT timecaptured from oam1731data5 WHERE timecaptured between ? and ?
Java Oracle date: 2012-01-18 end date 2012-01-18
Thanks in advance for any help.
Mitch

A java.sql.Date represents a date without time. You must use a Timestamp if you care about the time part.
The javadoc of java.sql.Date says:
To conform with the definition of SQL DATE, the millisecond values
wrapped by a java.sql.Date instance must be 'normalized' by setting
the hours, minutes, seconds, and milliseconds to zero in the
particular time zone with which the instance is associated.

Using Date for your start and end dates shouldn't cause any problem. The data in the specified interval should be retrieved in that time interval (Those data that you printed which were inserted on 1/18/2012 are supposed to be retrieved in this case.) Therefore I don't think that omitting time portion is your problem.

Related

how to use date_part in hibernate query?

String q = "select id from Calendar c " +
"where c.isActive = 1 and " +
"date_part('dow', '2017-09-19 13:23:23'::date) = c.frequencyValue)";
Query query = em.createQuery(q);
List results = query.getResultList();
If I include ::date, hibernate would complain because : conflicts with parameter, but if I don't, postgres will complain. Could not choose a best candidate function. You might need to add explicit type casts. What can I do?
https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html#queryhql-expressions
as specified extract function should work if the underlying db supports them so:
extract(dow from date '2017-09-19 13:23:23');
should works

intersystem cache C# query with datetime

When I use cache sql query in C# I'm getting an error:
SQLtext1 = "SELECT top 10 * FROM dbo.DAPPLICATIONSTAT where TIMESTAMP = '2015-02-01 00:00:00'"
I would like to use a where clause with a datetime filter.
I am using InterSystems.Data.CacheClient.dll to execute the query.
Error Messge :
[SQLCODE: <-4>:<A term expected, beginning with one of the following: identifier, constant, aggregate, %ALPHAUP, %EXACT, %MVR, %SQLSTRING, %SQLUPPER, %STRING, %UPPER, $$, :, +, -, (, NOT, EXISTS, or FOR>]
[Cache Error: <<SYNTAX>errdone+2^%qaqqt>] [Details: <Prepare>]
[%msg: < SQL ERROR #4: A term expected, beginning with either of: (, NOT, EXISTS, or FOR^SELECT top :%qpar(1) * FROM dbo . DAPPLICATIONSTAT where TIMESTAMP>
I think that you have reserved word TIMESTAMP and so, you have that error
Try this SQL query, where filedname TIMESTAMP in dobled quotas
SELECT top 10 * FROM dbo.DAPPLICATIONSTAT where "TIMESTAMP" = '2015-02-01 00:00:00'

How to implement raw sql query in Tastypie

I am trying to do this simple query, but it does not work. Thanks.
SELECT * FROM TSimple where (start_date < '2012-04-20' and end_date is null) or
(end_date > '2012-04-20' and start_date < '2012-04-20')
class TSimple (models.Model):
start_date = models.DateTimeField()
end_date = models.DateTimeField(blank=True, null=True)
...
class TSimpleResource(ModelResource):
def dehydrate(self, bundle):
request_method = bundle.request.META['REQUEST_METHOD']
if request_method=='GET':
new_date = bundle.request.GET.get('new_date', '')
qs = TSimple.objects.raw(
'SELECT * FROM TSimple where (start_date<=\'' +
new_date + '\' and end_date>=\'' +
new_date + '\') or (start_date<=\'' + new_date +
'\' and end_date is null)')
ret_list = [row for row in qs]
// NOT WORK. Not able to get correct json data in javascript.
// It needs return bundle. HOW to replace bundle?
// Is this correct way to do it?
return ret_list
else:
// This is ok.
return bundle
I have following questions:
1) (raw sql method) If implementing in dehydrate method is correct way to do it? If it is, above does not work. It should return bundle object. How to construct new bundle?
If above method is ok, I noticed that bundle already constructed .data field with default query(?), which will be thrown away with new query. That raise the questions if this is right way to do it.
2) If there are other raw sql method to do it? Where to execute the sql?
3) How to do it in filter?
4) I know sql and not familiar with complex filter. That's why I am trying to use raw sql method to do quick prototype. What are the draw back? I noticed that using Tastypie has many unnecessary queries which I don't know how to get rid of it. Example, query on table with foreign key trigger query to another table's data, which I don't want to get.
I figure out the filter and it seems worked. But I am still interested in raw sql.
def apply_filters(self, request, applicable_filters):
base_filter = super(TSimpleResource, self).apply_filters(request,
applicable_filters)
new_date = request.GET.get('new_date', None)
if new_date:
qset = (
(
Q(start_date__lte=new_date) &
Q(end_date__gte=new_date)
) |
(
Q(start_date__lte=new_date) &
Q(end_date__isnull=True)
)
)
base_filter = base_filter.filter(qset)
return base_filter

Convert a string representing a timestamp to an actual timestamp in PostgreSQL?

In PostgreSQL: I convert string to timestamp with to_timestamp():
select * from ms_secondaryhealthcarearea
where to_timestamp((COALESCE(update_datetime, '19900101010101'),'YYYYMMDDHH24MISS')
> to_timestamp('20121128191843','YYYYMMDDHH24MISS')
But I get this error:
ERROR: syntax error at end of input
LINE 1: ...H24MISS') >to_timestamp('20121128191843','YYYYMMDDHH24MISS')
^
********** Error **********
ERROR: syntax error at end of input
SQL state: 42601
Character: 176
Why? How to convert a string to timestamp?
One too many opening brackets. Try this:
select *
from ms_secondaryhealthcarearea
where to_timestamp(COALESCE(update_datetime, '19900101010101'),'YYYYMMDDHH24MISS') >to_timestamp('20121128191843','YYYYMMDDHH24MISS')
You had two opening brackets at to_timestamp:
where to_timestamp((COA.. -- <-- the second one is not needed!
#ppeterka has pointed out the syntax error.
The more pressing question is: Why store timestamp data as string to begin with? If your circumstances allow, consider converting the column to its proper type:
ALTER TABLE ms_secondaryhealthcarearea
ALTER COLUMN update_datetime TYPE timestamp
USING to_timestamp(update_datetime,'YYYYMMDDHH24MISS');
Or use timestamptz - depending on your requirements.
Another way to convert a string to a timestamp type of PostgreSql is the above,
SELECT to_timestamp('23-11-1986 06:30:00', 'DD-MM-YYYY hh24:mi:ss')::timestamp without time zone;
I had the same requirement as how I read the title. How to convert an epoch timestamp as text to a real timestamp. In my case I extracted one from a json object. So I ended up with a timestamp as text with milliseconds
'1528446110978' (GMT: Friday, June 8, 2018 8:21:50.978 AM)
This is what I tried. Just the latter (ts_ok_with_ms) is exactly right.
SELECT
data->>'expiration' AS expiration,
pg_typeof(data->>'expiration'),
-- to_timestamp(data->>'expiration'), < ERROR: function to_timestamp(text) does not exist
to_timestamp(
(data->>'expiration')::int8
) AS ts_wrong,
to_timestamp(
LEFT(
data->>'expiration',
10
)::int8
) AS ts_ok,
to_timestamp(
LEFT(
data->>'expiration',
10
)::int8
) + (
CASE
WHEN LENGTH(data->>'expiration') = 13
THEN RIGHT(data->>'expiration', 3) ELSE '0'
END||' ms')::interval AS ts_ok_with_ms
FROM (
SELECT '{"expiration": 1528446110978}'::json AS data
) dummy
This is the (transposed) record that is returned:
expiration 1528446110978
pg_typeof text
ts_wrong 50404-07-12 12:09:37.999872+00
ts_ok 2018-06-08 08:21:50+00
ts_ok_with_ms 2018-06-08 08:21:50.978+00
I'm sure I overlooked a simpler version of how to get from a timestamp string in a json object to a real timestamp with ms (ts_ok_with_ms), but I hope this helps nonetheless.
Update: Here's a function for your convenience.
CREATE OR REPLACE FUNCTION data.timestamp_from_text(ts text)
RETURNS timestamptz
LANGUAGE SQL AS
$$
SELECT to_timestamp(LEFT(ts, 10)::int8) +
(
CASE
WHEN LENGTH(ts) = 13
THEN RIGHT(ts, 3) ELSE '0'
END||' ms'
)::interval
$$;

How to do a timestamp comparison with JPA query?

We need to make sure only results within the last 30 days are returned for a JPQL query. An example follows:
Date now = new Date();
Timestamp thirtyDaysAgo = new Timestamp(now.getTime() - 86400000*30);
Query query = em.createQuery(
"SELECT msg FROM Message msg "+
"WHERE msg.targetTime < CURRENT_TIMESTAMP AND msg.targetTime > {ts, '"+thirtyDaysAgo+"'}");
List result = query.getResultList();
Here is the error we receive:
<openjpa-1.2.3-SNAPSHOT-r422266:907835 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: An error occurred while parsing the query filter 'SELECT msg FROM BroadcastMessage msg WHERE msg.targetTime < CURRENT_TIMESTAMP AND msg.targetTime > {ts, '2010-04-18 04:15:37.827'}'. Error message: org.apache.openjpa.kernel.jpql.TokenMgrError: Lexical error at line 1, column 217. Encountered: "{" (123), after : ""
Help!
So the query you input is not JPQL (which you could see by referring to the JPA spec). If you want to compare a field with a Date then you input the Date as a parameter to the query
msg.targetTime < CURRENT_TIMESTAMP AND msg.targetTime > :param
THIS IS NOT SQL.
The JDBC escape syntax may not be supported in the version of OpenJPA that you're using. The documentation for the latest 1.2.x release is here: http://openjpa.apache.org/builds/1.2.2/apache-openjpa-1.2.2/docs/manual/manual.html#jpa_langref_lit .
The documentation mentioned earlier refers to the docs for OpenJPA 2.0.0 (latest): http://openjpa.apache.org/builds/latest/docs/manual/jpa_langref.html#jpa_langref_lit
That said is there any reason why you want to inject a string into your JPQL? What about something like the following snippet?
Date now = new Date();
Date thirtyDaysAgo = new Date(now.getTime() - (30 * MS_IN_DAY));
Query q = em.createQuery("Select m from Message m "
+ "where m.targetTime < :now and m.targetTime > :thirtyDays");
q.setParameter("now", now);
q.setParameter("thirtyDays", thirtyDaysAgo);
List<Message> results = (List<Message>) q.getResultList();