in aws-datastore/src/main/java/com/amplifyframework/datastore/storage/sqlite/SQLiteCommandFactory.java [135:265]
public SqlCommand queryFor(@NonNull ModelSchema modelSchema,
@NonNull QueryOptions options) throws DataStoreException {
final SQLiteTable table = SQLiteTable.fromSchema(modelSchema);
final String tableName = table.getName();
StringBuilder rawQuery = new StringBuilder();
StringBuilder selectColumns = new StringBuilder();
StringBuilder joinStatement = new StringBuilder();
final List<Object> bindings = new ArrayList<>();
// Track the list of columns to return, along with the alias for the corresponding table
Map<String, List<SQLiteColumn>> columns = new HashMap<>();
columns.put(table.getName(), table.getSortedColumns());
Map<String, Integer> tableCount = new HashMap<>();
tableCount.put(tableName, 1);
// Joins the foreign keys
recursivelyBuildJoins(table, columns, joinStatement, tableCount, tableName);
// Convert columns to comma-separated column names
boolean firstTable = true;
for (String tableAlias : columns.keySet()) {
if (!firstTable) {
selectColumns.append(",").append(SqlKeyword.DELIMITER);
} else {
firstTable = false;
}
Iterator<SQLiteColumn> columnsIterator = Objects.requireNonNull(columns.get(tableAlias)).iterator();
while (columnsIterator.hasNext()) {
final SQLiteColumn column = columnsIterator.next();
String columnName = column.getQuotedColumnName().replace(column.getTableName(), tableAlias);
selectColumns.append(columnName);
// Alias columns with a unique alias to avoid duplicate column names or alias names
String columnAlias = column.getAliasedName()
+ tableAlias.substring(column.getTableName().length());
selectColumns.append(SqlKeyword.DELIMITER)
.append(SqlKeyword.AS)
.append(SqlKeyword.DELIMITER)
.append(Wrap.inBackticks(columnAlias));
if (columnsIterator.hasNext()) {
selectColumns.append(",").append(SqlKeyword.DELIMITER);
}
}
}
// Start SELECT statement.
// SELECT columns FROM tableName
rawQuery.append(SqlKeyword.SELECT)
.append(SqlKeyword.DELIMITER)
.append(selectColumns.toString())
.append(SqlKeyword.DELIMITER)
.append(SqlKeyword.FROM)
.append(SqlKeyword.DELIMITER)
.append(Wrap.inBackticks(tableName));
// Append join statements.
// INNER JOIN tableOne ON tableName.id=tableOne.foreignKey
// LEFT JOIN tableTwo ON tableName.id=tableTwo.foreignKey
if (!joinStatement.toString().isEmpty()) {
rawQuery.append(SqlKeyword.DELIMITER)
.append(joinStatement.toString());
}
// Append predicates.
// WHERE condition
final QueryPredicate predicate = options.getQueryPredicate();
if (!QueryPredicates.all().equals(predicate)) {
final SQLPredicate sqlPredicate = new SQLPredicate(predicate);
bindings.addAll(sqlPredicate.getBindings());
String sqlPredicateString = sqlPredicate.toString();
if (predicate instanceof QueryPredicateOperation) {
QueryPredicateOperation<?> predicateOperation = (QueryPredicateOperation<?>) predicate;
String predicateOperationField = predicateOperation.field();
if (predicateOperationField.equals(PrimaryKey.fieldName()) && predicateOperation.modelName() == null
&& predicateOperation.operator().type() == QueryOperator.Type.EQUAL) {
// The WHERE condition is Where.id("some-ID") but no model name is given.
sqlPredicateString = sqlPredicateString.replace(predicateOperationField,
tableName + "." + predicateOperationField);
}
}
rawQuery.append(SqlKeyword.DELIMITER)
.append(SqlKeyword.WHERE)
.append(SqlKeyword.DELIMITER)
.append(sqlPredicateString);
}
// Append order by
final List<QuerySortBy> sortByList = options.getSortBy();
if (sortByList != null) {
rawQuery.append(SqlKeyword.DELIMITER)
.append(SqlKeyword.ORDER_BY)
.append(SqlKeyword.DELIMITER);
Iterator<QuerySortBy> sortByIterator = sortByList.iterator();
while (sortByIterator.hasNext()) {
final QuerySortBy sortBy = sortByIterator.next();
String modelName = Wrap.inBackticks(sortBy.getModelName());
String fieldName = Wrap.inBackticks(sortBy.getField());
if (modelName == null) {
modelName = Wrap.inBackticks(tableName);
}
final String columnName = modelName + "." + fieldName;
rawQuery.append(columnName)
.append(SqlKeyword.DELIMITER)
.append(SqlKeyword.fromQuerySortOrder(sortBy.getSortOrder()));
if (sortByIterator.hasNext()) {
rawQuery.append(",")
.append(SqlKeyword.DELIMITER);
}
}
}
// Append pagination after order by
final QueryPaginationInput paginationInput = options.getPaginationInput();
if (paginationInput != null) {
rawQuery.append(SqlKeyword.DELIMITER)
.append(SqlKeyword.LIMIT)
.append(SqlKeyword.DELIMITER)
.append("?")
.append(SqlKeyword.DELIMITER)
.append(SqlKeyword.OFFSET)
.append(SqlKeyword.DELIMITER)
.append("?");
bindings.add(paginationInput.getLimit());
bindings.add(paginationInput.getPage() * paginationInput.getLimit());
}
rawQuery.append(";");
final String queryString = rawQuery.toString();
return new SqlCommand(table.getName(), queryString, bindings);
}