получить данные из sqlite на основе фильтра времени - PullRequest
0 голосов
/ 03 апреля 2019

Я занимаюсь разработкой приложения, которое показывает список данных формы, и я добавляю кнопку фильтра в этот список, которая фильтрует данные на основе различных фильтров, таких как исходный отдел и даты (от даты1 до даты2). Мои фильтры отделов и источников работают нормально, но ничего не получаются, когда я выбираю даты.

Дата в sqlite хранится в целочисленном формате, и я пытаюсь сравнить обе даты из sqlite с датой, получаемой от пользователя. но это ничего не показывает.

DatabaseHelper класс

public class DbHelper extends SQLiteOpenHelper {

    public static final int DATABASE_VERSION = 13;
    public static final String DATABASE_NAME = "LoinReg.db";

    public DbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
       db.execSQL(SQL_CREATE_REG_ENTRIES);
       db.execSQL(SQL_CREATE_FORM_ENTRIES);
       db.execSQL(SQL_ADD_HISTORY);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        if(newVersion > oldVersion){
            db.execSQL(SQL_REG_DELETE_ENTRIES);
            db.execSQL(SQL_FORM_DELETE);
            db.execSQL(SQL_HISTORY_DELETE);
            onCreate(db);
         }
    }

    private static final String SQL_CREATE_FORM_ENTRIES =
            "CREATE TABLE IF NOT EXISTS " + FormEntry.COLUMN_TABLE_NAME +
                    " (" + FormEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                    + FormEntry.COLUMN_NAME_NAME + " TEXT,"
                    + FormEntry.COLUMN_NAME_EMAIL + " TEXT,"
                    + FormEntry.COLUMN_NAME_MOBILE + " TEXT,"
                    + FormEntry.COLUMN_NAME_ALTERNATE_NUMBER + " TEXT,"
                    + FormEntry.COLUMN_NAME_JEE + " TEXT,"
                    + COLUNM_NAME_JEERANK + " TEXT,"
                    + FormEntry.COLUMN_NAME_PERCENTAGE + " TEXT,"
                    + FormEntry.COLUMN_NAME_CITY + " TEXT,"
                    + FormEntry.COLUMN_NAME_DEPT + " TEXT,"
                    + FormEntry.COLUMN_NAME_SOURCE + " TEXT,"
                    + FormEntry.TIMESTAMP + " INTEGER )";
 public boolean insertForm(String name, String email, String phone, String alternate, String jee, String jeeRank, String percentage, String city, String dept, String source){
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(FormContract.FormEntry.COLUMN_NAME_NAME,name);
        values.put(FormContract.FormEntry.COLUMN_NAME_EMAIL,email);
        values.put(FormContract.FormEntry.COLUMN_NAME_MOBILE,phone);
        values.put(FormContract.FormEntry.COLUMN_NAME_ALTERNATE_NUMBER, alternate);
        values.put(FormContract.FormEntry.COLUMN_NAME_JEE,jee);
        values.put(FormContract.FormEntry.COLUNM_NAME_JEERANK,jeeRank);
        values.put(FormContract.FormEntry.COLUMN_NAME_PERCENTAGE,percentage);
        values.put(FormContract.FormEntry.COLUMN_NAME_CITY,city);
        values.put(FormContract.FormEntry.COLUMN_NAME_DEPT,dept);
        values.put(FormContract.FormEntry.COLUMN_NAME_SOURCE,source);
        values.put(FormEntry.TIMESTAMP,System.currentTimeMillis());

        long newRowId = db.insert(FormContract.FormEntry.COLUMN_TABLE_NAME,null,values);

        if(newRowId == -1){
            return false;
        }else{
            return true;
        }
}
}

MainActivity.java

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener, EnquiryAdapter.OnItemClickListener {

    DbHelper mDbHelper;
    public static final String FORM_ID = "form_id";
    public static final String SQL = "sql";
    public static final String DEPT = "dept";
    public static final String SOURCE = "source";
    public static final String STARTDATE = "start_date";
    public static final String ENDDATE = "end_date";
    private static String sql, department, source;
    long StartDate, EndDate;


    private RecyclerView mRecyclerView;
    private EnquiryAdapter mAdapter;
   private EditText mStartDate, mEndDate;
    private Spinner mDeptSpinner, mSourceSpinner;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        mDbHelper = new DbHelper(this);


        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               Intent intent = new Intent(MainActivity.this,FormActivity.class);
               startActivity(intent);
            }
        });

        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
        View headerView = navigationView.getHeaderView(0);

        Intent intent = getIntent();
        String email = intent.getStringExtra(LoginActivity.EXTRA_EMAIL);
        TextView mEmail = headerView.findViewById(R.id.email);
        mEmail.setText(email);

        //RecyclerView Setup
        mRecyclerView = findViewById(R.id.recyclerview);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mAdapter = new EnquiryAdapter(MainActivity.this,mDbHelper.getFormData());
        mRecyclerView.setAdapter(mAdapter);
        mAdapter.setOnItemClickListener(MainActivity.this);
   }
