-1

I'm trying to load data from my table in sqlite Database to my ExpandableListView inside my activity. I followed the answer from this question Android ExpandableListView and SQLite Database.

My parent list will show MVP_INDUSTRY_TYPE Column depends on date Selected, My child list will show MVP_BRCH_CODE_NAME and MVP_BRCH_ADDRESS.

DatabaseHelper. java

package com.example.spmapp;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import androidx.annotation.Nullable;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;


public class DataBaseHelper extends SQLiteOpenHelper {

    public static final String MVP_TBL = "MVP_tbl";
    public static final String MVP_BRCH_CODE_NAME = "MVP_BRCH_CODE_NAME";
    public static final String MVP_ID = "MVP_ID";
    public static final String MVP_BRCH_ADDRESS = "MVP_BRCH_ADDRESS";
    public static final String MVP_AREA = "AREA";
    public static final String MVP_AREA_CODE = "AREA_CODE";
    public static final String MVP_INDUSTRY_TYPE = "MVP_INDUSTRY_TYPE";
    public static final String token = "TOKEN";
    public static final String MVP_DATE = "SCHEDULED_DATE";
    public static final String MVP_CLASS_ID = "MVP_CLASS_ID";



    public DataBaseHelper(@Nullable Context context) {
        super(context, "taggedList.db", null, 1);

    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        String createMVPVirtualTableStatement = "CREATE VIRTUAL TABLE IF NOT EXISTS " + MVP_TBL + " USING FTS3(" + MVP_BRCH_CODE_NAME + ", " + MVP_ID + " , " + MVP_BRCH_ADDRESS + ", " + MVP_AREA + ", " + MVP_AREA_CODE + ", " + MVP_INDUSTRY_TYPE + ", " + token + ", " + MVP_DATE + ", " + MVP_CLASS_ID + ")";
        sqLiteDatabase.execSQL(createMVPVirtualTableStatement);

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        onCreate(sqLiteDatabase);
    }
    public Cursor getSelectedParentMVPDate(String txtMVPDate){
        SQLiteDatabase db = this.getWritableDatabase();
        String query = "Select * from "+MVP_TBL+" WHERE " +MVP_DATE+ " LIKE '%"+txtMVPDate+"%' LIMIT 50";
        return db.rawQuery(query, null);
    }
    public Cursor getSelectedChildMVPDate(String MVPIndustry){
        SQLiteDatabase db = this.getWritableDatabase();
        String query = "Select * from "+MVP_TBL+" WHERE " +MVP_INDUSTRY_TYPE+ " LIKE '%"+MVPIndustry+"%' LIMIT 50";
        return db.rawQuery(query, null);
    }

}

MasterVisitPlan.java

public class MasterVisitPlan extends AppCompatActivity implements AdapterView.OnItemSelectedListener,CalendarAdapter.OnItemListener {

    private boolean isBackPressedOnce = false;

    public static String email;
    public static String VisitDate;
    public static String ItemBrnchCodeName;
    public static String mrCode;
    public static String ClassID;
    private static String token;
    private static String bearerToken;
    public static int counterVisit;
    private RecyclerView calendarRecyclerView;
    private LocalDate selectedDate;
    private TextView monthYearText;


    TextView empName, empPos, date;

    GoogleSignInClient mGoogleSignInClient;

    DrawerLayout drawerLayout;

    ImageView gps, empPhoto;

    ConstraintLayout calendar;

    DataBaseHelper dataBaseHelper;
    private Cursor mGroupsCursor; // cursor for list of groups (list top nodes)
    private int mGroupIdColumnIndex;
    private MyExpandableListAdapter mAdapter;

    SimpleCursorAdapter sca;
    Cursor csr;
    SearchView searchView;
    ListView Searchlstview;


    @Override
    protected void onCreate(Bundle savedIntanceState) {
        super.onCreate(savedIntanceState);
        setContentView(R.layout.activity_master_visit_plan);
        initWidgets();
        selectedDate = LocalDate.now();
        setMonthView();
        setOrRefreshListView();
        getCurrentDate();

        dataBaseHelper = new DataBaseHelper(MasterVisitPlan.this);
        fillMVPdata();  
    }

