Edit: Added resolution following the original question. The problem turned out to be related to aggregate functions in temporary tables rather than parameter markers with inner joins. A more detailed explanation is in the resolution.
This question is not a duplicate. The problem is unrelated to the presence of an IN clause, which I have illustrated by eliminating the IN clause from the queries to illustrate that the defective behavior remains independent of the IN clause.
There appears to be some confusion about where exactly the problem is in my question below. The problem is not in the IN clause. The problem is that the parameter specified with pheno_temp1.pheno_count=? is not being replaced.
To address this misreading of the question, I rewrote the two rawQuery calls to illustrate that the behavior is in the parameter replacement for the inner join. There is no IN clause in the following calls, and they exhibit exactly the same behavior as specified in the original two calls (which I have retained for reference).
// More restrictive example. This call gives the correct result;
// note there are NO parameter markers.
cursor = _mendelDatabase.rawQuery("SELECT organism.org_id FROM organism INNER JOIN pheno_temp1 ON organism.org_id=pheno_temp1.org_id WHERE pheno_temp1.pheno_count=1",null);
// This call returns NO results. pheno_count=1 has been replaced with
// pheno_count=?
cursor = _mendelDatabase.rawQuery("SELECT organism.org_id FROM organism INNER JOIN pheno_temp1 ON organism.org_id=pheno_temp1.org_id WHERE pheno_temp1.pheno_count=?",new String[]{"1"});
// This query still gives the correct result; It includes a parameter
// marker for a column from the organism table.
cursor = _mendelDatabase.rawQuery("SELECT organism.org_id FROM organism INNER JOIN pheno_temp1 ON organism.org_id=pheno_temp1.org_id WHERE pheno_temp1.pheno_count=1 AND organism.bbch_stage=?",new String[]{"9"});
// This query still returns no rows. It includes 2 parameter markers;
// one for a column from organism (see above call which worked) and one
// for pheno_count from the inner table.
cursor = _mendelDatabase.rawQuery("SELECT organism.org_id FROM organism INNER JOIN pheno_temp1 ON organism.org_id=pheno_temp1.org_id WHERE pheno_temp1.pheno_count=? AND organism.bbch_stage=?",new String[]{"1","9"});
I am observing behavior when executing rawQuery that suggests it is bugged when using selectionArgs to pass values for a where clause on a table that is specified in an inner join.
I have the following tables in a SQLite database:
table organism
org_id bbch_stage org_name (other data)
-----------------------------------------------------------------------
0 9 homozygous dominant starter plant (miscellaneous)
1 9 homozygous recessive starter plant (miscellaneous)
table pheno_temp1
org_id pheno_count
--------------------
0 1
The following calls return different result sets:
// This call returns the correct result set
cursor = _mendelDatabase.rawQuery("SELECT organism.org_id FROM organism INNER JOIN pheno_temp1 ON organism.org_id=pheno_temp1.org_id WHERE pheno_temp1.pheno_count=1 AND organism.bbch_stage IN (?)",new String[]{"9"});
// This call returns no rows
cursor = _mendelDatabase.rawQuery("SELECT organism.org_id FROM organism INNER JOIN pheno_temp1 ON organism.org_id=pheno_temp1.org_id WHERE pheno_temp1.pheno_count=? AND organism.bbch_stage IN (?)",new String[]{"1","9"});
This appears to be aberrant behavior to me. However, before I try to file a bug report I'd like to know if there is some subtle behavior of rawQuery with inner joins and selectionArgs that is not apparent in the documentation.
I am observing this behavior on an HTC One running Android 4.1.1. Development environment is Android Studio 2.1.1. Compile SDK 23, build tools 23.0.3, min SDK 14, target SDK 23. Java 1.8.0_91.
Background:
The queries above are the simplest queries illustrating the problem that might occur in the app. Real queries might arbitrarily include organism restrictions on maternal and paternal lineage, organism "birth" date (before, after, on, or between two dates), or multiple bbch stages; specification of multiple phenotypes, or specification of multiple alleles from a genetic table (omitted in the example above). The arbitrary nature of the restrictions make a view unsuitable. Instead I build work tables for the phenotype and allele restrictions (if needed), and then use them in an inner join to restrict the rows selected from the organism table (again, if needed).
The restrictions on the phenotypes and alleles are set by building temporary tables which are then joined to the organism table. If the user has set restrictions on phenotype, the pheno_temp1
table will specify (in pheno_count
) how many of those restrictions were met for each organism. So if the user set three phenotype restrictions, only entries in pheno_temp1
with pheno_count=3
will satisfy the user's criteria. In the inner join, the where clause on pheno_count
must accommodate a varying value. A similar (but significantly more complex) mechanism is used for restricting results by alleles.
There are ways for me to code around the rawQuery behavior without concatenating the count value into the where clause (that involve more steps with the temp tables), so I am not looking for a solution to that problem. What I am looking for is confirmation the behavior is bugged before I open a bug report.
Discussions for more general "How do I do an inner join" questions on elsewhere on this site suggest that the second query (the one that returns no rows) should work, but all the answers I have seen say something like "This is an example ...," not "This is code I tested and know for certain works." (... except for maybe this question SQLite rawquery selectionArgs not working).