How can I check that a SQL query has no result? - java

As written in the title, I check my SQL database with following method:
public String[] getRecord(String category){
String[] record = new String[3];
Cursor crsRecord = sqliteDatabase.rawQuery(QUERY_GET_RECORD + category, null);
int i=0;
while(crsRecord.moveToNext()){
record[i] = crsRecord.getString(0);
i++;
}
return record;
}
Now it could be that the line:
Cursor crsRecord = sqliteDatabase.rawQuery(QUERY_GET_RECORD + category, null);
has no result, because I have no appropriate data in my database. How can I check that I have no result?

cursor.moveToFirst();
if (cursor.isAfterLast()){
// You have no results
}
Or, you could just change your code to this:
while(!crsRecord.isAfterLast()){
// Instead of using an int literal to get the colum index,
// use the getColumnIndex method
int index = crsRecord.getColumnIndex(COLUMN_NAME);
if (index == -1) {
// You don't have the column-- do whatever you need to do.
}
else {
record[i] = crsRecord.getString(index);
i++;
}
crsRecord.moveToNext();
}
If there are no records, the while loop never starts.

Related

Index in for method is not increasing

Ok this might seem easy but its been bugging my mind for days and I honestly don't know why it the index wont increase and get the other data. I dont know where to but the return. I placed it in 2 lines and the first one only gives the first row of data from the database and the second one only gives the last one from the database. (See commented out lines below). How to get each row that fits the if-statements?
Here's my code:
public Object[] populateTable(ArrayList<Outlet> outletList, String selection, int size, int monthCtr, String selDay){
for(int i = 0; i<outletList.size(); i++){
if(outletList.get(i).getCity().equalsIgnoreCase(selection)){
if(outletList.get(i).getStatus().equals("ACTIVE")){
bar = outletList.get(i).getBarangay();
code = Integer.toString(outletList.get(i).getCode());
name = outletList.get(i).getName();
data = new Object[]{bar, name, code};
//return data ->gives the first one in the database
}
}
}
}
//return data -> gives the last one in the database
}
You need to save all your results in another array and return that instead.
public Object[] populateTable(ArrayList<Outlet> outletList, String selection, int size, int monthCtr, String selDay)
{
List<object> result = new List<object>();
for(int i = 0; i<outletList.size(); i++)
{
if(outletList.get(i).getCity().equalsIgnoreCase(selection))
{
if(outletList.get(i).getStatus().equals("ACTIVE"))
{
bar = outletList.get(i).getBarangay();
code = Integer.toString(outletList.get(i).getCode());
name = outletList.get(i).getName();
data = new Object[]{bar, name, code};
result.Add(data);
}
}
}
return result.ToArray();
}
try this:
public List<Outlet> populateTable(ArrayList<Outlet> outletList, String selection, int size, int monthCtr, String selDay){
List<Outlet> data = new ArrayList<Outlet>();
for(int i = 0; i < outletList.size(); i++){
if(outletList.get(i).getCity().equalsIgnoreCase(selection) &&
outletList.get(i).getStatus().equals("ACTIVE")){
data.add(outletList.get(i));
}
}
return data;
}
Your problem here is as follow:
Your first return statement, will exit the for loop, and return
the first object, as your results have shown.
Your second return statement, will, as you have explained, only
return the last record that was iterated over in the for loop.
Your third problem is on this line data = new Object[]{bar, name,
code};. After every loop, you instantiate the data object to a new
array of objects, instead of adding the values to the array, so essentially, you are always creating an array of objects with 1 item in it, the last one that was iterated.
If you want to return all objects in the array, you should try the following:
public Object[] populateTable(ArrayList<Outlet> outletList, String selection, int size, int monthCtr, String selDay)
{
Object[] result = new Object[outletList.size()];
for (int i = 0; i < outletList.size(); i++)
{
if (outletList.get(i).getCity().equalsIgnoreCase(selection))
{
if (outletList.get(i).getStatus().equals("ACTIVE"))
{
bar = outletList.get(i).getBarangay();
code = Integer.toString(outletList.get(i).getCode());
name = outletList.get(i).getName();
var data = new { bar, name, code };
result[i] = data;
}
}
}
return result;
}

Return Count(*) in Android SQLite table

