use of com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable in project amplify-android by aws-amplify.
the class SQLiteCommandFactory method createIndexesFor.
@NonNull
@Override
public Set<SqlCommand> createIndexesFor(@NonNull ModelSchema modelSchema) {
final SQLiteTable table = SQLiteTable.fromSchema(modelSchema);
Set<SqlCommand> indexCommands = new HashSet<>();
for (ModelIndex modelIndex : modelSchema.getIndexes().values()) {
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("CREATE INDEX IF NOT EXISTS").append(SqlKeyword.DELIMITER).append(Wrap.inBackticks(modelIndex.getIndexName())).append(SqlKeyword.DELIMITER).append(SqlKeyword.ON).append(SqlKeyword.DELIMITER).append(Wrap.inBackticks(table.getName())).append(SqlKeyword.DELIMITER);
stringBuilder.append("(");
Iterator<String> iterator = modelIndex.getIndexFieldNames().iterator();
while (iterator.hasNext()) {
final String indexColumnName = iterator.next();
stringBuilder.append(Wrap.inBackticks(indexColumnName));
if (iterator.hasNext()) {
stringBuilder.append(",").append(SqlKeyword.DELIMITER);
}
}
stringBuilder.append(");");
indexCommands.add(new SqlCommand(table.getName(), stringBuilder.toString()));
}
return Immutable.of(indexCommands);
}
use of com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable in project amplify-android by aws-amplify.
the class SQLiteCommandFactory method insertFor.
@NonNull
@Override
public <T extends Model> SqlCommand insertFor(@NonNull ModelSchema modelSchema, @NonNull T item) throws DataStoreException {
final SQLiteTable table = SQLiteTable.fromSchema(modelSchema);
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("INSERT INTO").append(SqlKeyword.DELIMITER).append(Wrap.inBackticks(table.getName())).append(SqlKeyword.DELIMITER).append("(");
final List<SQLiteColumn> columns = table.getSortedColumns();
final Iterator<SQLiteColumn> columnsIterator = columns.iterator();
while (columnsIterator.hasNext()) {
final String columnName = columnsIterator.next().getName();
stringBuilder.append(Wrap.inBackticks(columnName));
if (columnsIterator.hasNext()) {
stringBuilder.append(",").append(SqlKeyword.DELIMITER);
}
}
stringBuilder.append(")").append(SqlKeyword.DELIMITER).append("VALUES").append(SqlKeyword.DELIMITER).append("(");
for (int i = 0; i < columns.size(); i++) {
if (i == columns.size() - 1) {
stringBuilder.append("?");
} else {
stringBuilder.append("?, ");
}
}
stringBuilder.append(")");
final String preparedInsertStatement = stringBuilder.toString();
return new SqlCommand(table.getName(), preparedInsertStatement, // VALUES clause
extractFieldValues(item));
}
use of com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable in project amplify-android by aws-amplify.
the class SQLiteCommandFactory method recursivelyBuildJoins.
/**
* Recursively build joins for multilevel nested joins.
*/
private void recursivelyBuildJoins(SQLiteTable table, Map<String, List<SQLiteColumn>> columns, StringBuilder joinStatement, Map<String, Integer> tableCount, String tableAlias) {
// Joins the foreign keys
// LEFT JOIN if foreign key is optional, INNER JOIN otherwise.
final Iterator<SQLiteColumn> foreignKeyIterator = table.getForeignKeys().iterator();
while (foreignKeyIterator.hasNext()) {
final SQLiteColumn foreignKey = foreignKeyIterator.next();
final String ownedTableName = foreignKey.getOwnedType();
final ModelSchema ownedSchema = schemaRegistry.getModelSchemaForModelClass(ownedTableName);
final SQLiteTable ownedTable = SQLiteTable.fromSchema(ownedSchema);
int newOwnedTableCount = 1;
String ownedTableAlias = ownedTableName;
if (tableCount.containsKey(ownedTableName)) {
Integer currentOwnedTableCount = tableCount.get(ownedTableName);
newOwnedTableCount += currentOwnedTableCount == null ? 0 : currentOwnedTableCount;
ownedTableAlias += newOwnedTableCount;
}
tableCount.put(ownedTableName, newOwnedTableCount);
columns.put(ownedTableAlias, ownedTable.getSortedColumns());
SqlKeyword joinType = foreignKey.isNonNull() ? SqlKeyword.INNER_JOIN : SqlKeyword.LEFT_JOIN;
joinStatement.append(joinType).append(SqlKeyword.DELIMITER).append(Wrap.inBackticks(ownedTableName)).append(SqlKeyword.DELIMITER);
if (!ownedTableName.equals(ownedTableAlias)) {
joinStatement.append(SqlKeyword.AS).append(SqlKeyword.DELIMITER).append(Wrap.inBackticks(ownedTableAlias)).append(SqlKeyword.DELIMITER);
}
// Reference the foreign key and primary key using the corresponding table's alias.
String foreignKeyName = foreignKey.getQuotedColumnName().replace(table.getName(), tableAlias);
String ownedTablePrimaryKeyName = ownedTable.getPrimaryKeyColumnName().replace(ownedTableName, ownedTableAlias);
joinStatement.append(SqlKeyword.ON).append(SqlKeyword.DELIMITER).append(foreignKeyName).append(SqlKeyword.EQUAL).append(ownedTablePrimaryKeyName);
if (foreignKeyIterator.hasNext()) {
joinStatement.append(SqlKeyword.DELIMITER);
}
// important that this comes last to maintain the order of the joins
recursivelyBuildJoins(ownedTable, columns, joinStatement, tableCount, ownedTableAlias);
}
}
use of com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable in project amplify-android by aws-amplify.
the class SQLiteModelTree method recurseTree.
private void recurseTree(Map<ModelSchema, Set<String>> map, ModelSchema modelSchema, Collection<String> parentIds) {
for (ModelAssociation association : modelSchema.getAssociations().values()) {
switch(association.getName()) {
case "HasOne":
case "HasMany":
// model name
String childModel = association.getAssociatedType();
ModelSchema childSchema = registry.getModelSchemaForModelClass(childModel);
SQLiteTable childTable = SQLiteTable.fromSchema(childSchema);
String childId;
String parentId;
try {
childId = childTable.getPrimaryKey().getName();
parentId = // get a map of associations
childSchema.getAssociations().get(// get @BelongsTo association linked to this field
association.getAssociatedName()).getTargetName();
} catch (NullPointerException unexpectedAssociation) {
LOG.warn("Foreign key was not found due to unidirectional relationship without @BelongsTo. " + "Failed to publish cascading mutations.", unexpectedAssociation);
return;
}
// Collect every children one level deeper than current level
Set<String> childrenIds = new HashSet<>();
try (Cursor cursor = queryChildren(childTable.getName(), childId, parentId, parentIds)) {
if (cursor != null && cursor.moveToFirst()) {
int index = cursor.getColumnIndexOrThrow(childId);
do {
childrenIds.add(cursor.getString(index));
} while (cursor.moveToNext());
}
} catch (SQLiteException exception) {
// Don't cut the search short. Populate rest of the tree.
LOG.warn("Failed to query children of deleted model(s).", exception);
}
// Add queried result to the map
if (!childrenIds.isEmpty()) {
if (!map.containsKey(childSchema)) {
map.put(childSchema, childrenIds);
} else {
map.get(childSchema).addAll(childrenIds);
}
recurseTree(map, childSchema, childrenIds);
}
break;
case "BelongsTo":
default:
}
}
}
use of com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable in project amplify-android by aws-amplify.
the class SQLiteStorageAdapter method writeData.
private <T extends Model> void writeData(T item, StorageItemChange.Type writeType) throws DataStoreException {
final String modelName = item.getModelName();
final ModelSchema modelSchema = schemaRegistry.getModelSchemaForModelClass(modelName);
final SQLiteTable sqliteTable = SQLiteTable.fromSchema(modelSchema);
// Generate SQL command for given action
switch(writeType) {
case CREATE:
LOG.verbose("Creating item in " + sqliteTable.getName() + " identified by ID: " + item.getId());
sqlCommandProcessor.execute(sqlCommandFactory.insertFor(modelSchema, item));
break;
case UPDATE:
LOG.verbose("Updating item in " + sqliteTable.getName() + " identified by ID: " + item.getId());
sqlCommandProcessor.execute(sqlCommandFactory.updateFor(modelSchema, item));
break;
case DELETE:
LOG.verbose("Deleting item in " + sqliteTable.getName() + " identified by ID: " + item.getId());
final String primaryKeyName = sqliteTable.getPrimaryKey().getName();
final QueryPredicate matchId = QueryField.field(modelName, primaryKeyName).eq(item.getId());
sqlCommandProcessor.execute(sqlCommandFactory.deleteFor(modelSchema, matchId));
break;
default:
throw new DataStoreException("Unexpected change was requested: " + writeType.name(), "Valid storage changes are CREATE, UPDATE, and DELETE.");
}
}
Aggregations