From f1325a6d7a5ab7e63637178838e4910159a48d18 Mon Sep 17 00:00:00 2001 From: Alexander Frank Date: Tue, 9 Sep 2014 11:47:34 +0200 Subject: [PATCH] Splitting up combined indices for primary and foreign keys to use simple single column indices --- .../datarobot/PersistenceDefinition.java | 11 +- .../builder/schema/writer/TableWriter.java | 333 +++++++++--------- .../writer/ToManyAssociationWriter.java | 43 ++- .../DatarobotPerformanceTests/build.gradle | 4 +- examples/Notes/build.gradle | 4 +- 5 files changed, 202 insertions(+), 193 deletions(-) diff --git a/Datarobot/src/main/java/com/arconsis/android/datarobot/PersistenceDefinition.java b/Datarobot/src/main/java/com/arconsis/android/datarobot/PersistenceDefinition.java index 3e71a70..7a1790a 100644 --- a/Datarobot/src/main/java/com/arconsis/android/datarobot/PersistenceDefinition.java +++ b/Datarobot/src/main/java/com/arconsis/android/datarobot/PersistenceDefinition.java @@ -17,8 +17,6 @@ import android.content.Context; -import com.arconsis.android.datarobot.schema.SchemaConstants; - import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; @@ -31,6 +29,7 @@ import static com.arconsis.android.datarobot.schema.SchemaConstants.GENERATED_SUFFIX; import static com.arconsis.android.datarobot.schema.SchemaConstants.LINK; import static com.arconsis.android.datarobot.schema.SchemaConstants.SQL_CREATION; +import static com.arconsis.android.datarobot.schema.SchemaConstants.SQL_INDEX; import static com.arconsis.android.datarobot.schema.SchemaConstants.TABLE; import static com.arconsis.android.datarobot.schema.SchemaConstants.UPDATE_HOOK; @@ -103,8 +102,12 @@ private static PersistenceDefinition loadPersistenceData(final Context context) String statement = (String) def.getDeclaredField(SQL_CREATION).get(null); creationStatements.add(statement); - String indexing = (String) def.getDeclaredField(SchemaConstants.SQL_INDEX).get(null); - indexStatements.add(indexing); + Field[] allFields = def.getDeclaredFields(); + for (Field field : allFields) { + if (field.getName().startsWith(SQL_INDEX)) { + indexStatements.add((String) field.get(null)); + } + } } } diff --git a/DatarobotProcessor/src/main/java/com/arconsis/android/datarobot/builder/schema/writer/TableWriter.java b/DatarobotProcessor/src/main/java/com/arconsis/android/datarobot/builder/schema/writer/TableWriter.java index b9d2f36..06c9a38 100644 --- a/DatarobotProcessor/src/main/java/com/arconsis/android/datarobot/builder/schema/writer/TableWriter.java +++ b/DatarobotProcessor/src/main/java/com/arconsis/android/datarobot/builder/schema/writer/TableWriter.java @@ -15,6 +15,18 @@ */ package com.arconsis.android.datarobot.builder.schema.writer; +import com.arconsis.android.datarobot.builder.schema.data.Association; +import com.arconsis.android.datarobot.builder.schema.data.Column; +import com.arconsis.android.datarobot.builder.schema.data.Table; +import com.arconsis.android.datarobot.schema.AssociationType; +import com.arconsis.android.datarobot.schema.SchemaConstants; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; + import static com.arconsis.android.datarobot.builder.Constants.CONSTANT_ATTRIBUTE_ARRAY; import static com.arconsis.android.datarobot.builder.Constants.CONSTANT_STRING; import static com.arconsis.android.datarobot.builder.Constants.CONSTANT_STRING_ARRAY; @@ -30,174 +42,165 @@ import static com.arconsis.android.datarobot.schema.SchemaConstants.TABLE_NAME; import static java.lang.String.format; -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; - -import com.arconsis.android.datarobot.builder.schema.data.Association; -import com.arconsis.android.datarobot.builder.schema.data.Column; -import com.arconsis.android.datarobot.builder.schema.data.Table; -import com.arconsis.android.datarobot.schema.AssociationType; -import com.arconsis.android.datarobot.schema.SchemaConstants; - /** * @author Alexander Frank * @author Falk Appel */ public class TableWriter implements Writer { - private final String indent; - private final Table table; - - public TableWriter(final String indent, final Table table) { - this.indent = indent; - this.table = table; - } - - @Override - public String write() { - StringBuilder builder = new StringBuilder(indent); - List columnNames = new LinkedList(); - List toOneAssociationNames = new LinkedList(); - List columnSql = new LinkedList(); - - addDeclaration(builder); - addTableData(builder); - addColumns(builder, columnSql, columnNames, toOneAssociationNames); - addSqlStatment(builder, columnSql); - addProjection(builder, columnNames, toOneAssociationNames); - addAttributes(builder, columnNames); - addAssociations(builder); - addEnd(builder); - - return builder.toString(); - } - - private void addDeclaration(final StringBuilder builder) { - builder.append("public interface ").append(table.getName()).append(TABLE).append(" {\n"); - } - - private void addTableData(final StringBuilder builder) { - builder.append(indent).append(TAB).append(format(CONSTANT_STRING, CLASS_NAME, table.getEntityClassName())); - builder.append(indent).append(TAB).append(format(CONSTANT_STRING, TABLE_NAME, table.getName())); - builder.append("\n"); - } - - private void addColumns(final StringBuilder builder, final List columnSql, final List columnNames, final List toOneAssociationNames) { - int columnIdx = 0; - for (Column column : table.getColumns()) { - ColumnWriter columnWriter = new ColumnWriter(TAB, column, columnIdx++); - builder.append(columnWriter.write()); - columnSql.add(columnWriter.getSql()); - columnNames.add(column.getNameInEntity()); - } - for (Association association : table.getAssociations()) { - if (association.getCardinality() == AssociationType.TO_ONE) { - ToOneAssociationAttributeWriter toOneAssociationWriter = new ToOneAssociationAttributeWriter(TAB, association, columnIdx++); - builder.append(toOneAssociationWriter.write()); - columnSql.add(toOneAssociationWriter.getSql()); - toOneAssociationNames.add(FOREIGN_KEY + association.getNameInEntity()); - } - } - builder.append("\n"); - } - - private void addSqlStatment(final StringBuilder builder, final List columnSql) { - StringBuilder statment = new StringBuilder("CREATE TABLE "); - statment.append(table.getName()).append(" ("); - statment.append(concat(columnSql, new None())); - statment.append(")"); - - builder.append(indent).append(TAB).append(format(CONSTANT_STRING, SQL_CREATION, statment.toString())); - - StringBuilder index = new StringBuilder("CREATE INDEX "); - index.append(table.getName().toLowerCase()).append(INDEX_SUFFIX); - index.append(" on ").append(table.getName()).append(" ("); - index.append(concat(filterIndexableColumns(), new None())); - index.append(")"); - builder.append(indent).append(TAB).append(format(CONSTANT_STRING, SQL_INDEX, index.toString())); - } - - private void addProjection(final StringBuilder builder, final List columnNames, final List toOneAssociationNames) { - List columnsWithForeignKeys = new LinkedList(columnNames); - columnsWithForeignKeys.addAll(toOneAssociationNames); - - builder.append(indent).append(TAB).append(format(CONSTANT_STRING_ARRAY, PROJECTION, concat(columnsWithForeignKeys, new Quote()))); - } - - private void addAttributes(final StringBuilder builder, final List columnNames) { - builder.append(indent).append(TAB).append(format(CONSTANT_ATTRIBUTE_ARRAY, ATTRIBUTES, concat(columnNames, new UpperCase()))); - builder.append("\n"); - } - - private void addAssociations(final StringBuilder builder) { - if (table.getAssociations().size() > 0) { - builder.append(indent).append(TAB).append("public interface ").append(SchemaConstants.ASSOCIATIONS_INTERFACE).append(" {\n"); - for (Association association : table.getAssociations()) { - AssociationsInterfaceWriter associationWriter = new AssociationsInterfaceWriter(indent + TAB + TAB, table, association); - builder.append(associationWriter.write()); - } - builder.append(indent).append(TAB).append("}\n"); - } - } - - private void addEnd(final StringBuilder builder) { - builder.append(indent).append("}\n"); - } - - private Collection filterIndexableColumns() { - Collection indexable = new ArrayList(); - for (Column column : table.getColumns()) { - if (column.isPrimary()) { - indexable.add(column.getNameInEntity()); - } - } - for (Association association : table.getAssociations()) { - if (AssociationType.TO_ONE == association.getCardinality()) { - indexable.add(FOREIGN_KEY + association.getNameInEntity()); - } - } - return indexable; - } - - private String concat(final Collection columns, final StringRefine refiner) { - StringBuilder namesConcat = new StringBuilder(); - int counter = 0; - for (String name : columns) { - namesConcat.append(refiner.refine(name)); - if (counter++ < columns.size() - 1) { - namesConcat.append(", "); - } - } - return namesConcat.toString(); - } - - private interface StringRefine { - String refine(String input); - } - - private final class Quote implements StringRefine { - @Override - public String refine(final String input) { - return "\"" + input + "\""; - } - } - - public class UpperCase implements StringRefine { - @Override - public String refine(final String input) { - return input.toUpperCase(Locale.getDefault()); - } - - } - - private final class None implements StringRefine { - @Override - public String refine(final String input) { - return input; - } - } - - } + private final String indent; + private final Table table; + + public TableWriter(final String indent, final Table table) { + this.indent = indent; + this.table = table; + } + + @Override + public String write() { + StringBuilder builder = new StringBuilder(indent); + List columnNames = new LinkedList(); + List toOneAssociationNames = new LinkedList(); + List columnSql = new LinkedList(); + + addDeclaration(builder); + addTableData(builder); + addColumns(builder, columnSql, columnNames, toOneAssociationNames); + addSqlStatement(builder, columnSql); + addProjection(builder, columnNames, toOneAssociationNames); + addAttributes(builder, columnNames); + addAssociations(builder); + addEnd(builder); + + return builder.toString(); + } + + private void addDeclaration(final StringBuilder builder) { + builder.append("public interface ").append(table.getName()).append(TABLE).append(" {\n"); + } + + private void addTableData(final StringBuilder builder) { + builder.append(indent).append(TAB).append(format(CONSTANT_STRING, CLASS_NAME, table.getEntityClassName())); + builder.append(indent).append(TAB).append(format(CONSTANT_STRING, TABLE_NAME, table.getName())); + builder.append("\n"); + } + + private void addColumns(final StringBuilder builder, final List columnSql, final List columnNames, + final List toOneAssociationNames) { + int columnIdx = 0; + for (Column column : table.getColumns()) { + ColumnWriter columnWriter = new ColumnWriter(TAB, column, columnIdx++); + builder.append(columnWriter.write()); + columnSql.add(columnWriter.getSql()); + columnNames.add(column.getNameInEntity()); + } + for (Association association : table.getAssociations()) { + if (association.getCardinality() == AssociationType.TO_ONE) { + ToOneAssociationAttributeWriter toOneAssociationWriter = new ToOneAssociationAttributeWriter(TAB, association, columnIdx++); + builder.append(toOneAssociationWriter.write()); + columnSql.add(toOneAssociationWriter.getSql()); + toOneAssociationNames.add(FOREIGN_KEY + association.getNameInEntity()); + } + } + builder.append("\n"); + } + + private void addSqlStatement(final StringBuilder builder, final List columnSql) { + StringBuilder statement = new StringBuilder("CREATE TABLE "); + statement.append(table.getName()).append(" ("); + statement.append(concat(columnSql, new None())); + statement.append(")"); + + builder.append(indent).append(TAB).append(format(CONSTANT_STRING, SQL_CREATION, statement.toString())); + + for (String column : filterIndexableColumns()) { + StringBuilder index = new StringBuilder("CREATE INDEX "); + index.append(table.getName().toLowerCase()).append("_").append(column.toLowerCase()).append(INDEX_SUFFIX); + index.append(" on ").append(table.getName()).append(" ("); + index.append(column); + index.append(")"); + builder.append(indent).append(TAB).append(format(CONSTANT_STRING, SQL_INDEX + "_" + column.toUpperCase(), index.toString())); + } + } + + private void addProjection(final StringBuilder builder, final List columnNames, final List toOneAssociationNames) { + List columnsWithForeignKeys = new LinkedList(columnNames); + columnsWithForeignKeys.addAll(toOneAssociationNames); + + builder.append(indent).append(TAB).append(format(CONSTANT_STRING_ARRAY, PROJECTION, concat(columnsWithForeignKeys, new Quote()))); + } + + private void addAttributes(final StringBuilder builder, final List columnNames) { + builder.append(indent).append(TAB).append(format(CONSTANT_ATTRIBUTE_ARRAY, ATTRIBUTES, concat(columnNames, new UpperCase()))); + builder.append("\n"); + } + + private void addAssociations(final StringBuilder builder) { + if (table.getAssociations().size() > 0) { + builder.append(indent).append(TAB).append("public interface ").append(SchemaConstants.ASSOCIATIONS_INTERFACE).append(" {\n"); + for (Association association : table.getAssociations()) { + AssociationsInterfaceWriter associationWriter = new AssociationsInterfaceWriter(indent + TAB + TAB, table, association); + builder.append(associationWriter.write()); + } + builder.append(indent).append(TAB).append("}\n"); + } + } + + private void addEnd(final StringBuilder builder) { + builder.append(indent).append("}\n"); + } + + private Collection filterIndexableColumns() { + Collection indexable = new ArrayList(); + for (Column column : table.getColumns()) { + if (column.isPrimary()) { + indexable.add(column.getNameInEntity()); + } + } + for (Association association : table.getAssociations()) { + if (AssociationType.TO_ONE == association.getCardinality()) { + indexable.add(FOREIGN_KEY + association.getNameInEntity()); + } + } + return indexable; + } + + private String concat(final Collection columns, final StringRefine refiner) { + StringBuilder namesConcat = new StringBuilder(); + int counter = 0; + for (String name : columns) { + namesConcat.append(refiner.refine(name)); + if (counter++ < columns.size() - 1) { + namesConcat.append(", "); + } + } + return namesConcat.toString(); + } + + private interface StringRefine { + String refine(String input); + } + + private final class Quote implements StringRefine { + @Override + public String refine(final String input) { + return "\"" + input + "\""; + } + } + + public class UpperCase implements StringRefine { + @Override + public String refine(final String input) { + return input.toUpperCase(Locale.getDefault()); + } + + } + + private final class None implements StringRefine { + @Override + public String refine(final String input) { + return input; + } + } + +} diff --git a/DatarobotProcessor/src/main/java/com/arconsis/android/datarobot/builder/schema/writer/ToManyAssociationWriter.java b/DatarobotProcessor/src/main/java/com/arconsis/android/datarobot/builder/schema/writer/ToManyAssociationWriter.java index 18c4e47..66f9e34 100644 --- a/DatarobotProcessor/src/main/java/com/arconsis/android/datarobot/builder/schema/writer/ToManyAssociationWriter.java +++ b/DatarobotProcessor/src/main/java/com/arconsis/android/datarobot/builder/schema/writer/ToManyAssociationWriter.java @@ -15,6 +15,11 @@ */ package com.arconsis.android.datarobot.builder.schema.writer; +import com.arconsis.android.datarobot.schema.SchemaConstants; +import com.arconsis.android.datarobot.util.Pair; + +import java.util.Locale; + import static com.arconsis.android.datarobot.builder.Constants.CONSTANT_ATTRIBUTE_ARRAY; import static com.arconsis.android.datarobot.builder.Constants.CONSTANT_PREFIX; import static com.arconsis.android.datarobot.builder.Constants.CONSTANT_STRING; @@ -31,11 +36,6 @@ import static com.arconsis.android.datarobot.schema.SchemaConstants.TO_SUFFIX; import static java.lang.String.format; -import java.util.Locale; - -import com.arconsis.android.datarobot.schema.SchemaConstants; -import com.arconsis.android.datarobot.util.Pair; - /** * @author Alexander Frank * @author Falk Appel @@ -72,7 +72,7 @@ public String write() { addAttribute(builder, canonicalLeft, simpleLeftLower, 0, FROM_SUFFIX); addAttribute(builder, canonicalRight, simpleRightLower, 1, TO_SUFFIX); builder.append("\n"); - addSqlStatment(builder); + addSqlStatement(builder); addProjection(builder); addAttributes(builder); addEnd(builder); @@ -100,24 +100,31 @@ private void addAttribute(final StringBuilder builder, final String canonicalNam } - private void addSqlStatment(final StringBuilder builder) { - String fromColumn = simpleLeftLower + FROM_SUFFIX; - String toColumn = simpleRightLower + TO_SUFFIX; + private void addSqlStatement(final StringBuilder builder) { + String fromColumn = FOREIGN_KEY + simpleLeftLower + FROM_SUFFIX; + String toColumn = FOREIGN_KEY + simpleRightLower + TO_SUFFIX; - StringBuilder statment = new StringBuilder("CREATE TABLE "); - statment.append(tableName).append("("); - statment.append(FOREIGN_KEY).append(fromColumn).append(" Integer, "); - statment.append(FOREIGN_KEY).append(toColumn).append(" Integer, "); - statment.append("UNIQUE(").append(FOREIGN_KEY).append(fromColumn).append(", ").append(FOREIGN_KEY).append(toColumn).append(") ON CONFLICT IGNORE)"); + StringBuilder statement = new StringBuilder("CREATE TABLE "); + statement.append(tableName).append("("); + statement.append(fromColumn).append(" Integer, "); + statement.append(toColumn).append(" Integer, "); + statement.append("UNIQUE(").append(fromColumn).append(", ").append(toColumn).append(") ON CONFLICT IGNORE)"); + + builder.append(indent).append(TAB).append(format(CONSTANT_STRING, SQL_CREATION, statement.toString())); + + builder.append(indent).append(TAB).append(createIndexStatement(tableName, fromColumn)); + builder.append(indent).append(TAB).append(createIndexStatement(tableName, toColumn)); + } - builder.append(indent).append(TAB).append(format(CONSTANT_STRING, SQL_CREATION, statment.toString())); + private String createIndexStatement(String tableName, String columnName) { + String lowerColumnName = columnName.toLowerCase(); StringBuilder index = new StringBuilder("CREATE INDEX "); - index.append(simpleLeftLower).append(simpleRightLower).append(INDEX_SUFFIX); + index.append(tableName.toLowerCase()).append("_").append(lowerColumnName).append(INDEX_SUFFIX); index.append(" on ").append(tableName).append(" ("); - index.append(FOREIGN_KEY).append(fromColumn).append(", ").append(FOREIGN_KEY).append(toColumn); + index.append(columnName); index.append(")"); - builder.append(indent).append(TAB).append(format(CONSTANT_STRING, SQL_INDEX, index.toString())); + return format(CONSTANT_STRING, SQL_INDEX + "_" + lowerColumnName, index.toString()); } private void addProjection(final StringBuilder builder) { diff --git a/examples/DatarobotPerformanceTests/build.gradle b/examples/DatarobotPerformanceTests/build.gradle index 0093301..a7ad3b6 100644 --- a/examples/DatarobotPerformanceTests/build.gradle +++ b/examples/DatarobotPerformanceTests/build.gradle @@ -1,19 +1,17 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { - jcenter() mavenCentral() mavenLocal() } dependencies { classpath 'com.android.tools.build:gradle:0.12.2' - classpath 'com.neenbedankt.gradle.plugins:android-apt:1.2+' + classpath 'com.neenbedankt.gradle.plugins:android-apt:1.2' } } allprojects { repositories { - jcenter() mavenCentral() mavenLocal() } diff --git a/examples/Notes/build.gradle b/examples/Notes/build.gradle index 0093301..a7ad3b6 100644 --- a/examples/Notes/build.gradle +++ b/examples/Notes/build.gradle @@ -1,19 +1,17 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { - jcenter() mavenCentral() mavenLocal() } dependencies { classpath 'com.android.tools.build:gradle:0.12.2' - classpath 'com.neenbedankt.gradle.plugins:android-apt:1.2+' + classpath 'com.neenbedankt.gradle.plugins:android-apt:1.2' } } allprojects { repositories { - jcenter() mavenCentral() mavenLocal() }