Android Inner join query error - android-sqlite

I am creating notepad and now I am facing issue when I am trying to implement join with dynamically passing id into it and also using Order by. it is giving SQLiteexception near "=".
I don't know what is the reason I am writing this query:
String selectQuery = "SELECT " + KEY_TASKNOTE + " FROM " + TABLE_TODOTASK
+ " INNER JOIN" + TABLE_TODOTASK_DETAILS + "ON " + KEY_TASKID + "=" + KEY_TASK_DETAILS_TASKID + " WHERE "
+ KEY_TASK_TASKLISTID + "=" + tasklist_Id + " ORDER BY " + KEY_TASK_DETAILS_DUEDATE;
CONSTANTS:
// TASK table name
private static final String TABLE_TODOTASK = "todotask";
// TASKLIST Table Columns names
private static final String KEY_TASKID = "Id";
private static final String KEY_TASKNOTE = "tasknote";
private static final String KEY_TASKDUEDATE = "duedate";
private static final String KEY_TASKCOMPLETED = "taskcompleted";
private static final String KEY_TASK_TASKLISTID = "TaskList_id";
// TASKDETAILS table name
private static final String TABLE_TODOTASK_DETAILS = "todotaskdetails";
// TASKDETAILS Table Columns names
private static final String KEY_TASK_DETAILS_ID = "ID";
private static final String KEY_TASK_DETAILS_TASKID = "Task_id";
private static final String KEY_TASK_DETAILS_DUEDATE = "taskduedate";
private static final String KEY_TASK_DETAILS_EVENT = "taskevent";
private static final String KEY_TASKDETAILS_REMINDER = "taskreminder";
private static final String KEY_TASKDETAILS_REPEAT = "taskrepeat";
private static final String KEY_TASKDETAILS_PRIORITY = "taskpriority";
Please help, thanks

For inner join, you need to use tablename1.fieldName = tablename2.fieldName, but you used only field name = field name. Add the table prefixes like this:
String selectQuery = "SELECT " + KEY_TASKNOTE + " FROM " + TABLE_TODOTASK
+ " INNER JOIN " + TABLE_TODOTASK_DETAILS + " ON " + TABLE_TODOTASK+"."+KEY_TASKID + "=" + TABLE_TODOTASK_DETAILS +"."+KEY_TASK_DETAILS_TASKID + " WHERE "
+ KEY_TASK_TASKLISTID + "=" + tasklist_Id + " ORDER BY " + KEY_TASK_DETAILS_DUEDATE;
Simple example of inner join
SELECT column_name(s)
FROM table_name1
INNER JOIN table_name2
ON table_name1.column_name=table_name2.column_name

Related

android display arraylist items in dialog