private void showFilterDialog(){

        LayoutInflater layoutInflater = LayoutInflater.from(MainActivity.this);
        View filterDialog = layoutInflater.inflate(R.layout.filters,null);

        /**
         * getting the reference to the @View
         * */
        mStartDate = filterDialog.findViewById(R.id.editText);
        mEndDate = filterDialog.findViewById(R.id.editText2);
        mDeptSpinner = filterDialog.findViewById(R.id.filter_dept);
        mSourceSpinner = filterDialog.findViewById(R.id.filter_source);

        AlertDialog.Builder alertBuilder = new AlertDialog.Builder(MainActivity.this);
        alertBuilder.setTitle("Filters");
        alertBuilder.setView(filterDialog);


        mStartDate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showDatePicker(v);
                hideKeyboard(v);

            }
        });

        mEndDate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showEndDatePicker(v);
                hideKeyboard(v);
            }
        });

        /**
         * Assigning the list of items to the @Spinner.
         * */
        ArrayAdapter<CharSequence> deptAdapter = ArrayAdapter.createFromResource(this,R.array.Department,android.R.layout.simple_spinner_dropdown_item);
        deptAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mDeptSpinner.setAdapter(deptAdapter);

        ArrayAdapter<CharSequence> sourceAdapter = ArrayAdapter.createFromResource(this,R.array.Source,android.R.layout.simple_spinner_dropdown_item);
        sourceAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mSourceSpinner.setAdapter(sourceAdapter);

        /**
         * @sql statement.
         * */
        sql = "Select * from " +FormEntry.COLUMN_TABLE_NAME+ " where ";


        alertBuilder.setPositiveButton("Apply", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

                Log.d("Date in milisec", String.valueOf(StartDate));
                Log.d("Date 2 in milisec", String.valueOf(EndDate));

                if(sd != null && ed != null){


                    sql = sql + FormEntry.TIMESTAMP+ " BETWEEN" + " ?" + " AND" + " ?";
                }else{
                    sql = "Select * from " +FormEntry.COLUMN_TABLE_NAME+ " where ";
                }

                department = mDeptSpinner.getSelectedItem().toString();
                source = mSourceSpinner.getSelectedItem().toString();

                if(mDeptSpinner.getSelectedItem() != null){
                    sql = sql + FormEntry.COLUMN_NAME_DEPT + " = ?";
                }

                if(mSourceSpinner.getSelectedItem() != null){
                    sql = sql + " OR "+ FormEntry.COLUMN_NAME_SOURCE + " = ?";
                }

                Intent intent = new Intent(MainActivity.this, FilterActivity.class);


               intent.putExtra(STARTDATE, StartDate);
               intent.putExtra(ENDDATE, EndDate);
                intent.putExtra(DEPT,department);
                intent.putExtra(SOURCE, source);
                intent.putExtra(SQL,sql);

                startActivity(intent);
            }
        })
        .setNegativeButton("Cancel",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                dialog.cancel();
                            }
                        });

        AlertDialog alertDialog = alertBuilder.create();
        alertDialog.show();
        Button pos = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
        pos.setTextColor(Color.BLUE);
        Button neg = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
        neg.setTextColor(Color.BLUE);
    }
    public void showDatePicker(View view) {
        DialogFragment newFragment = new DateFragment();
        newFragment.show(getSupportFragmentManager(),"datePicker");
    }
    public void showEndDatePicker(View v){
        DialogFragment dialogFragment = new EndDateFragment();
        dialogFragment.show(getSupportFragmentManager(),"End Date");
    }
    public void processDatePickerResult(int year,int month,int day){
        String month_string = Integer.toString(month +1);
        String day_string = Integer.toString(day);
        String year_string = Integer.toString(year);
        String dateMessage = (year_string + "-" + month_string +
                "-" + day_string);
        mStartDate.setText(dateMessage);
        StartDate = getTimeInMillis(day,month,year);

    }
    public void processEndDatePickerResult(int year, int month, int day){
        String month_string = Integer.toString(month + 1);
        String day_string  = Integer.toString(day);
        String year_String = Integer.toString(year);
        String dateMessage = (year_String + "-" + month_string +
                "-" + day_string);
        mEndDate.setText(dateMessage);
        EndDate = getTimeInMillis(day,month,year);
    }

    private void hideKeyboard(View view){
        InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);

    }

    public static long getTimeInMillis(int day, int month, int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month, day);
        return calendar.getTimeInMillis();
    }
}

