Blackberry sqlite - Cannot prepare already prepared statement exception - sqlite

In blackberry sqlite while executing the below code i getting exception "Cannot prepare already prepared statement"
public Department[] getDepartment()
{
Department[] department = null;
try
{
database = DatabaseFactory.open(myURI);
Statement st = database.createStatement("SELECT code, name, status FROM Department");
st.prepare();
Cursor c = st.getCursor();
Row r;
int i = 0;
department = new Department[i];
while(c.next())
{
r = c.getRow();
i++;
Department dept = (Department) r.getObject(i);
department[i] = dept;
}
st.close();
database.close();
}
catch ( Exception e )
{
System.out.println("Exception occured --------------" +e.getMessage());
}
return department;
}
anybody know solution for this

The st.prepare() is only necessary if the statement is not prepared, which means:
The statement references an external variable
The statement references a computed variable
In this case, neither is the case, so the statement is redundant.
References
SQLite: File History - prepare.c
Getting “Re-preparing already prepared query” warning with caching enabled · Issue #581 · Netflix/astyanax · GitHub
SQLite: View Ticket - Repreparation errors are always returned as SQLITE_SCHEMA

Related

OrientDB execute script asynchronously and fetch records in a lazy fashion

Currently, we are using the Document API in OrientDB version 2.2. Let us suppose we have a class Company and a class Employee. Let's suppose we are interested in all Companies with at least one employee having a name from an arbitrary list. Employees are defined as LINKEDLISTs in our Company schema.
Our query would look smth like this:
select from Company where employees in (select from Employee where name in ["John", "Paul"])
Currently we have defined the following two indexes:
Company.employees (index on the employee links (their #rid)) -> dictionary hash index and
Employee.name -> notunique index
When executing the above query with explain we see that only the second index Employee.name is used, since we did not define the above indexes as a compound index. AS far as I could understand compound indexes across different classes like in our case are not supported in Orient 2.x.
Queries like this:
select from Company let $e = select from employees where name in ["John", "Paul"] where employees in $e
do not solve our problem either.
Searching across different blogs revealed two suggestions so far:
trying to define a compound index via inheritance by introducing a parent class on employee and company and defining the above two indexes on that
https://github.com/orientechnologies/orientdb/issues/5069
bundle the two queries in a batch scrip like this:
https://github.com/orientechnologies/orientdb/issues/6684
String cmd = "begin\n";
cmd += "let a = select from Employees where name " + query + "\n";
cmd += "let b = select from Company where employees in $a\n";
cmd += "COMMIT\n";
cmd += "return $b";
Suggestion 1 did not work for us.
Suggestion 2. worked. Both indexes have been used in each separate query, but then we ran into the next limitation of Orient. Batch scripts seem to be executed only synchronously, meaning that we can only get the results as a list all at once and not one by one in a lazy fashion, which in our case is a NO GO due to the memory overhead.
One naive workaround we tried is as follows:
public class OCommandAsyncScript extends OCommandScript implements OCommandRequestAsynch{
public OCommandAsyncScript(String sql, String cmd) {
super(sql, cmd);
}
#Override
public boolean isAsynchronous() {
return true;
}
private void containsAtLeastOne(final #Nonnull ODatabaseDocumentTx documentTx,
final #Nonnull Consumer<Company> matchConsumer,
final #Nonnull String queryText
) throws TimeoutException {
String cmd = "begin\n";
cmd += "let a = select from Employee where name " + queryText + "\n";
cmd += "let b = select from Company where employees in $a\n";
cmd += "COMMIT\n";
cmd += "return $b";
final OCommandHandler resultListener = new OCommandHandler(documentTx, (document -> {
final Company companies = document2model(document);
matchConsumer.accept(company);
}));
OCommandAsyncScript request = new OCommandAsyncScript("sql", cmd);
request.setResultListener(resultListener);
documentTx.command(request).execute();
...
}
}
public class OCommandHandler implements OCommandResultListener {
private final ODatabaseDocumentTx database;
private final Consumer<ODocument> matchConsumer;
public OCommandHandler(
final #Nonnull ODatabaseDocumentTx database,
final #Nonnull Consumer<ODocument> matchConsumer
) {
this.database = database;
this.matchConsumer = matchConsumer;
}
#Override
public boolean result(Object iRecord) {
if (iRecord != null) {
final ODocument document = (ODocument) iRecord;
/*
Result handler might be asynchronous, if document is loaded in a lazy mode,
database will be queries to fetch various fields. Need to activate it on the current thread.
*/
database.activateOnCurrentThread();
matchConsumer.accept(document);
}
return true;
}
...
}
The approach of defining a custom OCommandAsyncScript did not work unfortunately. When debugging the OStorageRemote class of Orient it seems that no partial results could be read, Here the respective extract from the source code:
public Object command(final OCommandRequestText iCommand) {
....
try {
OStorageRemote.this.beginResponse(network, session);
List<ORecord> temporaryResults = new ArrayList();
boolean addNextRecord = true;
byte status;
if(asynch) {
while((status = network.readByte()) > 0) {
ORecord record = (ORecord)OChannelBinaryProtocol.readIdentifiable(network);
if(record != null) {
switch(status) {
case 1:
if(addNextRecord) {
addNextRecord = iCommand.getResultListener().result(record);
database.getLocalCache().updateRecord(record);
}
break;
case 2:
if(record.getIdentity().getClusterId() == -2) {
temporaryResults.add(record);
}
database.getLocalCache().updateRecord(record);
}
}
}
}
}
Network.readbyte() is always null, hence no records could be fetched at all.
Is there any other workaround how we could execute a sql script in asynchronus mode and retrieve results in a lazy fashion preventing the generation of large lists on our application side?

Cursor inside another cursor in sqlite db

I have the below code where I am using nested cursors. Both of them are not null but I am getting error
"android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0" on the inner cursor.
Cursor cursor3 = null;
Cursor cursor2 = db.getAllFriendsChat();
cursor2.moveToFirst();
while (!cursor2.isAfterLast()) {
String number = cursor2.getString(cursor2.getColumnIndexOrThrow(ChatModel.COLUMN_CHAT_SENT_TO));
cursor3 = db.getName(number);
String name = cursor3.getString(cursor3.getColumnIndexOrThrow(db.KEY_NAME));
db.insertList(name, number);
cursor3.close();
cursor2.moveToNext();
}
cursor2.close();
getName() Method:
public Cursor getName(String phone) {
SQLiteDatabase db = this.getWritableDatabase();
Cursor c = db.rawQuery("select * from " + TABLE_STUDENTS + " where phone_number = " + phone, null);
if (c != null) {
c.moveToFirst(); //***I see that this statement is executed.***
}
return c;
}
I am unable to understand where I am doing mistake. Is there a different way to handle nested cursors in sqlite db. Pls help.
Thanks !
rawQuery() never returns null.
To test whether a cursor is empty, you have to check whether moveToFirst() succeeds, or call isAfterLast().

How to check table is empty with count(*)

I am trying to check if a table is empty. I code this method:
public boolean checkIfNULL()
throws SQLException, ClassNotFoundException {
boolean flag=false;
System.out.println("Checking if table is empty...");
String sq = "select count(*) from TABLE1";
try {
Class.forName(typeDB);
c = DriverManager.getConnection(path);
stm = c.prepareStatement(sq);
PreparedStatement stm = c.prepareStatement(sq);
int rowsAffected = stm.executeUpdate();
if(rowsAffected == 0)
flag=true;
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
if (stm != null) {
stm.close();
}
if (c != null) {
c.close();
}
}
return flag;
}
but sth wrong is hapenning and I get an error message
Query returns results
Exceptionn: java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (Connection is closed)
How I check the returning value of check?
UPDATE 1:
Instead of the query above, I tried also SELECT EXISTS(SELECT 1 FROM TABLE1)
but the same is happening..
UPDATE 2:
I used this:
ResultSet rs = stm.executeQuery();
if(!rs.next())
flag=true;
else
System.err.println("ERROR - The table has records...");
and it prints the ERROR - "The table has records...". How is this possible? I see the table through SQLite manager and it is empty!
You are executing a SELECT, so you need to use executeQuery, not executeUpdate. executeUpdate is for statements like UPDATE, DELETE and INSERT, executeQuery is for executing statements that return a result set (like SELECT).
You need to execute a select statement, and do:
try (ResultSet rs = stm.executeQuery()) {
rs.next(); // You always have a row, with the count
int count = rs.getInt(1);
flag = count == 0;
}
The code in your update won't work, because if you do a SELECT count(*) FROM table, then you always have one row (with the count).

Dapper using ODBC store procedure Input parm always promt #XXX was not supplied

I need help from All Dapper master.
I have been learning using Dapper since one month ago, but I have error when executing query using ODBC SP.
The code originally was written by someone(DapperExample) but not using ODBC, thanks to the writer I forgot your name.
My SP:
CREATE PROCEDURE SP_GET_FIND_EMPLOYEES (#EmpID INT)
AS
BEGIN
SET NOCOUNT ON;
SELECT * FROM tblEmployee WHERE EmpID = #EmpID
END
GO
My Code
public class EmployeeDashBoard : IEmployeeDashBoard
{
private IDbConnection _db;
string connStr2 = WebConfigurationManager.ConnectionStrings["DapperExample"].ConnectionString;
public EmployeeDashBoard()
{
}
public Employee Find(int id)
{
//type b, by sp
using (IDbConnection connection = new OdbcConnection(connStr2))
{
var p = new DynamicParameters();
p.Add("#EmpID", id);
Employee result = this._db.Query<Employee>("dbo.SP_GET_FIND_EMPLOYEES", new { #EmpID = id }, commandType: CommandType.StoredProcedure).Single();
return result;
}
}
}
Error:
ERROR [42000] [Microsoft][SQL Server Native Client 11.0][SQL Server]Procedure or function 'SP_GET_FIND_EMPLOYEES' expects parameter '#EmpID', which was not supplied.
Thanks in Advance.
Masa Sih
I Solved by my self, I'm using Sybase ODBC SP, ( God Job Sam ), now I can avoid entity framework in the feature.
Here the tricks:
Solved: SP_GET_FIND_EMPLOYEES ?
using (IDbConnection connection = new OdbcConnection(connStr2))
{
var p = new DynamicParameters();
p.Add("?EmpID?", id.ToString());
Employee result = this._db.Query<Employee>("dbo.SP_GET_FIND_EMPLOYEES ?", p, commandType: CommandType.StoredProcedure).Single();
return result;
}
Your implementation for ODBC named parameters is incorrect. You encase the named parameter with question marks in your statement and create the named parameter without the question marks. The question marks are used by Dapper to parse the statement to find the names.
p.Add("EmpID", id.ToString());
Employee result = this._db.Query<Employee>("dbo.SP_GET_FIND_EMPLOYEES ?EmpID?", p, commandType: CommandType.StoredProcedure).Single();
See this answer for more information: https://stackoverflow.com/a/26484944/6490042

Dapper and Downward Integer Conversion

I am checking out v1.25 of Dapper with Sqlite via System.Data.Sqlite. If I run this query:
var rowCount = dbc.Query<int>("SELECT COUNT(*) AS RowCount FROM Data").Single();
I get the following error: System.InvalidCastException: Specified cast is not valid
This is because Sqlite returns the above value as an Int64, which I can verify with the following code. This will throw "Int64":
var row = dbc.Query("SELECT COUNT(*) AS RowCount FROM Data").Single();
Type t = row.RowCount.GetType();
throw new System.Exception(t.FullName);
Now, the following code will actually handle the downward conversion from Int64 to Int32:
public class QuerySummary
{
public int RecordCount { get; set; }
}
var qs = dbc.Query<QuerySummary>("SELECT COUNT(*) AS RecordCount FROM Data").Single();
rowCount = qs.RecordCount;
throw new System.Exception(rowCount.ToString());
When I throw this exception, it gives me the actual row count, indicating that Dapper handled the conversion for me.
My question is, why is it that dbc.Query<int> does not handle the downward conversion in a similar way to dbc.Query<QuerySummary>? Is this intended behavior?
No, that is not intentional. I've committed and pushed changes to github which make the following pass (it fails on 1.25); it should appear on NuGet at some point soon too:
// http://stackoverflow.com/q/23696254/23354
public void DownwardIntegerConversion()
{
const string sql = "select cast(42 as bigint) as Value";
int i = connection.Query<HasInt32>(sql).Single().Value;
Assert.IsEqualTo(42, i);
i = connection.Query<int>(sql).Single();
Assert.IsEqualTo(42, i);
}

Resources