I am having an arraylist fetching name and status of a person. Arraylist is storing the status and name. Its displaying one name at a time. How can I be able to display multiple names at once in alert dialog?
private ArrayList getunfiledRogspDoctorList() {
SqlDataStore sd = new SqlDataStore(this);
sd.open();
String gspQuery = " SELECT * FROM "+ TABLE_DOCTOR + " WHERE " + Queryclass.DOCTOR_ROGSP_STATUS + " == " + 0 + " AND " + Queryclass.DOCTOR_DATE_ID + " = '" + selectionID + "'";
Cursor gspCu = sd.getData(gspQuery);
if(gspCu.moveToFirst()){
do {
rogspname = gspCu.getString(gspCu.getColumnIndex(Queryclass.DOCTOR_CONTACTNAME));
unfiledrogspDoctorList.add(gspCu.getString(gspCu.getColumnIndex(Queryclass.DOCTOR_ROGSP_STATUS)) + rogspname);
}while (gspCu.moveToNext());
}
gspCu.close();
sd.close();
System.out.println("unfiledrogspDoctorList "+unfiledrogspDoctorList);
return unfiledrogspDoctorList;
}
From the code, you are having an ArrayList of your target display String in unfiledrogspDoctorList:
// Suggest to also define the type of your returning ArrayList
private ArrayList<String> getunfiledRogspDoctorList() {
// Define a local ArrayList
ArrayList<String> unfiledrogspDoctorList = new ArrayList<>();
SqlDataStore sd = new SqlDataStore(this);
sd.open();
String gspQuery = " SELECT * FROM "+ TABLE_DOCTOR + " WHERE " + Queryclass.DOCTOR_ROGSP_STATUS + " == " + 0 + " AND " + Queryclass.DOCTOR_DATE_ID + " = '" + selectionID + "'";
Cursor gspCu = sd.getData(gspQuery);
if(gspCu.moveToFirst()){
do {
rogspname = gspCu.getString(gspCu.getColumnIndex(Queryclass.DOCTOR_CONTACTNAME));
unfiledrogspDoctorList.add(gspCu.getString(gspCu.getColumnIndex(Queryclass.DOCTOR_ROGSP_STATUS)) + rogspname);
}while (gspCu.moveToNext());
}
gspCu.close();
sd.close();
System.out.println("unfiledrogspDoctorList "+unfiledrogspDoctorList);
return unfiledrogspDoctorList;
}
You can consider to convert your ArrayList of String into just a String.
private String concat(ArrayList<String> unfiledrogspDoctorList) {
StringBuilder sb = new StringBuilder();
for (String item : unfiledrogspDoctorList) {
sb.append(item);
sb.append(","); // Or change into other separate you would like to display
}
sb.setLength(Math.max(0, sb.length() - 1)); // Remove the appending character
return sb.toString();
}
Then you can make use of an AlertDialog to display that concatenated String.
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder
.setMessage(concat(getunfiledRogspDoctorList()))
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Do anything upon pressing OK button
}
);
AlertDialog alert = builder.create();
alert.show();
You could use :-
SELECT group_concat(name) FROM ....
or to place each on a line you could change the default comma separator to a line feed using
SELECT group_concat(name,'\n') FROM ....
.... representing the rest of the SQL in the question
See https://www.sqlite.org/lang_aggfunc.html#group_concat
note that the GROUP as no GROUP BY clause is provided is a single group (and therefore output row) made up of ALL extracted rows.

Exception: (Index -1 requested, with a size of 2) while retrieving data from a Cursor