Here is my simple function:
public int countCats(String tableName) {
int catCount = 0;
Cursor cursor = database.rawQuery("SELECT COUNT(*) FROM " + MySQLiteHelper.TABLE_CAT, null);
if (cursor != null) {
catCount = cursor.getColumnIndex("COUNT");
}
return catCount;
}
There are 11 rows int this table. But this function returns -1. How is appropriate way to handle this?
EDIT:
I have updated to this:
public int countCats(String tableName) {
int catCount = 0;
Cursor cursor = database.rawQuery("SELECT COUNT("+ MySQLiteHelper.COLUMN_CAT+ ") FROM " + MySQLiteHelper.TABLE_CAT, null);
if (cursor.moveToFirst()) {
catCount = cursor.getInt(0);
}
cursor.close();
return catCount;
}
Now I get 0;
You're only asking for the column index for a column COUNT that does not exist in the cursor. Hence -1 is returned.
To retrieve the count value, move the cursor to the first row and get the first column value:
if (cursor.moveToFirst()) {
catCount = cursor.getInt(0);
}
(A COUNT(*) query will always have a result row but it's a good habit to check the result of moveToFirst() anyway.)
You forget to call
cursor.moveToFirst();
You are just looking for the index of the result and not the value itself.
So now you know that the value you like to know is in the first column. Now you have to go to the first row and take that value.
cursor.moveToFirst();
int count=cursor.getInt(1);

NullPointerException while counting the number of rows using COUNT() in SQLite helper

I am getting NullPointerException whle performing COUNT() in SQLite. please see the following code -
public int getrcofpersons() {
// TODO Auto-generated method stub
SQLiteDatabase myDB;
int values = 0;
int count = 0;
try {
myDB=this.openDataBase();
Cursor c=myDB.rawQuery("select count(PersonID) from Persons;",null);
if (c != null ) {
String h = "";
c.moveToFirst();
count = c.getInt(c.getColumnIndex("PersonID"));
// put your code to get data from cursor
}
if(c != null) {
c.close();
myDB.close();
}
} catch(SQLException sqle) {
throw sqle;
}
System.out.println(count + " is the rowcount of persons.");
return count;
}
This function is returning Null value. Even System.out.println(count + " is the rowcount of persons."); also showing the count value as 0, which is the initialized value. Now I cannot post the logcat, because this code snippet is associated with many other functionalities, that you might not understand. So, please, tell me if I did any mistake in this code.
Please see the following code. This code is calling the above method(which is in the helper.java).
adapter.java :
public int getrowcountofpersons() {
// TODO Auto-generated method stub
int rc = 0;
try {
//open();
rc = mDbHelper.getrcofpersons(); //Here the nullPointerException is raised.
// close();
}
catch (Exception e)
{Log.v("getrowcountofpersons()","5");
Log.v("Error in getrowcountofpersons() of adapter : ",e.toString());
}
Log.v("getrowcountofpersons()","6");
System.out.println(rc + " is the rowcount of persons in adapter.");
return rc;
}
Thanks in advance.
Change
count = c.getInt(c.getColumnIndex("PersonID"));
to
count = c.getInt(0);
There is no column name PersonID into your Cursor object c. And this will have only one column so you can retrieve that column using 0 (ZERO) index.
After code update :-
Check if mDbHelper is null or not. This might be null. So check if you are initiating the mDbHelper object.

Loop through Resultset depending on what columns are getting generated

I am working on a multithreaded project in which I need to randomly find columns that I will be using in my SELECT sql and then I will be executing that SELECT sql query.
After finding those columns-
I need to see whether the id is between the valid range, if it in between the Valid Range, then loop around the resultset using those columns from the columnsList and get the data back and store in a variable.
else if id is not in the valid range, I need to check I am not getting any data back from the resultset. But somehow if I am getting the data back and flag is true to stop the program, then exit the program. Else if I am getting the data back but flag is false to stop the program, then count how many of those happening.
Below is my code-
private volatile int count;
#Override
public void run() {
.....
final String columnsList = getColumns(table.getColumns());
....
rs = preparedStatement.executeQuery();
....
if (Read.endValidRange < id && id < Read.startValidRange) {
while (rs.next()) {
for(String column: columnsList.split(",")) {
System.out.println(column + ": " + rs.getString(column));
}
}
} else {
if(rs.next() && Read.flagTerminate) {
System.exit(1);
} else {
count++;
}
}
....
}
/**
* A simple method to get the column names in the order in which it was
* inserted
*
* #param columns
* #return
*/
private String getColumns(final List<String> columns) {
List<String> copy = new ArrayList<String>(columns);
Collections.shuffle(copy);
int rNumber = random.nextInt(columns.size());
List<String> subList = copy.subList(0, rNumber);
Collections.sort(subList, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return columns.indexOf(o1) < columns.indexOf(o2) ? -1 : 1;
}
});
return StringUtils.join(subList, ",");
}
Problem Statement-
I am not able to understand how should I iterate through the resultset as every time I will be having different columns in my SELECT sql depending on what is getting generated. And apart from that how can I make it more cleaner in the if else loop.
OK..
You can have the Randomly generated columns saved in a String array..and then while iterating via resultset you use that array...as follows:
UPDATE
You should not include those columns in select statement..Instead you should select all columns in select statement using *...and then get the value of that column in rs.next() loop...
rs = con.executeQuery("Select * from tablename");
while(rs.next())
{
for (String col : columnsList )
{
System.out.print(rs.get(col));
}
System.out.print("\n");
}
UPDATE1
You need your critical code section written within run() to be wrapped in synchronized block so as to avoid Race Condition as follows:
private volatile int count;
#Override
public void run() {
.....
while (!Read.flagTerminate)
{
synchronized(this)
{
if (!Read.flagTerminate)
{
String columnsList = getColumns(table.getColumns());
....
rs = preparedStatement.executeQuery();
....
if (Read.endValidRange < id && id < Read.startValidRange)
{
while (rs.next())
{
for(String column: columnsList.split(","))
{
System.out.println(column + ": " + rs.getString(column));
}
}
}
else
{
while (rs.next())
{
count++;
}
}
}
}
}
System.exit(0);//it implies that flag = true;
....
}
/**
* A simple method to get the column names in the order in which it was
* inserted
*
* #param columns
* #return
*/
private String getColumns(final List<String> columns) {
List<String> copy = new ArrayList<String>(columns);
Collections.shuffle(copy);
int rNumber = random.nextInt(columns.size());
List<String> subList = copy.subList(0, rNumber);
Collections.sort(subList, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
return columns.indexOf(o1) < columns.indexOf(o2) ? -1 : 1;
}
});
return StringUtils.join(subList, ",");
}
What about this:
if (Read.endValidRange < id && id < Read.startValidRange) {
while (rs.next()) {
for (String column : columnsList.split(",")) {
System.out.println(column + ": " + rs.getString(column));
}
}
} else if (rs.next()) {
if (Read.flagTerminate) {
System.exit(1);
} else {
count++;
}
}
I have also updated the if-else conditions as per my understanding of the question.