FilterActivity.java

public class FilterActivity extends AppCompatActivity implements EnquiryAdapter.OnItemClickListener {
    private RecyclerView mRecyclerView;
    private EnquiryAdapter mAdapter;
    private DbHelper mDbHelper;
    public static final String FORM_ID = "form_id";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_filter);

        mRecyclerView = findViewById(R.id.filter_recyclerview);
        mDbHelper = new DbHelper(this);


        SQLiteDatabase db = mDbHelper.getReadableDatabase();

        Intent intent = getIntent();
        intent.getExtras();

        String sql = intent.getStringExtra(MainActivity.SQL);
       String dept = intent.getStringExtra(MainActivity.DEPT);
       String source = intent.getStringExtra(MainActivity.SOURCE);
      long startDate = intent.getIntExtra(MainActivity.STARTDATE,0);
      long endDate = intent.getIntExtra(MainActivity.ENDDATE,0);


        Cursor cursor = db.rawQuery(sql,new String[]{String.valueOf(startDate), String.valueOf(endDate), dept, source});

        mAdapter = new EnquiryAdapter(FilterActivity.this, cursor);

        //RecyclerView Setup
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        //mAdapter = new EnquiryAdapter(FilterActivity.this,mDbHelper.getFormData());
        mRecyclerView.setAdapter(mAdapter);
        mAdapter.setOnItemClickListener(FilterActivity.this);
    }
    @Override
    public void onItemClick(int position) {
        Intent intent = new Intent(this, DetailedActivity.class);
        int id = EnquiryAdapter.id;
        intent.putExtra(FORM_ID,id);
        startActivity(intent);
    }
}

1 Ответ

1 голос
/ 03 апреля 2019

Ваша проблема в том, что не было бы логического соединения предложения BETWEEN и других частей предложения WHERE в сгенерированном SQL.

То есть , если переменная sd и ed оба не равны NULL (в коде, при условии, что они не объявляются или не создаются) таким образом, чтобы SQL включал предложение BETWEEN, не было бы ни И, ни ИЛИ (я думаю, что первое будет необходимо). Таким образом, SQL, переданный через Intent Extra, будет выглядеть следующим образом: -

SELECT * FROM your_table WHERE your_timestamp_column BETWEEN ? AND ? your_dept_column = ? OR your_source_column = ?

Пока это должно быть (при условии И ): -

SELECT * FROM your_table WHERE your_timestamp_column BETWEEN ? AND ? 
    AND ( -- <<<<<<<<<<<< MISSING CONJUNCTION
        your_dept_column = ? OR your_source_column = ?
    )
  • где your_table, your_timestamp_column, your_dept_column и your_source_column являются идентификаторами, разрешенными из ваших переменных.

Возможно, ваш код может выглядеть следующим образом: -

            String time_filter_end_char = ""; //<<<<<<<<<< NO ) at end if no time_filter
            String sd = String.valueOf(StartDate); //<<<<<<<<<< ?????????
            String ed = String.valueOf(EndDate); //<<<<<<<<<< ??????????
            if(sd != null && ed != null && sd.length() >  0 && ed.length() > 0 ){
                time_filter_end_char = ")";
                sql = sql + FormEntry.TIMESTAMP+ " BETWEEN" + " ?" + " AND" + " ? AND("; //<<<<<<<<<< CONJUNCTION ADDED
            }
            //<<<<<<<<<< else construct/clause REMOVED as it does nothing
            department = mDeptSpinner.getSelectedItem().toString();
            source = mSourceSpinner.getSelectedItem().toString();

            if(mDeptSpinner.getSelectedItem() != null){
                sql = sql + FormEntry.COLUMN_NAME_DEPT + " = ?";
            }

            if(mSourceSpinner.getSelectedItem() != null){
                sql = sql + " OR "+ FormEntry.COLUMN_NAME_SOURCE + " = ?";
            }
            sql = sql + time_filter_end_char;

Однако, если вышеперечисленное будет проблемой, если dept или source оба будут нулевыми или пустыми.