Hey I have a problem with accessing the data from a Cursor in Android Studio.
I have two tables in the database events and messages. So each event in the events table may have multiple messages in the messages table. The event and its messages share a common event_id.
I am using LoaderCallbacks to get a Cursor from a ContentProvider. In the ContentProvider query method, I am using a rawQuery to INNER JOIN these two tables.
In this example I query for an event which shares its event_id with two messages from the message table. In the ContentProvider the rawQuery() method with the INNER JOIN was performed.
At this state I can see in the Debugger that the variable mCount from the Cursor is -1. I am not sure what this means but anyways, back in the onLoadFinish() method the Cursor now contains a variable mCursor and this variable again contains a variable mCount which is 2. Which makes sense, since the query should return a Cursor with two rows and since there are two messages. But now I try to get a String with the getString() method and the CursorIndexOutOfBoundsException: Index -1 requested, with a size of 2 is thrown.
I realy don't understand what this means. And I don't find any hint in die Cursor docs, what it means when mCount is -1.
Furthermore in the onLoadFinished method the variable mEditTable is null. And in other queries where I don't join anything it always contains a table.
I am quite sure that the issue somwhere lays with the INNER JOIN, since everything works fine if I use just a query method inside the ContentProvider.query method. But I don't know what I should do differently. I hope you might help me with this. I am aware that, if there is no message related to an event, this query will return an empty cursor with mCount = 0 and then again an exception will be thrown. But this is not the case in this example.
EventProvider class:
public class EventProvider extends ContentProvider {
private static final String LOG_TAG = EventProvider.class.getSimpleName();
private static final int EVENTS = 100;
private static final int EVENT_ID = 101;
private static final int EVENT_MESSAGE_ID = 102;
private static UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private EventDbHelper mEventDbHelper;
static {
sUriMatcher.addURI(EventContract.CONTENT_AUTHORITY, EventContract.PATH_EVENTS, EVENTS);
sUriMatcher.addURI(EventContract.CONTENT_AUTHORITY, EventContract.PATH_EVENTS + "/#", EVENT_ID);
sUriMatcher.addURI(EventContract.CONTENT_AUTHORITY, EventContract.PATH_EVENT_AND_ITS_MESSAGES + "/#", EVENT_MESSAGE_ID);
}
#Override
public boolean onCreate() {
mEventDbHelper = new EventDbHelper(getContext());
return true;
}
#Nullable
#Override
public Cursor query(#NonNull Uri uri, #Nullable String[] projection, #Nullable String selection, #Nullable String[] selectionArgs, #Nullable String sortOrder) {
SQLiteDatabase database = mEventDbHelper.getReadableDatabase();
Cursor retCursor;
final int match = sUriMatcher.match(uri);
switch (match) {
case EVENTS:
retCursor = database.query(EventEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
break;
case EVENT_ID:
selection = EventEntry.COLUMN_EVENT_ID + "=?";
selectionArgs = new String[] {String.valueOf(ContentUris.parseId(uri))};
retCursor = database.query(EventEntry.TABLE_NAME, projection,selection, selectionArgs, null, null, sortOrder);
break;
case EVENT_MESSAGE_ID:
selection = MessageEntry.TABLE_NAME + "." + MessageEntry.COLUMN_EVENT_ID + "=?";
selectionArgs = new String[] {String.valueOf(ContentUris.parseId(uri))};
StringBuilder sqlQuery = new StringBuilder();
sqlQuery.append("SELECT ");
if(projection != null && projection.length > 0) {
for(String s: projection) {
sqlQuery.append(s).append(", ");
}
}
sqlQuery.replace(sqlQuery.length()-2, sqlQuery.length(), " FROM ").append(MessageEntry.TABLE_NAME);
sqlQuery.append(" INNER JOIN ").append(EventEntry.TABLE_NAME).append(" ON ");
sqlQuery.append(EventEntry.TABLE_NAME).append(".").append(EventEntry.COLUMN_EVENT_ID).append("=");
sqlQuery.append(MessageEntry.TABLE_NAME).append(".").append(MessageEntry.COLUMN_EVENT_ID);
sqlQuery.append(" WHERE ").append(selection).append(" ORDER BY ").append(sortOrder).append(";");
Log.v(LOG_TAG, "SQL command for: " + uri.toString());
Log.v(LOG_TAG, sqlQuery.toString());
retCursor = database.rawQuery(sqlQuery.toString(), selectionArgs);
break;
default:
throw new IllegalArgumentException("Cannot query unknown URI: " + uri);
}
retCursor.setNotificationUri(getContext().getContentResolver(), uri);
return retCursor;
}
EventActivity:
#NonNull
#Override
public Loader<Cursor> onCreateLoader(int id, #Nullable Bundle args) {
String[] projection = {
MessageEntry.TABLE_NAME + "." + MessageEntry.COLUMN_EVENT_ID,
MessageEntry.TABLE_NAME + "." + MessageEntry.COLUMN_SENDER,
MessageEntry.TABLE_NAME + "." + MessageEntry.COLUMN_DATE,
MessageEntry.TABLE_NAME + "." + MessageEntry.COLUMN_MESSAGE,
EventEntry.TABLE_NAME + "." + EventEntry._ID,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_NAME,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_DATE,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_DATE_ADDENDUM,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_CONTACT,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_STATUS,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_PICTURE_NAME,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_DESCRIPTION,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_STREET,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_HOUSE_NUMBER,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_POST_CODE,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_CITY,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_EMAIL,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_LOCATION,
EventEntry.TABLE_NAME + "." + EventEntry.COLUMN_SIGNED_UP
};
String sortOrder = MessageEntry.COLUMN_DATE + " DESC";
return new CursorLoader(this, mCurrentEventUri, projection, null, null, sortOrder);
}
#Override
public void onLoadFinished(#NonNull Loader<Cursor> loader, Cursor cursor) {
int indexName = cursor.getColumnIndex(EventEntry.COLUMN_NAME);
int indexImage = cursor.getColumnIndex(EventEntry.COLUMN_PICTURE_NAME);
String imageName = cursor.getString(indexImage); //Here the Exception is thrown
mEventName.setText(cursor.getString(indexName));
mEventAdapter.swapCursor(cursor);
}
If you need something else, I will upload it.
Thanks.
CursorIndexOutOfBoundsException: Index -1 requested, with a size of 2
-1 with Cursors will generally be 1 of 2 issues :-
that the column name passed to getColumnIndex is not a name of a column in the output.
that the Cursor is at the beginning that is at the position that is "before the first row", as is the case when a Cursor is returned.
I suspect that your issue is due to 2 as I believe the message indicates the row of the column.
2 can happen if a move???? (e.g. moveToFirst, moveToNext) method was not actioned (I cannot see any such move in your code) or that the result was not checked (the move methods return true or false to indicate whether or not the move request could be satisfied).
see (probably moveToFirst)
https://developer.android.com/reference/android/database/Cursor#move(int)
https://developer.android.com/reference/android/database/Cursor#moveToFirst()
https://developer.android.com/reference/android/database/Cursor#moveToLast()
https://developer.android.com/reference/android/database/Cursor#moveToNext()
https://developer.android.com/reference/android/database/Cursor#moveToPosition(int)
https://developer.android.com/reference/android/database/Cursor#moveToPrevious()
The fix would be to move the Cursor to a row, checking if the move was actually successful and to then extract the data.
e.g.
String imageName = "No Image"
if (cursor.moveToFirst() && indexImage > -1) {
imageName = cursor.getString(indexImage); //Here the Exception is thrown
}
The above, && indexImage > -1, would also weed out the situation where the column name does not exist in the Cursor.

apache beam: accessing metrics during pipeline processing

Using the WordCount.java example to test metrics. The PrintMetricsFn function (see below) prints the metrics correctly once the pipeline is finished, but fails when called while the pipeline is processing. DirectRunner and FlinkRunner both throw exceptions (null input), while SparkRunner prints only the header line (similar to "* Metric Values *").
private static void PrintMetricsFn(final MetricsFilter inputFilter) {
final MetricResults metrics = result.metrics();
final MetricQueryResults returns = metrics.queryMetrics(inputFilter);
final Iterable<MetricResult<Long>> counters = returns.getCounters();
System.out.println("*** Metric Values ***");
for(final MetricResult<Long> s: counters){
System.out.println(s.getName().getNamespace() + ":" +
s.getName().getName() + ":" + s.getStep() + ": count=" +
s.getAttempted()) ;
}
final Iterable<MetricResult<DistributionResult>> dist = returns.getDistributions();
for (final MetricResult<DistributionResult> d: dist) {
System.out.println(d.getName().getNamespace() + ":" +
d.getName().getName() + ":" + d.getStep() + ": sum=" +
d.getAttempted().getSum() + ", count=" +
d.getAttempted().getCount() + ", min=" +
d.getAttempted().getMin() + ", max=" +
d.getAttempted().getMax() + ", mean=" +
d.getAttempted().getMean());
}
final Iterable<MetricResult<GaugeResult>> gauge = returns.getGauges();
for (final MetricResult<GaugeResult> g: gauge) {
System.out.println(g.getName().getNamespace() + ":" +
g.getName().getName() + ":" + g.getStep() + ": gauge=" +
g.getAttempted().getValue());
}
return;
}
Here are the declarations for the external variables:
private static PipelineResult result;
private static MetricQueryResults returns;
private static MetricsFilter mFilter;
And here's where the mFilter and result variables are set:
mFilter = MetricsFilter.builder()
.addNameFilter(MetricNameFilter.named("ExtractWordsFn", "emptyLines"))
.addNameFilter(MetricNameFilter.named("ExtractWordsFn", "lineLenDistro"))
.addNameFilter(MetricNameFilter.named("ExtractWordsFn", "maxLineLen"))
.build();
result = p.run();
Finally, here's the function that calls PrintMetricsFN without success:
#ProcessElement
public void processElement(#Element final String element, final OutputReceiver<String> receiver) {
lineLen = element.length();
lineLenDist.update(lineLen);
if (element.trim().isEmpty()) {
emptyLines.inc();
}
if (lineLen > localMax) {
localMax = lineLen;
maxLineLen.set(localMax);
}
if((lineCnt++ % 10) == 0) {
PrintMetricsFn(mFilter);
}
// Split the line into words.
final String[] words = element.split(ExampleUtils.TOKENIZER_PATTERN, -1);
// Output each word encountered into the output PCollection.
for (final String word : words) {
if (!word.isEmpty()) {
receiver.output(word);
}
}
}
And for completeness, here's the error I get from DirectRunner:
Caused by: java.lang.NullPointerException
at org.apache.beam.examples.WordCount.PrintMetricsFn(WordCount.java:158)
at org.apache.beam.examples.WordCount.access$1(WordCount.java:157)
at org.apache.beam.examples.WordCount$ExtractWordsFn.processElement(WordCount.java:132)

Inheritance doesn't work in Query

I'm new to Spring and i have an issue with the following query:
String rejected_offer_query = "SELECT b.job_instance_id, b.start_time, count (*) " +
"FROM SygaOfferRejected s , BatchJobExecution b, BatchJobInstance bi "+
"where s.heure_debut = b.start_time " +
"and s.heure_fin = b.end_time " +
"and b.job_execution_id = bi.job_instance_id " +
"and bi.job_name = :batchName "+
"and b.status = :batchStatus " +
"group by b.job_instance_id";
It doesn't return data, but it should return one row as a result: (Test made directly with MySql).
I think it's an inheritance problem because when i try to execute the same query with a super class it works :
SELECT b.job_instance_id, b.start_time, count (*) " +
"FROM SygaOffer s , BatchJobExecution b, BatchJobInstance bi "+
"where s.heure_debut = b.start_time " +
"and s.heure_fin = b.end_time " +
"and b.job_execution_id = bi.job_instance_id " +
"and bi.job_name = :batchName "+
"and b.status = :batchStatus " +
"group by b.job_instance_id"
The SygaOfferRejected class extends the SygaOffer, here's the source code;
#Entity
#Inheritance
#Table(name = "bob_syga_off")
public class SygaOffer {
#Id
private long id_offre;
private String acteur;
private String heure_debut;
private String heure_fin;
private String reference_offre;
private int retry;
}
------------------------------------------
#Entity
#Table(name ="bob_syga_offr_rejected")
public class SygaOfferRejected extends SygaOffer{
}
The inheritance strategy is the issue i should specify the TABLE_PER_CLASS type in the parent class :
#Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
Hope that helps ;)

Android SQLite cannot bind argument

I'm trying to do a simple query of my database, where a unique Identification number is stored for a PendingIntent. To allow me to cancel a notification set by AlarmManager if needed.
The insertion of a value works fine, but I am unable to overcome the error:
java.lang.IllegalArgumentException: Cannot bind argument at index 1 because the index is out of range. The statement has 0 parameters.
Database structure:
public class DBAdapter {
private static final String TAG = "DBAdapter";
public static final String KEY_ROWID = "_id";
public static final String TASK = "task";
public static final String NOTIFICATION = "notification";
public static final int COL_ROWID = 0;
public static final int COL_TASK = 1;
public static final int COL_NOTIFICATION = 2;
public static final String[] ALL_KEYS = new String[] {KEY_ROWID, TASK, NOTIFICATION};
// DB info: it's name, and the table.
public static final String DATABASE_NAME = "TaskDB";
public static final String DATABASE_TABLE = "CurrentTasks";
public static final int DATABASE_VERSION = 3;
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key, "
+ TASK + " text not null, "
+ NOTIFICATION + " integer"
+ ");";
Now I have created a method to extract the notification ID from the database as needed, using the following code:
public int getNotifID(long notifID){
String[] x = {ALL_KEYS[2]};
String[]args = new String[]{NOTIFICATION};
String where = NOTIFICATION + "=" + notifID;
int y = 0;
//String select = "SELECT "+NOTIFICATION+" FROM "+DATABASE_TABLE+" WHERE "+notifID+"="+NOTIFICATION;
//Cursor c = db.rawQuery(select,new String[]{});
Cursor c = db.query(true,DATABASE_TABLE,x,Long.toString(notifID),args,null,null,null,null,null);
if (c!= null && c.moveToFirst()){
y = c.getInt(COL_NOTIFICATION);
}
return y;
}
As you can see I have attempted to do this both with a rawQuery and a regular query, but with no success.
Rewrite your raw query to:
String select = "SELECT "+NOTIFICATION+" FROM "+DATABASE_TABLE+" WHERE "+NOTIFICATION+"=?";
Cursor c = db.rawQuery(select,new String[]{""+notifId});
if(c!=null && c.getCount()>0) {
c.moveToFirst();
}
c.close();