    private void fillMVPdata(){
        mGroupsCursor = dataBaseHelper.getSelectedParentMVPDate(date.getText().toString());
        startManagingCursor(mGroupsCursor);
        mGroupsCursor.moveToFirst();


        ExpandableListView Selectedlstview = (ExpandableListView) findViewById(R.id.MVPListitem);
        mAdapter = new MyExpandableListAdapter(mGroupsCursor, this,

                R.layout.mvp_list_parent,
                R.layout.mvp_list_child,
                new String[] {DataBaseHelper.MVP_INDUSTRY_TYPE},
                new int[] {R.id.txtMVPParent},
                new String[] {DataBaseHelper.MVP_BRCH_CODE_NAME, DataBaseHelper.MVP_BRCH_ADDRESS},
                new int[] {R.id.txtviewBrnchCodeName, R.id.txtviewBrchAddr});

                Selectedlstview.setAdapter(mAdapter);

    }
    public class MyExpandableListAdapter extends SimpleCursorTreeAdapter {
        public MyExpandableListAdapter(Cursor cursor, Context context,int groupLayout, int childLayout, String[] groupFrom,
                                       int[] groupTo, String[] childrenFrom, int[] childrenTo) {
            super(context, cursor, groupLayout, groupFrom, groupTo,
                    childLayout, childrenFrom, childrenTo);
        }

        @Override
        protected Cursor getChildrenCursor(Cursor cursor) {
            @SuppressLint("Range") Cursor childCursor = dataBaseHelper.getSelectedChildMVPDate(cursor.getString(cursor.getColumnIndex("MVP_INDUSTRY_TYPE")));
            startManagingCursor(childCursor);
            childCursor.moveToFirst();
            return childCursor;
        }
    }
}
Ryan Baltazar
  • 15
  • 1
  • 5

1 Answers1

1

Column -1 indicates that the column is not in the Cursor when using the getColumnIndex method.

As the only occurrence of the method, in the provided code, is in the getSelectedChildMVPDate method in the DatabaseHelper class, then that must be where the issue is taking place.

Replicating the essentials of your code with an additional method in DataBaseHelper class :-

public void insertMVPTBLRow(String branchCodeName, long id, String address, String area, String areacode, String industryType, String tkn, String date, String classId) {
    ContentValues cv = new ContentValues();
    cv.put(MVP_BRCH_CODE_NAME,branchCodeName);
    cv.put(MVP_ID,id);
    cv.put(MVP_BRCH_ADDRESS,address);
    cv.put(MVP_AREA,area);
    cv.put(MVP_AREA_CODE,areacode);
    cv.put(MVP_INDUSTRY_TYPE,industryType);
    cv.put(token,tkn);
    cv.put(MVP_DATE,date);
    cv.put(MVP_CLASS_ID,classId);
    this.getWritableDatabase().insert(MVP_TBL,null,cv);
}

and then using the following code in an activity:-

    dataBaseHelper = new DataBaseHelper(this);
    dataBaseHelper.getWritableDatabase().delete(DataBaseHelper.MVP_TBL,null,null);
    dataBaseHelper.insertMVPTBLRow("B1",100,"StreetX","Area1","A001","I001","tkn001",String.valueOf(System.currentTimeMillis()),"CLASS1");
    dataBaseHelper.insertMVPTBLRow("B1",101,"StreetX","Area1","A001","I001","tkn002",String.valueOf(System.currentTimeMillis()),"CLASS1");
    mGroupsCursor = dataBaseHelper.getSelectedParentMVPDate("");
    startManagingCursor(mGroupsCursor);
    mGroupsCursor.moveToFirst();
    Cursor cursor = mGroupsCursor;
    @SuppressLint("Range") Cursor childCursor = dataBaseHelper.getSelectedChildMVPDate(cursor.getString(cursor.getColumnIndex("MVP_INDUSTRY_TYPE")));
    startManagingCursor(childCursor);
    childCursor.moveToFirst();
    DatabaseUtils.dumpCursor(mGroupsCursor);
    DatabaseUtils.dumpCursor(childCursor);
  • Note empty string passed so all rows are extracted.