Can I make SQLiteDatabase complain about missing parameters?

Recently, I've had a few bugs because of code like this:
Cursor myCursor = myDb.rawQuery(
"SELECT ... " +
" FROM ...complicated join... " +
" WHERE field1 = ? AND (field2 = ? OR field3 = ?) ",
new String[] {myField1, myField2}); // Oops, forgot about field3
When this happens, the query just silently ignores the missing parameter, causing bugs to go unnoticed. Is there some pedantic setting or anything else that I can use to make SQLite scream (at run-time) when the number of placeholders and the number of fields do not match?
I know that I could build my own wrapper, but I'm wondering if there's something built-in...
Android is basically just passing the args unchecked to native sqlite, see http://www.sqlite.org/c3ref/bind_blob.html
If something is not bound it is simply considered to be bound to NULL. Binding too much should result in an error though
I don't know of / have not seen any debug option in Android's source for that kind of checks but you could probably write some code that checks your sql syntax:
SQLiteChecker mDbChecked = new SQLiteChecker(mDb);
Cursor c = mDbChecked.rawQuery("select complicated from table where stuff=?",
new String[] {"one", "two"});
where SQLiteChecker would be something along the lines of
/**
* Simple Delegate for SQLiteDatabase
*/
public class SQLiteChecker {
private final SQLiteDatabase mDbDelegate;
public SQLiteChecker(SQLiteDatabase db) {
mDbDelegate = db;
}
// ------------ Delegate methods --------------------//
public int delete(String table, String whereClause, String[] whereArgs) {
checkSQL(whereClause, whereArgs);
return mDbDelegate.delete(table, whereClause, whereArgs);
}
public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
checkSQL(whereClause, whereArgs);
return mDbDelegate.update(table, values, whereClause, whereArgs);
}
public void execSQL(String sql, Object[] bindArgs) throws SQLException {
checkSQL(sql, bindArgs);
mDbDelegate.execSQL(sql, bindArgs);
}
public Cursor rawQuery(String sql, String[] selectionArgs) {
checkSQL(sql, selectionArgs);
return mDbDelegate.rawQuery(sql, selectionArgs);
}
// add more if you need
// -------------- checking logic -------------------//
private static void checkSQL(String query, Object[] args) {
// bit unreliable but simple:
// just check if amount of ? matches args.length
int expected = countChar(query, '?');
int actual = args != null ? args.length : 0;
if (expected != actual) {
Log.e("CHECK", "You seem to have messed up [" + query + "]");
Log.e("CHECK", "expected:" + expected + " actual:" + actual);
}
}
private static int countChar(String string, char ch) {
if (string == null) return 0;
int count = 0;
for (int i = 0; i < string.length(); i++) {
if (string.charAt(i) == ch)
count++;
}
return count;
}
}

Categories

Resources