How to use Multiple resultsets with POSTGRES JDBC? - postgresql

I am using JDBC on a PostgreSQL database.
When I query for an entity in a resultset, it returns 5 rows.
Related to that entity is another entity, for which I query while i am using a row in the above resultset.
When I execute this query, the above resultset is closed.
This means that it is allowing only 1 resultset to be active on 1 connection at a time.
Previously the same code was working perfect for Oracle DB server.
Is it that I need to ask the DB admin to configure the server to allow multiple resultsets?
Or to do some change in the code?
Or is it impossible to do it in postgre?
Here is the code for more details:
Connection conn = PTSConnection.getConnection();
Statement stmt = conn.createStatement();
ResultSet lines = stmt.executeQuery("SELECT LINEID,STARTSTOPID,ENDSTOPID FROM LINES"); **//first resultset is active**
while (lines.next()){
int lineId= lines.getInt(1);
Stop ss = StopStorage.getByID(lines.getInt(2));
Stop es = StopStorage.getByID(lines.getInt(3));
ResultSet stops = stmt.executeQuery("SELECT STOPID FROM STOPSINLINES WHERE LINEID=" + lineId); **//first resultset dies**
List<Stop> lineStops = new ArrayList<Stop>();
while(stops.next()){
Stop stop = StopStorage.getByID(stops.getInt(1));
lineStops.add(stop);
}
stops.close();
Line aLine = null;
ResultSet emergencyLine = stmt.executeQuery("SELECT CAUSE, STARTTIME, ENDTIME FROM EMERGENCYLINES WHERE LINEID =" + lineId);
if(emergencyLine.next()){
String cause = emergencyLine.getString(1);
Time startTime = emergencyLine.getTime(2);
Time endTime = emergencyLine.getTime(3);
aLine = new EmergencyLine(ss, es, cause, startTime, endTime, (Stop[]) lineStops.toArray(new Stop[lineStops.size()]));
} else {
aLine = new Line(ss, es, (Stop[]) lineStops.toArray(new Stop[lineStops.size()]));
}
emergencyLine.close();
LineRepository.getInstance().addLine(aLine);
}
lines.close();