Results in a successful run with the Log including:-

2022-06-15 10:55:26.892 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@2caa87e
2022-06-15 10:55:26.893 I/System.out: 0 {
2022-06-15 10:55:26.893 I/System.out:    MVP_BRCH_CODE_NAME=B1
2022-06-15 10:55:26.893 I/System.out:    MVP_ID=100
2022-06-15 10:55:26.893 I/System.out:    MVP_BRCH_ADDRESS=StreetX
2022-06-15 10:55:26.893 I/System.out:    AREA=Area1
2022-06-15 10:55:26.893 I/System.out:    AREA_CODE=A001
2022-06-15 10:55:26.893 I/System.out:    MVP_INDUSTRY_TYPE=I001
2022-06-15 10:55:26.893 I/System.out:    TOKEN=tkn001
2022-06-15 10:55:26.893 I/System.out:    SCHEDULED_DATE=1655254526888
2022-06-15 10:55:26.893 I/System.out:    MVP_CLASS_ID=CLASS1
2022-06-15 10:55:26.893 I/System.out: }
2022-06-15 10:55:26.893 I/System.out: 1 {
2022-06-15 10:55:26.893 I/System.out:    MVP_BRCH_CODE_NAME=B1
2022-06-15 10:55:26.893 I/System.out:    MVP_ID=101
2022-06-15 10:55:26.893 I/System.out:    MVP_BRCH_ADDRESS=StreetX
2022-06-15 10:55:26.894 I/System.out:    AREA=Area1
2022-06-15 10:55:26.894 I/System.out:    AREA_CODE=A001
2022-06-15 10:55:26.894 I/System.out:    MVP_INDUSTRY_TYPE=I001
2022-06-15 10:55:26.894 I/System.out:    TOKEN=tkn002
2022-06-15 10:55:26.895 I/System.out:    SCHEDULED_DATE=1655254526889
2022-06-15 10:55:26.895 I/System.out:    MVP_CLASS_ID=CLASS1
2022-06-15 10:55:26.895 I/System.out: }
2022-06-15 10:55:26.895 I/System.out: <<<<<
2022-06-15 10:55:26.895 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@f1451df
2022-06-15 10:55:26.895 I/System.out: 0 {
2022-06-15 10:55:26.895 I/System.out:    MVP_BRCH_CODE_NAME=B1
2022-06-15 10:55:26.895 I/System.out:    MVP_ID=100
2022-06-15 10:55:26.895 I/System.out:    MVP_BRCH_ADDRESS=StreetX
2022-06-15 10:55:26.895 I/System.out:    AREA=Area1
2022-06-15 10:55:26.895 I/System.out:    AREA_CODE=A001
2022-06-15 10:55:26.895 I/System.out:    MVP_INDUSTRY_TYPE=I001
2022-06-15 10:55:26.895 I/System.out:    TOKEN=tkn001
2022-06-15 10:55:26.896 I/System.out:    SCHEDULED_DATE=1655254526888
2022-06-15 10:55:26.896 I/System.out:    MVP_CLASS_ID=CLASS1
2022-06-15 10:55:26.896 I/System.out: }
2022-06-15 10:55:26.896 I/System.out: 1 {
2022-06-15 10:55:26.896 I/System.out:    MVP_BRCH_CODE_NAME=B1
2022-06-15 10:55:26.896 I/System.out:    MVP_ID=101
2022-06-15 10:55:26.896 I/System.out:    MVP_BRCH_ADDRESS=StreetX
2022-06-15 10:55:26.896 I/System.out:    AREA=Area1
2022-06-15 10:55:26.896 I/System.out:    AREA_CODE=A001
2022-06-15 10:55:26.896 I/System.out:    MVP_INDUSTRY_TYPE=I001
2022-06-15 10:55:26.896 I/System.out:    TOKEN=tkn002
2022-06-15 10:55:26.896 I/System.out:    SCHEDULED_DATE=1655254526889
2022-06-15 10:55:26.896 I/System.out:    MVP_CLASS_ID=CLASS1
2022-06-15 10:55:26.896 I/System.out: }
2022-06-15 10:55:26.897 I/System.out: <<<<<

