Search in sources :

Example 6 with SQLiteColumn

use of com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteColumn 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 7 with SQLiteColumn

use of com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteColumn 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 8 with SQLiteColumn

use of com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteColumn in project amplify-android by aws-amplify.

the class SQLiteModelFieldTypeConverter method convertValueFromSource.

@Override
public Object convertValueFromSource(@NonNull Cursor cursor, @NonNull ModelField field) throws DataStoreException {
    final JavaFieldType javaFieldType = TypeConverter.getJavaFieldType(field);
    try {
        // Skip if there is no equivalent column for field in object
        final SQLiteColumn column = columns.get(field.getName());
        if (column == null) {
            LOGGER.verbose(String.format("Column with name %s does not exist", field.getName()));
            return null;
        }
        String columnName = column.getAliasedName();
        if (javaFieldType == JavaFieldType.MODEL) {
            int newInnerModelCount = 1;
            String fieldTargetType = field.getTargetType();
            if (cursorInnerModelCounts.containsKey(fieldTargetType)) {
                Integer currentInnerModelCount = cursorInnerModelCounts.get(fieldTargetType);
                newInnerModelCount += currentInnerModelCount == null ? 0 : currentInnerModelCount;
            }
            cursorInnerModelCounts.put(fieldTargetType, newInnerModelCount);
        }
        if (isInnerModel && cursorInnerModelCounts.containsKey(parentSchema.getName())) {
            Integer modelCount = cursorInnerModelCounts.get(parentSchema.getName());
            if (!Objects.equals(modelCount, 1)) {
                // More than 1 of the model the field belongs to is present in the cursor
                columnName += modelCount;
            }
        }
        final int columnIndex = cursor.getColumnIndexOrThrow(columnName);
        // This check is necessary, because primitive values will return 0 even when null
        if (cursor.isNull(columnIndex)) {
            return null;
        }
        final String valueAsString = cursor.getString(columnIndex);
        LOGGER.verbose(String.format("Attempt to convert value \"%s\" from field %s of type %s in model %s", valueAsString, field.getName(), field.getTargetType(), parentSchema.getName()));
        switch(javaFieldType) {
            case STRING:
                return cursor.getString(columnIndex);
            case MODEL:
                return convertModelAssociationToTarget(cursor, field);
            case ENUM:
                return convertEnumValueToTarget(valueAsString, field);
            case CUSTOM_TYPE:
                return convertCustomTypeToTarget(cursor, field, columnIndex);
            case INTEGER:
                return cursor.getInt(columnIndex);
            case BOOLEAN:
                return cursor.getInt(columnIndex) != 0;
            case FLOAT:
                return cursor.getFloat(columnIndex);
            case DOUBLE:
                return cursor.getDouble(columnIndex);
            case LONG:
                return cursor.getLong(columnIndex);
            case DATE:
                return new Temporal.Date(valueAsString);
            case DATE_TIME:
                return new Temporal.DateTime(valueAsString);
            case TIME:
                return new Temporal.Time(valueAsString);
            case TIMESTAMP:
                return new Temporal.Timestamp(cursor.getLong(columnIndex), TimeUnit.SECONDS);
            default:
                LOGGER.warn(String.format("Field of type %s is not supported. Fallback to null.", javaFieldType));
                return null;
        }
    } catch (Exception exception) {
        throw new DataStoreException(String.format("Error converting field \"%s\" from model \"%s\"", field.getName(), parentSchema.getName()), exception, AmplifyException.REPORT_BUG_TO_AWS_SUGGESTION);
    }
}
Also used : DataStoreException(com.amplifyframework.datastore.DataStoreException) SQLiteColumn(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteColumn) LocalTime(java.time.LocalTime) OffsetTime(java.time.OffsetTime) OffsetDateTime(java.time.OffsetDateTime) JavaFieldType(com.amplifyframework.core.model.types.JavaFieldType) OffsetDateTime(java.time.OffsetDateTime) AmplifyException(com.amplifyframework.AmplifyException) IOException(java.io.IOException) DataStoreException(com.amplifyframework.datastore.DataStoreException)

Aggregations

SQLiteColumn (com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteColumn)8 SQLiteTable (com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable)5 NonNull (androidx.annotation.NonNull)3 ModelSchema (com.amplifyframework.core.model.ModelSchema)2 QueryPredicate (com.amplifyframework.core.model.query.predicate.QueryPredicate)2 SQLPredicate (com.amplifyframework.datastore.storage.sqlite.adapter.SQLPredicate)2 ArrayList (java.util.ArrayList)2 AmplifyException (com.amplifyframework.AmplifyException)1 ModelField (com.amplifyframework.core.model.ModelField)1 QueryPaginationInput (com.amplifyframework.core.model.query.QueryPaginationInput)1 QuerySortBy (com.amplifyframework.core.model.query.QuerySortBy)1 QueryPredicateOperation (com.amplifyframework.core.model.query.predicate.QueryPredicateOperation)1 JavaFieldType (com.amplifyframework.core.model.types.JavaFieldType)1 DataStoreException (com.amplifyframework.datastore.DataStoreException)1 IOException (java.io.IOException)1 LocalTime (java.time.LocalTime)1 OffsetDateTime (java.time.OffsetDateTime)1 OffsetTime (java.time.OffsetTime)1 HashMap (java.util.HashMap)1 List (java.util.List)1