Search in sources :

Example 11 with SQLiteTable

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);
}
Also used : ModelIndex(com.amplifyframework.core.model.ModelIndex) SQLiteTable(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable) HashSet(java.util.HashSet) NonNull(androidx.annotation.NonNull)

Example 12 with SQLiteTable

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));
}
Also used : SQLiteColumn(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteColumn) SQLiteTable(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable) NonNull(androidx.annotation.NonNull)

Example 13 with SQLiteTable

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);
    }
}
Also used : ModelSchema(com.amplifyframework.core.model.ModelSchema) SQLiteColumn(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteColumn) SQLiteTable(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable)

Example 14 with SQLiteTable

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:
        }
    }
}
Also used : ModelSchema(com.amplifyframework.core.model.ModelSchema) ModelAssociation(com.amplifyframework.core.model.ModelAssociation) SQLiteTable(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable) Cursor(android.database.Cursor) SQLiteException(android.database.sqlite.SQLiteException) HashSet(java.util.HashSet)

Example 15 with SQLiteTable

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.");
    }
}
Also used : ModelSchema(com.amplifyframework.core.model.ModelSchema) DataStoreException(com.amplifyframework.datastore.DataStoreException) QueryPredicate(com.amplifyframework.core.model.query.predicate.QueryPredicate) SQLiteTable(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable)

Aggregations

SQLiteTable (com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable)15 NonNull (androidx.annotation.NonNull)8 ModelSchema (com.amplifyframework.core.model.ModelSchema)8 QueryPredicate (com.amplifyframework.core.model.query.predicate.QueryPredicate)6 SQLiteColumn (com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteColumn)5 ArrayList (java.util.ArrayList)5 SQLPredicate (com.amplifyframework.datastore.storage.sqlite.adapter.SQLPredicate)4 Cursor (android.database.Cursor)3 DataStoreException (com.amplifyframework.datastore.DataStoreException)3 AmplifyException (com.amplifyframework.AmplifyException)2 Model (com.amplifyframework.core.model.Model)2 ModelAssociation (com.amplifyframework.core.model.ModelAssociation)2 ModelField (com.amplifyframework.core.model.ModelField)2 SerializedModel (com.amplifyframework.core.model.SerializedModel)2 ObserveQueryOptions (com.amplifyframework.core.model.query.ObserveQueryOptions)2 QueryOptions (com.amplifyframework.core.model.query.QueryOptions)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 List (java.util.List)2 Context (android.content.Context)1