Now considering the message Failed to read row 0, column -1 from a CursorWindow which has 1 rows, 9 columns

Then

  1. The Cursor is positioned at row 0 (not at row -1 which is before the first row)

  2. Of the 9 columns the specified column has not been found.

  3. From the dump of both cursors there are 9 columns.

  4. getColumnIndex has a bug in that it is case sensitive

  5. However, as the above works, this is not an issue with your code although I would strongly suggest changing your code to use cursor.getColumnIndex(/*"MVP_INDUSTRY_TYPE" <<<<< CHANGED*/ DataBaseHelper.MVP_INDUSTRY_TYPE) (obviously the comment could be omitted)

  6. As such the issue is either:-

    1. Elsewhere in your code, or
    2. That the columns name coded/used in the onCreate method have been changed BUT that they have not been applied.
      • The onCreate method runs once and only once when the database is created.
      • The onCreate method will never automatically run again unless the database is deleted.
      • Uninstalling the App will delete the database BUT will lose any existing data.
      • If you need to retain existing data, then you need to rebuild the table with the correct column name, noting that virtual tables has restrictions. You would probably need to utilise the onOpen method and within the method:-
        • create the new table BUT with a different name

        • populate the newly created table with the data from the orginal table

        • drop the original table

        • rename the newly created table with the original/required name

        • However, as onOpen runs whenever the database is opened you would want to limit this to only do the above when required (i.e. when there is a naming discrepancy). The following onOPen method could be the basis

:-

@Override
public void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    Log.d("ONOPEN","ON OPEN INVOKED");
    Cursor checkit = db.query(MVP_TBL,null,null,null,null,null,null,"1");
    boolean needToProceed = false;
    for (String s: new String[]{MVP_AREA,MVP_AREA_CODE,MVP_DATE,MVP_ID,MVP_BRCH_ADDRESS,MVP_BRCH_CODE_NAME,MVP_CLASS_ID,MVP_INDUSTRY_TYPE,token}) {
        boolean found = false;
        for (String cc: checkit.getColumnNames()) {
            if (cc.equals(s)) {
                Log.d("ONOPEN","Column " + cc + " matched " + s);
                found = true;
                break;
            }
        }
        if (!found) {
            Log.d("ONOPEN","!!!!COLUMN " + s + " NOT MATCHED.!!!!" );
            needToProceed = true;
            break;
        }
    }
    if (!needToProceed) return;
    Log.d("ONOPEN","PROCEEDING WITH RECREATION OF " + MVP_TBL +" TABLE.");
    String renamed = "ORIGINAL_" + MVP_TBL;
    db.execSQL("ALTER TABLE " + MVP_TBL + " RENAME TO " + renamed + ";");
    onCreate(db);
    db.execSQL("INSERT INTO " + renamed + " SELECT * FROM " + MVP_TBL);
    db.execSQL("DROP TABLE IF EXISTS " + MVP_TBL);
    db.execSQL("ALTER TABLE " + renamed + " RENAME TO " + MVP_TBL);
}
  • The Logging should be removed if distributing the App.
MikeT
  • 51,415
  • 16
  • 49
  • 68
  • Cursor cursor = mGroupsCursor; on what method should I put this one sir? – Ryan Baltazar Jun 15 '22 at 03:15
  • I followed everything, but I still get the same error. – Ryan Baltazar Jun 15 '22 at 03:47
  • @RyanBaltazar not sure what you mean by followed everything. But if you used the activity code above, then edit your question with the output sent to the log. The indication is that the MPV_INDUSTRY_TYPE column is probably not named that in the table. – MikeT Jun 15 '22 at 05:21
  • The problem seems on getSelectedParentMVP, I tried to create a another table for Industry which has 2 columns, the error changes from 9 columns to 2 columns: "Failed to read row 0, column -1 from a CursorWindow which has 2 rows, 2 columns." – Ryan Baltazar Jun 15 '22 at 06:33