The reason is not that you are using two resultsets on the same connection, but you are re-using the same Statement object for a new query. When you run executeQuery() on a Statement instance, any previous result will be closed (I'm surprised that your code did work with Oracle...)
Simply create a new Statement object before executing the second query:
Statement stmt = conn.createStatement();
Statement nestedStmt = conn.createStatement();
ResultSet lines = stmt.executeQuery("SELECT LINEID,STARTSTOPID,ENDSTOPID FROM LINES"); **//first resultset is active**
while (lines.next()){
...
ResultSet stops = nestedStmt.executeQuery("SELECT STOPID FROM STOPSINLINES WHERE LINEID=" + lineId); **//first resultset dies**
List lineStops = new ArrayList();
while(stops.next()){
Stop stop = StopStorage.getByID(stops.getInt(1));
lineStops.add(stop);
}
stops.close();
...
ResultSet emergencyLine = nestedStmt.executeQuery("SELECT CAUSE, STARTTIME, ENDTIME FROM EMERGENCYLINES WHERE LINEID =" + lineId);
if(emergencyLine.next()){
String cause = emergencyLine.getString(1);
....
}
emergencyLine.close();
And don't for get to properly close all Statements and ResultSets !

Related

Sometimes postgres does not return records when queried remotely from JDBC Client

public static ArrayList<String[]> getDailyRecords () throws ClassNotFoundException {
ArrayList<String[]> list=new ArrayList<String[]> ();
String[] header = {"City", "Location", "Asset", "Number of Alerts", "Time spent in alerts", "Last seen temparature", "Limit"};
list.add (header);
String myDriver = "org.postgresql.Driver";
Class.forName (myDriver);
try( Connection conn = DriverManager.getConnection( ApplicationSettings.DATABASE_URL, ApplicationSettings.DATABASE_USER, ApplicationSettings.DATABASE_PASSWORD);
Statement st = conn.createStatement ();) {
conn.setAutoCommit (true);
ResultSet rs=null;
st.setFetchSize (200);
String dailyQuery="select * from sch.reports();";
rs= st.executeQuery (dailyQuery);
while (rs.next ()) {
String[] ar = new String[7];
ar[0] = rs.getString ("location");
ar[1] = rs.getString ("sublocation");
ar[2] = rs.getString ("zone");
ar[3] = rs.getString ("total_count");
ar[4] = rs.getString ("period");
String temp = rs.getString ("temparature");
ar[5] = temp;
list.add (ar);
}
conn.close ();
st.close ();
rs.close ();
}catch(Exception e){
e.printStackTrace ();
}catch(Error e){
e.printStackTrace ();
}
finally {
if(list.size ()==1){
System.out.println ("NO records found");
}else{
System.out.println ("Foudn some records");
}
return list;
}
I have a sql function, which does return records when queried locally from postgres clients. I invoke this function at scheduled timings from a java application. This worked fine for few months. But all of sudden, st.executeQuery() returning empty result set occasionally. Like 4 out of 10 attempts of executeQuery() in a day return empty resultset.
Things I have tried out:
Made sure query returns some records always. It should return 60 records.
Captured Errors,Exceptions. There were no errors seen.
Made sure JDBC connection is closed.
Debugged Postgres JDBC driver classes. Found that in cases when resultset is empty, data was not received from postgres data stream.
can size of data in tables influence query response?
Any help is kindly appreciated!
Update: SQL function definition added.
DECLARE
exception_error_code text;
exception_message text;
exception_detail text;
exception_hint text;
exception_context text;
BEGIN
RETURN QUERY
select l.name as location,sl.name as sublocation,z.name as zone,al.lim as lim,count(al.id) total_count,sum(al.timestamp_to-al.timestamp_from) period,t2.temperature temparature
from
map.location l
left join
map.sub_location sl
on l.id=sl.location_id
left join
map.zone z
on sl.id=z.sub_location_id
left join
map.subzone sz
on z.id=sz.zone_id
inner join
(select *,(info::json -> 'breach_type')::text as lim from alr.live where date(timestamp_from)= date(now() + INTERVAL '5 hours 30 minutes')) al
on sz.id= al.sub_zone_id
left join
(select subzone_id,max(nd_timestamp) as nd_timestamp from tel.temperature_sh group by subzone_id) t1
on al.sub_zone_id=t1.subzone_id
left join
tel.temperature_sh t2
on t1.subzone_id=t2.subzone_id
and t1.nd_timestamp=t2.nd_timestamp
group by l.name ,sl.name,z.name,t2.temperature , al.lim
order by l.name ,sl.name,z.name;
-- if something "breaks" do the following
EXCEPTION WHEN others THEN
get stacked diagnostics
exception_error_code = RETURNED_SQLSTATE
,exception_message = MESSAGE_TEXT
,exception_detail = PG_EXCEPTION_DETAIL
,exception_hint = PG_EXCEPTION_HINT
,exception_context = PG_EXCEPTION_CONTEXT
;
-- log exception for debugging
PERFORM public.insert_db_exception(
exception_error_code
,exception_message
,exception_detail
,exception_hint
,exception_context
);
END;

Android SQLite not returning data for given search term

I am trying to build a search interface but the SQLite database returns nothing here is the code for search function
public List<DiaryModel> searchData(String srchTerm){
List<DiaryModel> data2=new ArrayList<>();
SQLiteDatabase db1 = this.getWritableDatabase();
String sql="SELECT * FROM "+DB_TABLE+" WHERE "+KEY_HEADING+" LIKE '"+srchTerm+"%'";
Cursor cursor2 =db1.rawQuery(sql,null);
cursor2.moveToFirst();
StringBuilder stringBuffer2;
stringBuffer2 = new StringBuilder();
DiaryModel diaryModel2;
while (cursor2.moveToNext()){
diaryModel2 = new DiaryModel();
String heading = cursor2.getString(cursor2.getColumnIndexOrThrow("heading"));
String desc = cursor2.getString(cursor2.getColumnIndexOrThrow("desc_"));
diaryModel2.setHeading(heading);
diaryModel2.setDesc(desc);
stringBuffer2.append(diaryModel2);
data2.add(diaryModel2);
}
return data2;
}
but when I print everything the Database returns data, here is the code for get Data used for printing data present in Database
public List<DiaryModel> getdata(){
List<DiaryModel> data=new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor =db.rawQuery("SELECT * FROM diary_db", null);
cursor.moveToFirst();
StringBuilder stringBuffer = new StringBuilder();
DiaryModel diaryModel;
while (cursor.moveToNext()){
diaryModel = new DiaryModel();
String heading = cursor.getString(cursor.getColumnIndexOrThrow(KEY_HEADING));
String desc = cursor.getString(cursor.getColumnIndexOrThrow(KEY_DESC));
diaryModel.setHeading(heading);
diaryModel.setDesc(desc);
stringBuffer.append(diaryModel);
data.add(diaryModel);
}
return data
}
The thing is only this SQL statement is working
SELECT * FROM diary_db
and if any condition is put nothing returns.
There is something that you are doing wrong in both methods:
cursor.moveToFirst();
and then:
while (cursor.moveToNext()){
.................
}
This way you miss the 1st row of the results, because after you move the cursor to the 1st row, you move once again to the next row.
So delete this:
cursor.moveToFirst();
from both methods.

Dblink is not working in java

String id="";
List list = null;
Query query = null;
Session session = getSession();
String sql = "select id from student#dblink s, location#dblink l where s.id in (select name from Employ where id='" +Id +"') and s.country_id = l.country_id and l.country_end = '"+countryEnd+"'";
query = session.createSQLQuery(sql);
System.out.println("sql.1."+sql);
list = query.list();
if(list.size()>0)
id = list.get(0).toString();
else
id= "0";
System.out.println("Stage2Ubr Id is:"+id);
return id;
Here I got exception like "org.hibernate.exception.GenericJDBCException: could not execute query". Sometimes this exception is not coming. Sometimes it's working fine without exception. This exception won't come if dblink is working fine.Please help me. How to check wheather the dblink is working fine or not?

Linq query in stored procedure result set Ado.Net

I have a stored procedure with multiple joins, pulling all the data into a resultset I.e in dataset, now I want to write a linq query over it. How can I do that?
I am expecting:
IEnumerable<SomeType> result;
[where I need to know how the Properties of SomeType are defined.]
This is what I have tried but it does not look efficient.
SqlCommand cmd = new SqlCommand("Select top 10 * from trade");
cmd.Connection = con;
if (con.State != ConnectionState.Open)
{
con.Open();
}
SqlDataReader dr = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
var result = dt.AsEnumerable();
string valresukir = string.Empty;
var sortResult = result.OrderBy(x => Convert.ToInt32(x["trade_num"]) > 12);
string valuedata = string.Empty;
foreach (var i in sortResult)
{
valuedata += i["trade_num"].ToString();
}
to can write linq query on data table like
var data= from dataRow in dt.AsEnumerable()
where dataRow.Field<int>("trade_num") > 12
select dataRow
if trade_num is integer . Take it as a example and add your conditions accordingly.
Hope it will help you.

MARS vs NextResult

I rehydrate my business objects by collecting data from multiple tables, e.g.,
SELECT * FROM CaDataTable;
SELECT * FROM NyDataTable;
SELECT * FROM WaDataTable;
and so on...
(C# 3.5, SQL Server 2005)
I have been using batches:
void BatchReader()
{
string sql = "Select * From CaDataTable" +
"Select * From NyDataTable" +
"Select * From WaDataTable";
string connectionString = GetConnectionString();
using (SqlConnection conn = new SqlConnection(connectionString)) {
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
using (SqlDataReader reader = cmd.ExecuteReader()) {
do {
while (reader.Read()) {
ReadRecords(reader);
}
} while (reader.NextResult());
}
}
}
I've also used multiple commands against the same connection:
void MultipleCommandReader()
{
string connectionString = GetConnectionString();
string sql;
SqlCommand cmd;
using (SqlConnection conn = new SqlConnection(connectionString)) {
conn.Open();
sql = "Select * From CaDataTable";
cmd = new SqlCommand(sql, conn);
using (SqlDataReader reader = cmd.ExecuteReader()) {
while (reader.Read()) {
ReadRecords(reader);
}
}
sql = "Select * From NyDataTable";
cmd = new SqlCommand(sql, conn);
using (SqlDataReader reader = cmd.ExecuteReader()) {
while (reader.Read()) {
ReadRecords(reader);
}
}
sql = "Select * From WaDataTable";
cmd = new SqlCommand(sql, conn);
using (SqlDataReader reader = cmd.ExecuteReader()) {
while (reader.Read()) {
ReadRecords(reader);
}
}
}
}
Is one of these techniques significantly better than the other?
Also, would there be a gain if I use MARS on the second method? In other words, is it as simple as setting MultipleActiveResultSets=True in the connection string and reaping a big benefit?
If the data structure is the same in each table, I would do:
Select *, 'Ca' Source From CaDataTable
union all
Select *, 'Ny' Source From NyDataTable
union all
Select *, 'Wa' Source From WaDataTable
Without actually timing the two versions against one another, you can only speculate....
I hope bet that version 1 (BatchReader) will be faster, since you only get one round-trip to the database. Version 2 requires three distinct round-trips - one each for every query you execute.
But again: you can only really tell if you measure.
Marc
Oh, PS: of course in a real-life scenario it would also help so limit the columns returned, e.g. don't use SELECT * but instead use SELECT (list of fields) and keep that list of fields as short as possible.