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

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.

Related

Unable to write values into excel using multiple workbook.write methods

The below code is working without any runtime error if I call the owb.write(fileOut) and fileOut.close() method only once at at the ending (commented as write and close positioning) but the problem here is that the first value to be set when k=1, is not being printed in the workbook. It works fine when the iteration is in other columns and k=1.Only the first iteration is not being printed. Rest of the values are being set correctly.
I tried using multiple workbook.write() method. If you look at the below code, commented as [1], I had to invoke owb.write(fileOut) separately in the if condition(commented as if condition[1]) and else condition(commented as else condition [2]) because as I said, first value was not getting set in the workbook. I am getting the following runtime error while trying to execute the code in this scenario: Fail to save: an error occurs while saving the package : The part /docProps/app.xml fail to be saved in the stream with marshaller org.apache.poi.openxml4j.opc.internal.marshallers.DefaultMarshaller#3740f768
for(int i=0;i<noOfCols1;i++)
{
for(int j=1;j<=noOfRows1;j++)
{
value1 = formatter.formatCellValue(sheet1.getRow(j).getCell(i));
for(int m=1;m<=noOfRows2;m++)
{
value2 = formatter.formatCellValue(sheet2.getRow(m).getCell(i));
value1= value1.trim();
value2=value2.trim();
int value2Position = sheet2.getRow(m).getCell(i).getRowIndex();
if(!positions.contains(value2Position))
{
if(value1.contentEquals(value2))
{
positions.add(value2Position);
matched = true;
}
else{
matched = false;
}
}
if(matched==true)
{
break;
}
}
if(matched == false)
{
int k=1;
if(cFilledPositions.isEmpty()) //If condition[i]
{
rowHead = sheet.createRow((short)k);
rowHead.createCell(i).setCellValue(value1);
owb.write(fileOut); //[1]
}
else //else condition [1]
{
int l = cFilledPositions.size()-1;
k = cFilledPositions.get(l)+1;
rowHead = sheet.createRow((short)k);
rowHead.createCell(i).setCellValue(value1);
owb.write(fileOut);
}
cFilledPositions.add(k);
}
matched = false;
}
cFilledPositions.clear();
positions.clear();
}
//write and close positioning
fileOut.close();
I tried debugging and found that the createRow() method deletes the values previously created if called again on the same row.
To elaborate this, suppose the sheet.createRow() sets the value of a cell in the first iteration, and when it finishes its iteration in the j for loop, the cFilledPositions list is cleared and while it comes back after going to the main loop, 'cFilledPositionswill be empty and the integerkwill again be initialized to1. This is whencreateRow(k)` which is 1 is called again. This would flush out the previously existing values in the 1st row. I am trying to figure out a work around for this and will edit my answer with the solution if I my code works.
Below was the work around. I checked if the row is empty. The createRow function is called only when the row is empty. I have added the comments for the new code.
for(int i=0;i<noOfCols1;i++)
{
for(int j=1;j<=noOfRows1;j++)
{
value1 = formatter.formatCellValue(sheet1.getRow(j).getCell(i));
for(int m=1;m<=noOfRows2;m++)
{
value2 = formatter.formatCellValue(sheet2.getRow(m).getCell(i));
value1= value1.trim();
value2=value2.trim();
int value2Position = sheet2.getRow(m).getCell(i).getRowIndex();
if(!positions.contains(value2Position))
{
if(value1.contentEquals(value2))
{
positions.add(value2Position);
matched = true;
}
else{
matched = false;
}
}
if(matched==true)
{
break;
}
}
if(matched == false)
{
int k=1;
if(cFilledPositions.isEmpty())
{
try{
isEmpty = checkIfRowIsEmpty(sheet,k,formatter);
if(isEmpty)
{
rowHead = sheet.createRow(k);
}
rowHead.createCell(i).setCellValue(value1);
}
catch (Exception e){
try{
rowHead = sheet.createRow(k);
rowHead.createCell(i).setCellValue(value1);
}
catch (Exception e1){
}
}
}
else
{
int l = cFilledPositions.size()-1;
k = cFilledPositions.get(l)+1;
try{
isEmpty = checkIfRowIsEmpty(sheet,k,formatter);
if(isEmpty)
{
rowHead = sheet.createRow(k);
}
rowHead.createCell(i).setCellValue(value1);
}
catch (Exception e)
{
try{
rowHead = sheet.createRow(k);
rowHead.createCell(i).setCellValue(value1);
}
catch (Exception e1){
}
}
}
cFilledPositions.add(k);
}
matched = false;
}
cFilledPositions.clear();
positions.clear();
}

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

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.

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;
}
}

Java JDBC - prepared statement for bulk insertion using merge sort

I am using JDBC prepared statement for bulk insertion. I am calling ps.execute() method. If it fails then i am calling a method where i am passing the list of parameters and the prepared statement. I am using merge sort technique to divide the list and then trying to insert the records, but not successfull.
Here is my code;
from executePrepareStatement method i am calling
this.executeInsertStatement(query, myCollection, 0, myCollection.size());
// executeInsertStatement method
public void executeInsertStatement1(String query, List myCollection, int sIndx, int eIndx) throws DBException,SQLException {
int startIndx = sIndx, endIndx = eIndx, mid = 0;
try {
try{
if(conn.isClosed())
new DataService(CoreConstants.TARGET);
} catch (Exception e) { }
if(startIndx >= endIndx) {
return;
}
conn.setAutoCommit(false);
if (query != null) {
mid = (startIndx + endIndx) / 2;
ps = conn.prepareStatement(query);
executeInsertStatement(query, myCollection, startIndx, mid);
executeInsertStatement(query, myCollection, mid+1, endIndx);
//int end_low = mid;
//int start_high = mid + 1;
if(mid < endIndx)
endIndx = mid;
for (int i = 0; i < endIndx; i++) {
List list = (List) myCollection.get(i);
int count = 1;
for (int j = 0; j < list.size(); j++) {
if(list.get(j) instanceof Timestamp) {
ps.setTimestamp(count, (Timestamp) list.get(j));
} else if(list.get(j) instanceof java.lang.Character) {
ps.setString(count, String.valueOf(list.get(j)));
}
else {
ps.setObject(count, list.get(j));
}
count++;
}
try {
ps.execute();
} catch (Exception e) {
rollback();
}
}
}
} catch (Exception e) {
rollback();
} finally{
try {
if (ps != null) {
ps.close();
ps = null;
}
} catch (Exception ex) {
}
}
}
Thanks
I don't think you're on the right track by using a merge sort. I understand that you're trying to achive your solution using the concept of divide and conquer but I think you're making the problem harder (and more confusing/complex) than it really needs to be.
If I understand correctly, you have got a data set that you would want to insert into your database. And you would want to do it in bulk. PreparedStatement let's you do that by using a couple of neat methods: addBatch() and executeBatch()
Here's an outline of how I would have tried to implement your requirement:
I would set a batch limit i.e. the number of statements in my batch when I would like to execute the batch. Unless I reach this limit (which I can very well track by using a counter), I would continue to add to the batch
Once I hit the limit, I execute the batch, reset the counter, clear the batch and redo Step #1
This would continue till I'm done with my entire data set. Finally I would end by either committing the data to the database or even performing a rollback, based on my requirement.
Have a look at this answer for an example of how you might go about and implement this.

Categories

Resources