Так что, возможно, более правильный код будет выглядеть примерно так: -

    String sd = String.valueOf(StartDate);
    String ed = String.valueOf(EndDate);
    String department = mDeptSpinner.getSelectedItem().toString();
    String source = mSourceSpinner.getSelectedItem().toString();
    String sql = "SELECT * FROM " + FormEntry.COLUMN_TABLE_NAME; //<<<<<<< no filtering
    String time_filter = "";
    String department_filter = "";
    String source_filter = "";
    if (sd != null && ed != null && sd.length() > 0 && ed.length() > 0) {
        time_filter = FormEntry.TIMESTAMP + " BETWEEN" + " ?" + " AND" + " ? ";
    }
    if (department != null && department.length() > 0) {
        department_filter = FormEntry.COLUMN_NAME_DEPT + " = ?";
    }
    if (source != null && source.length() > 0) {
        source_filter = FormEntry.COLUMN_NAME_SOURCE + " = ?";
    }
    String dept_source_conjunction = "";
    if (department_filter.length() > 0 && source_filter.length() > 0) {
        dept_source_conjunction = " OR ";
    }
    if (time_filter.length() > 0 || department_filter.length() > 0 || source_filter.length() > 0) {
        sql = sql + " WHERE ";
    }
    String end_dept_source_char = "";
    if (time_filter.length() > 0) {
        sql = sql + time_filter;
        if (department_filter.length() > 0 || source_filter.length() > 0) {
            sql = sql + " AND ";
            if (dept_source_conjunction.length() > 0) {
                sql = sql + "(";
                end_dept_source_char = ")";
            }
        }
    }
    sql = sql + department_filter + dept_source_conjunction + source_filter  + end_dept_source_char;

Тестирование: -

Для проверки кода использовалась следующая адаптация вышеперечисленного: -

private String testit(String StartDate, String EndDate, String mDS, String mSS) {
        //String sd = String.valueOf(StartDate);
        //String ed = String.valueOf(EndDate);
        String sd = StartDate; //<<<<<<<<<< FOR TESTING
        String ed = EndDate; //<<<<<<<<<< FOR TESTING
        //String department = mDeptSpinner.getSelectedItem().toString();
        //String source = mSourceSpinner.getSelectedItem().toString();
        String department = mDS; //<<<<<<<<<< FOR TESTING
        String source = mSS; //<<<<<<<<<< FOR TESTING
        String sql = "SELECT * FROM " + FormEntry.COLUMN_TABLE_NAME; //<<<<<<< no filtering
        String time_filter = "";
        String department_filter = "";
        String source_filter = "";
        if (sd != null && ed != null && sd.length() > 0 && ed.length() > 0) {
            time_filter = FormEntry.TIMESTAMP + " BETWEEN" + " ?" + " AND" + " ? ";
        }
        if (department != null && department.length() > 0) {
            department_filter = FormEntry.COLUMN_NAME_DEPT + " = ?";
        }
        if (source != null && source.length() > 0) {
            source_filter = FormEntry.COLUMN_NAME_SOURCE + " = ?";
        }
        String dept_source_conjunction = "";
        if (department_filter.length() > 0 && source_filter.length() > 0) {
            dept_source_conjunction = " OR ";
        }
        if (time_filter.length() > 0 || department_filter.length() > 0 || source_filter.length() > 0) {
            sql = sql + " WHERE ";
        }
        String end_dept_source_char = "";
        if (time_filter.length() > 0) {
            sql = sql + time_filter;
            if (department_filter.length() > 0 || source_filter.length() > 0) {
                sql = sql + " AND ";
                if (dept_source_conjunction.length() > 0) {
                    sql = sql + "(";
                    end_dept_source_char = ")";
                }
            }
        }
        sql = sql + department_filter + dept_source_conjunction + source_filter  + end_dept_source_char;
        return sql;
    }

Тогда использовалось следующее: -

    Log.d("TEST2", testit(null,null,null,null)); //<<<<<<<<<< no filter
    Log.d("TEST1",testit("1111111111","2222222222",null,null)); // time filter only
    Log.d("TEST3", testit("1111111111","2222222222","d1","s1")); // full filter
    Log.d("TEST4",testit("1111111111","2222222222",null,"s1")); // time and source
    Log.d("TEST5",testit("1111111111","2222222222","d1","")); // time and dept

Результат: -

D/TEST2: SELECT * FROM your_table_name
D/TEST1: SELECT * FROM your_table_name WHERE your_timestamp_column BETWEEN ? AND ? 
D/TEST3: SELECT * FROM your_table_name WHERE your_timestamp_column BETWEEN ? AND ?  AND (your_department_column = ? OR your_source_column = ?)
D/TEST4: SELECT * FROM your_table_name WHERE your_timestamp_column BETWEEN ? AND ?  AND your_source_column = ?
D/TEST5: SELECT * FROM your_table_name WHERE your_timestamp_column BETWEEN ? AND ?  AND your_department_column = ?
...