diff --git a/core/src/main/kotlin/com/dbflow5/annotation/Fts.kt b/core/src/main/kotlin/com/dbflow5/annotation/Fts.kt new file mode 100644 index 000000000..074330d40 --- /dev/null +++ b/core/src/main/kotlin/com/dbflow5/annotation/Fts.kt @@ -0,0 +1,26 @@ +package com.dbflow5.annotation + +import kotlin.reflect.KClass + +/** + * Description: Creates a class using the SQLITE FTS3 [https://www.sqlite.org/fts3.html] + */ +@Retention(AnnotationRetention.SOURCE) +@Target(AnnotationTarget.CLASS) +annotation class Fts3 + + +/** + * Description: Creates a class using the SQLITE FTS4 [https://www.sqlite.org/fts3.html] + */ +@Retention(AnnotationRetention.SOURCE) +@Target(AnnotationTarget.CLASS) +annotation class Fts4( + /** + * Optionally points to a content table that fills this FTS4 with content. + * The content option allows FTS4 to forego storing the text being indexed and + * results in significant space savings. + */ + val contentTable: KClass<*> = Any::class +) + diff --git a/core/src/main/kotlin/com/dbflow5/annotation/Fts3.kt b/core/src/main/kotlin/com/dbflow5/annotation/Fts3.kt deleted file mode 100644 index 2a0f32000..000000000 --- a/core/src/main/kotlin/com/dbflow5/annotation/Fts3.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.dbflow5.annotation - -/** - * Description: Creates a class using the SQLITE FTS3 [https://www.sqlite.org/fts3.html] - */ -@Retention(AnnotationRetention.SOURCE) -@Target(AnnotationTarget.CLASS) -annotation class Fts3 \ No newline at end of file diff --git a/core/src/main/kotlin/com/dbflow5/annotation/Fts4.kt b/core/src/main/kotlin/com/dbflow5/annotation/Fts4.kt deleted file mode 100644 index 74485ae21..000000000 --- a/core/src/main/kotlin/com/dbflow5/annotation/Fts4.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.dbflow5.annotation - -import kotlin.reflect.KClass - -/** - * Description: Creates a class using the SQLITE FTS4 [https://www.sqlite.org/fts3.html] - */ -@Retention(AnnotationRetention.SOURCE) -@Target(AnnotationTarget.CLASS) -annotation class Fts4( - /** - * Optionally points to a content table that fills this FTS4 with content. - * The content option allows FTS4 to forego storing the text being indexed and - * results in significant space savings. - */ - val contentTable: KClass<*> = Any::class -) \ No newline at end of file diff --git a/lib/src/main/kotlin/com/dbflow5/query/Method.kt b/lib/src/main/kotlin/com/dbflow5/query/Method.kt index b387db600..ffdd62d93 100644 --- a/lib/src/main/kotlin/com/dbflow5/query/Method.kt +++ b/lib/src/main/kotlin/com/dbflow5/query/Method.kt @@ -264,7 +264,7 @@ inline fun offsets() = Method("offsets", tableName()) * @param start - the start match text. * @param end - the end match text * @param ellipses - * @param ftsTableColumnNumber - The FTS table column number to extract the returned fragments of + * @param index - The FTS table column number to extract the returned fragments of * text from. Columns are numbered from left to right starting with zero. * A negative value indicates that the text may be extracted from any column. * @param approximateTokens - The absolute value of this integer argument is used as the @@ -277,13 +277,13 @@ inline fun snippet( start: String? = null, end: String? = null, ellipses: String? = null, - ftsTableColumnNumber: Int? = null, + index: Int? = null, approximateTokens: Int? = null, ): Method { - val args = listOfNotNull(tableName(), start, end, ellipses, ftsTableColumnNumber, approximateTokens) + val args = listOfNotNull(tableName(), start, end, ellipses, index, approximateTokens) .map { if (it is String) propertyString("'${it}'") else propertyString(it.toString()) }.toTypedArray() return Method("snippet", *args) -} \ No newline at end of file +} diff --git a/processor/src/main/kotlin/com/dbflow5/processor/definition/Methods.kt b/processor/src/main/kotlin/com/dbflow5/processor/definition/Methods.kt index fe97743ec..3cad664c9 100644 --- a/processor/src/main/kotlin/com/dbflow5/processor/definition/Methods.kt +++ b/processor/src/main/kotlin/com/dbflow5/processor/definition/Methods.kt @@ -203,7 +203,7 @@ class CreationQueryMethod(private val tableDefinition: TableDefinition) : Method add("(") // FTS4 uses column names directly. add(tableDefinition.columnDefinitions.joinToString { it.columnName.quote() }) - tableDefinition.ftS4Behavior?.addContentTableCode(tableDefinition.columnDefinitions.isNotEmpty(), this) + tableDefinition.ftsBehavior?.addContentTableCode(tableDefinition.columnDefinitions.isNotEmpty(), this) add(")") }.S };\n") diff --git a/processor/src/main/kotlin/com/dbflow5/processor/definition/TableDefinition.kt b/processor/src/main/kotlin/com/dbflow5/processor/definition/TableDefinition.kt index a58cf8479..89349ac43 100644 --- a/processor/src/main/kotlin/com/dbflow5/processor/definition/TableDefinition.kt +++ b/processor/src/main/kotlin/com/dbflow5/processor/definition/TableDefinition.kt @@ -16,13 +16,16 @@ import com.dbflow5.processor.ClassNames import com.dbflow5.processor.ColumnValidator import com.dbflow5.processor.OneToManyValidator import com.dbflow5.processor.ProcessorManager -import com.dbflow5.processor.definition.BindToStatementMethod.Mode.* +import com.dbflow5.processor.definition.BindToStatementMethod.Mode.DELETE +import com.dbflow5.processor.definition.BindToStatementMethod.Mode.INSERT +import com.dbflow5.processor.definition.BindToStatementMethod.Mode.UPDATE import com.dbflow5.processor.definition.behavior.AssociationalBehavior import com.dbflow5.processor.definition.behavior.CachingBehavior import com.dbflow5.processor.definition.behavior.CreationQueryBehavior import com.dbflow5.processor.definition.behavior.CursorHandlingBehavior import com.dbflow5.processor.definition.behavior.FTS3Behavior import com.dbflow5.processor.definition.behavior.FTS4Behavior +import com.dbflow5.processor.definition.behavior.FtsBehavior import com.dbflow5.processor.definition.behavior.PrimaryKeyColumnBehavior import com.dbflow5.processor.definition.column.ColumnDefinition import com.dbflow5.processor.definition.column.DefinitionUtils @@ -97,21 +100,21 @@ class TableDefinition(private val table: Table, var implementsSqlStatementListener = false override val methods: Array = arrayOf( - BindToStatementMethod(this, INSERT), - BindToStatementMethod(this, UPDATE), - BindToStatementMethod(this, DELETE), - InsertStatementQueryMethod(this, InsertStatementQueryMethod.Mode.INSERT), - InsertStatementQueryMethod(this, InsertStatementQueryMethod.Mode.SAVE), - UpdateStatementQueryMethod(this), - DeleteStatementQueryMethod(this), - CreationQueryMethod(this), - LoadFromCursorMethod(this), - ExistenceMethod(this), - PrimaryConditionMethod(this), - OneToManyDeleteMethod(this), - OneToManySaveMethod(this, OneToManySaveMethod.METHOD_SAVE), - OneToManySaveMethod(this, OneToManySaveMethod.METHOD_INSERT), - OneToManySaveMethod(this, OneToManySaveMethod.METHOD_UPDATE)) + BindToStatementMethod(this, INSERT), + BindToStatementMethod(this, UPDATE), + BindToStatementMethod(this, DELETE), + InsertStatementQueryMethod(this, InsertStatementQueryMethod.Mode.INSERT), + InsertStatementQueryMethod(this, InsertStatementQueryMethod.Mode.SAVE), + UpdateStatementQueryMethod(this), + DeleteStatementQueryMethod(this), + CreationQueryMethod(this), + LoadFromCursorMethod(this), + ExistenceMethod(this), + PrimaryConditionMethod(this), + OneToManyDeleteMethod(this), + OneToManySaveMethod(this, OneToManySaveMethod.METHOD_SAVE), + OneToManySaveMethod(this, OneToManySaveMethod.METHOD_INSERT), + OneToManySaveMethod(this, OneToManySaveMethod.METHOD_UPDATE)) private val contentValueMethods: Array @@ -130,24 +133,23 @@ class TableDefinition(private val table: Table, var hasPrimaryConstructor = false override val associationalBehavior = AssociationalBehavior( - name = if (table.name.isNullOrEmpty()) element.simpleName.toString() else table.name, - databaseTypeName = table.extractTypeNameFromAnnotation { it.database }, - allFields = table.allFields) + name = if (table.name.isNullOrEmpty()) element.simpleName.toString() else table.name, + databaseTypeName = table.extractTypeNameFromAnnotation { it.database }, + allFields = table.allFields) override val cursorHandlingBehavior = CursorHandlingBehavior( - orderedCursorLookup = table.orderedCursorLookUp, - assignDefaultValuesFromCursor = table.assignDefaultValuesFromCursor) + orderedCursorLookup = table.orderedCursorLookUp, + assignDefaultValuesFromCursor = table.assignDefaultValuesFromCursor) val cachingBehavior = CachingBehavior( - cachingEnabled = table.cachingEnabled, - customCacheSize = table.cacheSize, - customCacheFieldName = null, - customMultiCacheFieldName = null) + cachingEnabled = table.cachingEnabled, + customCacheSize = table.cacheSize, + customCacheFieldName = null, + customMultiCacheFieldName = null) val type: Type - val ftS4Behavior: FTS4Behavior? - val ftS3Behavior: FTS3Behavior? + val ftsBehavior: FtsBehavior? init { setOutputClassName("_Table") @@ -167,25 +169,20 @@ class TableDefinition(private val table: Table, else -> Type.Normal } - ftS4Behavior = when { - fts4 != null -> FTS4Behavior(contentTable = fts4.extractTypeNameFromAnnotation { it.contentTable }, - databaseTypeName = associationalBehavior.databaseTypeName, - elementName = elementName, - manager = manager) - else -> null - } - - ftS3Behavior = when { - fts3 != null -> FTS3Behavior(elementName = elementName, - manager = manager) - else -> null + ftsBehavior = when (type) { + Type.FTS4 -> FTS4Behavior(contentTable = fts4!!.extractTypeNameFromAnnotation { it.contentTable }, + databaseTypeName = associationalBehavior.databaseTypeName, + elementName = elementName, + manager = manager) + Type.FTS3 -> FTS3Behavior(elementName, manager) + Type.Normal -> null } val inheritedColumns = table.inheritedColumns inheritedColumns.forEach { if (inheritedFieldNameList.contains(it.fieldName)) { manager.logError("A duplicate inherited column with name %1s was found for %1s", - it.fieldName, associationalBehavior.name) + it.fieldName, associationalBehavior.name) } inheritedFieldNameList.add(it.fieldName) inheritedColumnMap[it.fieldName] = it @@ -195,20 +192,20 @@ class TableDefinition(private val table: Table, inheritedPrimaryKeys.forEach { if (inheritedFieldNameList.contains(it.fieldName)) { manager.logError("A duplicate inherited column with name %1s was found for %1s", - it.fieldName, associationalBehavior.name) + it.fieldName, associationalBehavior.name) } inheritedFieldNameList.add(it.fieldName) inheritedPrimaryKeyMap[it.fieldName] = it } implementsContentValuesListener = element.implementsClass(manager.processingEnvironment, - ClassNames.CONTENT_VALUES_LISTENER) + ClassNames.CONTENT_VALUES_LISTENER) implementsSqlStatementListener = element.implementsClass(manager.processingEnvironment, - ClassNames.SQLITE_STATEMENT_LISTENER) + ClassNames.SQLITE_STATEMENT_LISTENER) contentValueMethods = arrayOf(BindToContentValuesMethod(this, true, implementsContentValuesListener), - BindToContentValuesMethod(this, false, implementsContentValuesListener)) + BindToContentValuesMethod(this, false, implementsContentValuesListener)) } @@ -247,11 +244,11 @@ class TableDefinition(private val table: Table, for (uniqueGroup in groups) { if (uniqueNumbersSet.contains(uniqueGroup.groupNumber)) { manager.logError("A duplicate unique group with number" + - " ${uniqueGroup.groupNumber} was found for ${associationalBehavior.name}") + " ${uniqueGroup.groupNumber} was found for ${associationalBehavior.name}") } val definition = UniqueGroupsDefinition(uniqueGroup) columnDefinitions.filter { it.uniqueGroups.contains(definition.number) } - .forEach { definition.addColumnDefinition(it) } + .forEach { definition.addColumnDefinition(it) } uniqueGroupsDefinitions.add(definition) uniqueNumbersSet.add(uniqueGroup.groupNumber) } @@ -261,11 +258,11 @@ class TableDefinition(private val table: Table, for (indexGroup in indexGroups) { if (uniqueNumbersSet.contains(indexGroup.number)) { manager.logError(TableDefinition::class, "A duplicate unique index number" + - " ${indexGroup.number} was found for $elementName") + " ${indexGroup.number} was found for $elementName") } val definition = IndexGroupsDefinition(this, indexGroup) columnDefinitions.filter { it.indexGroups.contains(definition.indexNumber) } - .forEach { definition.columnDefinitionList.add(it) } + .forEach { definition.columnDefinitionList.add(it) } indexGroupsDefinitions.add(definition) uniqueNumbersSet.add(indexGroup.number) } @@ -277,16 +274,16 @@ class TableDefinition(private val table: Table, for (element in elements) { classElementLookUpMap[element.simpleName.toString()] = element if (element is ExecutableElement && element.parameters.isEmpty() - && element.simpleName.toString() == "" - && element.enclosingElement == typeElement - && !element.modifiers.contains(Modifier.PRIVATE)) { + && element.simpleName.toString() == "" + && element.enclosingElement == typeElement + && !element.modifiers.contains(Modifier.PRIVATE)) { hasPrimaryConstructor = true } } if (!hasPrimaryConstructor) { manager.logError("For now, tables must have a visible, default, parameterless constructor. In" + - " Kotlin all field parameters must have default values.") + " Kotlin all field parameters must have default values.") } val columnValidator = ColumnValidator() @@ -305,28 +302,28 @@ class TableDefinition(private val table: Table, val isInheritedPrimaryKey = inheritedPrimaryKeyMap.containsKey(variableElement.simpleName.toString()) val isColumnMap = variableElement.annotation() != null if (variableElement.annotation() != null || isForeign || isPrimary - || isAllFields || isInherited || isInheritedPrimaryKey || isColumnMap) { + || isAllFields || isInherited || isInheritedPrimaryKey || isColumnMap) { if (checkInheritancePackagePrivate(isPackagePrivateNotInSamePackage, variableElement)) return val columnDefinition = if (isInheritedPrimaryKey) { val inherited = inheritedPrimaryKeyMap[variableElement.simpleName.toString()] ColumnDefinition(manager, variableElement, this, isPackagePrivateNotInSamePackage, - inherited?.column, inherited?.primaryKey) + inherited?.column, inherited?.primaryKey) } else if (isInherited) { val inherited = inheritedColumnMap[variableElement.simpleName.toString()] ColumnDefinition(manager, variableElement, this, isPackagePrivateNotInSamePackage, - inherited?.column, null, inherited?.nonNullConflict - ?: ConflictAction.NONE) + inherited?.column, null, inherited?.nonNullConflict + ?: ConflictAction.NONE) } else if (isForeign) { ReferenceColumnDefinition(variableElement.annotation()!!, manager, this, - variableElement, isPackagePrivateNotInSamePackage) + variableElement, isPackagePrivateNotInSamePackage) } else if (isColumnMap) { ReferenceColumnDefinition(variableElement.annotation()!!, - manager, this, variableElement, isPackagePrivateNotInSamePackage) + manager, this, variableElement, isPackagePrivateNotInSamePackage) } else { ColumnDefinition(manager, variableElement, - this, isPackagePrivateNotInSamePackage) + this, isPackagePrivateNotInSamePackage) } if (columnValidator.validate(manager, columnDefinition)) { @@ -341,16 +338,16 @@ class TableDefinition(private val table: Table, _primaryColumnDefinitions.add(columnDefinition) columnDefinition.type is ColumnDefinition.Type.PrimaryAutoIncrement -> { this.primaryKeyColumnBehavior = PrimaryKeyColumnBehavior( - hasRowID = false, - hasAutoIncrement = true, - associatedColumn = columnDefinition + hasRowID = false, + hasAutoIncrement = true, + associatedColumn = columnDefinition ) } columnDefinition.type is ColumnDefinition.Type.RowId -> { this.primaryKeyColumnBehavior = PrimaryKeyColumnBehavior( - hasRowID = true, - hasAutoIncrement = false, - associatedColumn = columnDefinition + hasRowID = true, + hasAutoIncrement = false, + associatedColumn = columnDefinition ) } } @@ -359,15 +356,14 @@ class TableDefinition(private val table: Table, // check to ensure not null. if (associatedColumn.isNullableType) { manager.logWarning("Attempting to use nullable field type on an autoincrementing column. " + - "To suppress or remove this warning " + - "switch to java primitive, add @android.support.annotation.NonNull," + - "@org.jetbrains.annotation.NotNull, or in Kotlin don't make it nullable. Check the column ${associatedColumn.columnName} " + - "on ${associationalBehavior.name}") + "To suppress or remove this warning " + + "switch to java primitive, add @android.support.annotation.NonNull," + + "@org.jetbrains.annotation.NotNull, or in Kotlin don't make it nullable. Check the column ${associatedColumn.columnName} " + + "on ${associationalBehavior.name}") } } - ftS3Behavior?.validateColumnDefinition(columnDefinition) - ftS4Behavior?.validateColumnDefinition(columnDefinition) + ftsBehavior?.validateColumnDefinition(columnDefinition) if (columnDefinition is ReferenceColumnDefinition) { if (!columnDefinition.isColumnMap) { @@ -380,7 +376,7 @@ class TableDefinition(private val table: Table, if (!columnDefinition.uniqueGroups.isEmpty()) { for (group in columnDefinition.uniqueGroups) { columnUniqueMap.getOrPut(group) { mutableSetOf() } - .add(columnDefinition) + .add(columnDefinition) } } } @@ -402,11 +398,11 @@ class TableDefinition(private val table: Table, override val primaryColumnDefinitions: List get() = primaryKeyColumnBehavior.associatedColumn?.let { arrayListOf(it) } - ?: when { - // fts4 use all columns, since there's no primary keys here. - ftS4Behavior != null -> columnDefinitions - else -> _primaryColumnDefinitions - } + ?: when { + // fts4 use all columns, since there's no primary keys here. + ftsBehavior != null -> columnDefinitions + else -> _primaryColumnDefinitions + } override val extendsClass: TypeName? get() = ParameterizedTypeName.get(ClassNames.MODEL_ADAPTER, elementClassName) @@ -439,7 +435,7 @@ class TableDefinition(private val table: Table, val getPropertiesBuilder = CodeBlock.builder() `override fun`(ClassNames.PROPERTY, "getProperty", - param(String::class, paramColumnName)) { + param(String::class, paramColumnName)) { modifiers(public, final) statement("$paramColumnName = \$T.quoteIfNeeded($paramColumnName)", ClassNames.STRING_UTILS) @@ -473,7 +469,7 @@ class TableDefinition(private val table: Table, val autoIncrement = primaryKeyColumnBehavior.associatedColumn autoIncrement?.let { `override fun`(TypeName.VOID, "updateAutoIncrement", param(elementClassName!!, ModelUtils.variable), - param(Number::class, "id")) { + param(Number::class, "id")) { modifiers(public, final) addCode(autoIncrement.updateAutoIncrementMethod) } @@ -481,32 +477,32 @@ class TableDefinition(private val table: Table, } val saveForeignKeyFields = columnDefinitions - .asSequence() - .filter { (it is ReferenceColumnDefinition) && it.foreignKeyColumnBehavior?.saveForeignKeyModel == true } - .map { it as ReferenceColumnDefinition } - .toList() + .asSequence() + .filter { (it is ReferenceColumnDefinition) && it.foreignKeyColumnBehavior?.saveForeignKeyModel == true } + .map { it as ReferenceColumnDefinition } + .toList() if (saveForeignKeyFields.isNotEmpty()) { val code = CodeBlock.builder() saveForeignKeyFields.forEach { it.appendSaveMethod(code) } `override fun`(TypeName.VOID, "saveForeignKeys", param(elementClassName!!, ModelUtils.variable), - param(ClassNames.DATABASE_WRAPPER, ModelUtils.wrapper)) { + param(ClassNames.DATABASE_WRAPPER, ModelUtils.wrapper)) { modifiers(public, final) addCode(code.build()) } } val deleteForeignKeyFields = columnDefinitions - .asSequence() - .filter { (it is ReferenceColumnDefinition) && it.foreignKeyColumnBehavior?.deleteForeignKeyModel == true } - .map { it as ReferenceColumnDefinition } - .toList() + .asSequence() + .filter { (it is ReferenceColumnDefinition) && it.foreignKeyColumnBehavior?.deleteForeignKeyModel == true } + .map { it as ReferenceColumnDefinition } + .toList() if (deleteForeignKeyFields.isNotEmpty()) { val code = CodeBlock.builder() deleteForeignKeyFields.forEach { it.appendDeleteMethod(code) } `override fun`(TypeName.VOID, "deleteForeignKeys", param(elementClassName!!, ModelUtils.variable), - param(ClassNames.DATABASE_WRAPPER, ModelUtils.wrapper)) { + param(ClassNames.DATABASE_WRAPPER, ModelUtils.wrapper)) { modifiers(public, final) addCode(code.build()) } @@ -543,70 +539,70 @@ class TableDefinition(private val table: Table, ", null" } add("\$L", - TypeSpec.anonymousClassBuilder(typeArgumentsString, *typeClasses.toTypedArray()) - .addSuperinterface(ParameterizedTypeName.get(ClassNames.CACHE_ADAPTER, elementTypeName)) - .apply { - if (primaryColumns.size > 1) { - `override fun`(ArrayTypeName.of(Any::class.java), "getCachingColumnValuesFromModel", - param(ArrayTypeName.of(Any::class.java), "inValues"), - param(elementClassName!!, ModelUtils.variable)) { - modifiers(public, final) - for (i in primaryColumns.indices) { - val column = primaryColumns[i] - addCode(column.getColumnAccessString(i)) - } - - `return`("inValues") - } - - `override fun`(ArrayTypeName.of(Any::class.java), "getCachingColumnValuesFromCursor", - param(ArrayTypeName.of(Any::class.java), "inValues"), - param(ClassNames.FLOW_CURSOR, "cursor")) { - modifiers(public, final) - for (i in primaryColumns.indices) { - val column = primaryColumns[i] - val method = DefinitionUtils.getLoadFromCursorMethodString(column.elementTypeName, column.complexColumnBehavior.wrapperTypeName) - statement("inValues[$i] = ${LoadFromCursorMethod.PARAM_CURSOR}" + - ".$method(${LoadFromCursorMethod.PARAM_CURSOR}.getColumnIndex(${column.columnName.S}))") - } - `return`("inValues") - } - } else { - // single primary key - `override fun`(Any::class, "getCachingColumnValueFromModel", - param(elementClassName!!, ModelUtils.variable)) { - modifiers(public, final) - addCode(primaryColumns[0].getSimpleAccessString()) - } - - `override fun`(Any::class, "getCachingColumnValueFromCursor", param(ClassNames.FLOW_CURSOR, "cursor")) { - modifiers(public, final) - val column = primaryColumns[0] - val method = DefinitionUtils.getLoadFromCursorMethodString(column.elementTypeName, column.complexColumnBehavior.wrapperTypeName) - `return`("${LoadFromCursorMethod.PARAM_CURSOR}.$method(${LoadFromCursorMethod.PARAM_CURSOR}.getColumnIndex(${column.columnName.S}))") - } - `override fun`(Any::class, "getCachingId", param(elementClassName!!, ModelUtils.variable)) { - modifiers(public, final) - `return`("getCachingColumnValueFromModel(${ModelUtils.variable})") - } + TypeSpec.anonymousClassBuilder(typeArgumentsString, *typeClasses.toTypedArray()) + .addSuperinterface(ParameterizedTypeName.get(ClassNames.CACHE_ADAPTER, elementTypeName)) + .apply { + if (primaryColumns.size > 1) { + `override fun`(ArrayTypeName.of(Any::class.java), "getCachingColumnValuesFromModel", + param(ArrayTypeName.of(Any::class.java), "inValues"), + param(elementClassName!!, ModelUtils.variable)) { + modifiers(public, final) + for (i in primaryColumns.indices) { + val column = primaryColumns[i] + addCode(column.getColumnAccessString(i)) + } + + `return`("inValues") + } + + `override fun`(ArrayTypeName.of(Any::class.java), "getCachingColumnValuesFromCursor", + param(ArrayTypeName.of(Any::class.java), "inValues"), + param(ClassNames.FLOW_CURSOR, "cursor")) { + modifiers(public, final) + for (i in primaryColumns.indices) { + val column = primaryColumns[i] + val method = DefinitionUtils.getLoadFromCursorMethodString(column.elementTypeName, column.complexColumnBehavior.wrapperTypeName) + statement("inValues[$i] = ${LoadFromCursorMethod.PARAM_CURSOR}" + + ".$method(${LoadFromCursorMethod.PARAM_CURSOR}.getColumnIndex(${column.columnName.S}))") } + `return`("inValues") + } + } else { + // single primary key + `override fun`(Any::class, "getCachingColumnValueFromModel", + param(elementClassName!!, ModelUtils.variable)) { + modifiers(public, final) + addCode(primaryColumns[0].getSimpleAccessString()) + } - if (foreignKeyDefinitions.isNotEmpty()) { - `override fun`(TypeName.VOID, "reloadRelationships", - param(elementClassName!!, ModelUtils.variable), - param(ClassNames.FLOW_CURSOR, LoadFromCursorMethod.PARAM_CURSOR), - param(ClassNames.DATABASE_WRAPPER, ModelUtils.wrapper)) { - modifiers(public, final) - code { - val noIndex = AtomicInteger(-1) - val nameAllocator = NameAllocator() - foreignKeyDefinitions.forEach { add(it.getLoadFromCursorMethod(false, noIndex, nameAllocator)) } - this - } - } + `override fun`(Any::class, "getCachingColumnValueFromCursor", param(ClassNames.FLOW_CURSOR, "cursor")) { + modifiers(public, final) + val column = primaryColumns[0] + val method = DefinitionUtils.getLoadFromCursorMethodString(column.elementTypeName, column.complexColumnBehavior.wrapperTypeName) + `return`("${LoadFromCursorMethod.PARAM_CURSOR}.$method(${LoadFromCursorMethod.PARAM_CURSOR}.getColumnIndex(${column.columnName.S}))") + } + `override fun`(Any::class, "getCachingId", param(elementClassName!!, ModelUtils.variable)) { + modifiers(public, final) + `return`("getCachingColumnValueFromModel(${ModelUtils.variable})") + } + } + + if (foreignKeyDefinitions.isNotEmpty()) { + `override fun`(TypeName.VOID, "reloadRelationships", + param(elementClassName!!, ModelUtils.variable), + param(ClassNames.FLOW_CURSOR, LoadFromCursorMethod.PARAM_CURSOR), + param(ClassNames.DATABASE_WRAPPER, ModelUtils.wrapper)) { + modifiers(public, final) + code { + val noIndex = AtomicInteger(-1) + val nameAllocator = NameAllocator() + foreignKeyDefinitions.forEach { add(it.getLoadFromCursorMethod(false, noIndex, nameAllocator)) } + this } } - .build()) + } + } + .build()) } } @@ -615,21 +611,21 @@ class TableDefinition(private val table: Table, `override fun`(ClassNames.SINGLE_MODEL_LOADER, "createSingleModelLoader") { modifiers(public, final) addStatement("return new \$T<>(getTable(), cacheAdapter)", - if (singlePrimaryKey) - ClassNames.SINGLE_KEY_CACHEABLE_MODEL_LOADER - else - ClassNames.CACHEABLE_MODEL_LOADER) + if (singlePrimaryKey) + ClassNames.SINGLE_KEY_CACHEABLE_MODEL_LOADER + else + ClassNames.CACHEABLE_MODEL_LOADER) } `override fun`(ClassNames.LIST_MODEL_LOADER, "createListModelLoader") { modifiers(public, final) `return`("new \$T<>(getTable(), cacheAdapter)", - if (singlePrimaryKey) - ClassNames.SINGLE_KEY_CACHEABLE_LIST_MODEL_LOADER - else - ClassNames.CACHEABLE_LIST_MODEL_LOADER) + if (singlePrimaryKey) + ClassNames.SINGLE_KEY_CACHEABLE_LIST_MODEL_LOADER + else + ClassNames.CACHEABLE_LIST_MODEL_LOADER) } `override fun`(ParameterizedTypeName.get(ClassNames.CACHEABLE_LIST_MODEL_SAVER, elementClassName), - "createListModelSaver") { + "createListModelSaver") { modifiers(protected) `return`("new \$T<>(getModelSaver(), cacheAdapter)", ClassNames.CACHEABLE_LIST_MODEL_SAVER) } @@ -639,7 +635,7 @@ class TableDefinition(private val table: Table, } `override fun`(elementClassName!!, "load", param(elementClassName!!, "model"), - param(ClassNames.DATABASE_WRAPPER, wrapper)) { + param(ClassNames.DATABASE_WRAPPER, wrapper)) { modifiers(public, final) statement("\$T loaded = super.load(model, $wrapper)", elementClassName!!) statement("cacheAdapter.storeModelInCache(model)") @@ -650,10 +646,10 @@ class TableDefinition(private val table: Table, } methods.mapNotNull { it.methodSpec } - .forEach { typeBuilder.addMethod(it) } + .forEach { typeBuilder.addMethod(it) } if (generateContentValues) { contentValueMethods.mapNotNull { it.methodSpec } - .forEach { typeBuilder.addMethod(it) } + .forEach { typeBuilder.addMethod(it) } } } } diff --git a/processor/src/main/kotlin/com/dbflow5/processor/definition/behavior/FTSBehaviors.kt b/processor/src/main/kotlin/com/dbflow5/processor/definition/behavior/FTSBehaviors.kt index c253c33ff..15988a58f 100644 --- a/processor/src/main/kotlin/com/dbflow5/processor/definition/behavior/FTSBehaviors.kt +++ b/processor/src/main/kotlin/com/dbflow5/processor/definition/behavior/FTSBehaviors.kt @@ -8,19 +8,15 @@ import com.squareup.javapoet.ClassName import com.squareup.javapoet.CodeBlock import com.squareup.javapoet.TypeName -/** - * Description: - */ -class FTS4Behavior( - val contentTable: TypeName, - private val databaseTypeName: TypeName, - private val elementName: String, - private val manager: ProcessorManager) { +interface FtsBehavior { + + val manager: ProcessorManager + val elementName: String fun validateColumnDefinition(columnDefinition: ColumnDefinition) { if (columnDefinition.type != ColumnDefinition.Type.RowId - && columnDefinition.columnName != "rowid" - && columnDefinition.elementTypeName.isOneOf(Int::class, Long::class)) { + && columnDefinition.columnName != "rowid" + && columnDefinition.elementTypeName.isOneOf(Int::class, Long::class)) { manager.logError("FTS4 Table of type $elementName can only have a single primary key named \"rowid\" of type rowid that is an Int or Long type.") } else if (columnDefinition.elementTypeName != ClassName.get(String::class.java)) { manager.logError("FTS4 Table of type $elementName must only contain String columns") @@ -28,6 +24,20 @@ class FTS4Behavior( } fun addContentTableCode(addComma: Boolean, codeBlock: CodeBlock.Builder) { + + } +} + +/** + * Description: + */ +class FTS4Behavior( + val contentTable: TypeName, + private val databaseTypeName: TypeName, + override val elementName: String, + override val manager: ProcessorManager) : FtsBehavior { + + override fun addContentTableCode(addComma: Boolean, codeBlock: CodeBlock.Builder) { val contentTableDefinition = manager.getTableDefinition(databaseTypeName, contentTable) contentTableDefinition?.let { tableDefinition -> if (addComma) { @@ -39,17 +49,5 @@ class FTS4Behavior( } class FTS3Behavior( - private val elementName: String, - private val manager: ProcessorManager) { - - fun validateColumnDefinition(columnDefinition: ColumnDefinition) { - if (columnDefinition.type != ColumnDefinition.Type.RowId - && columnDefinition.columnName != "rowid" - && columnDefinition.elementTypeName.isOneOf(Int::class, Long::class)) { - manager.logError("FTS4 Table of type $elementName can only have a single primary key named \"rowid\" of type rowid that is an Int or Long type.") - } else if (columnDefinition.elementTypeName != ClassName.get(String::class.java)) { - manager.logError("FTS4 Table of type $elementName must only contain String columns") - } - } - -} \ No newline at end of file + override val elementName: String, + override val manager: ProcessorManager) : FtsBehavior diff --git a/tests/src/androidTest/java/com/dbflow5/models/Fts4ModelTest.kt b/tests/src/androidTest/java/com/dbflow5/models/FtsModelTest.kt similarity index 98% rename from tests/src/androidTest/java/com/dbflow5/models/Fts4ModelTest.kt rename to tests/src/androidTest/java/com/dbflow5/models/FtsModelTest.kt index 56f68db53..79cbdc6cd 100644 --- a/tests/src/androidTest/java/com/dbflow5/models/Fts4ModelTest.kt +++ b/tests/src/androidTest/java/com/dbflow5/models/FtsModelTest.kt @@ -15,7 +15,7 @@ import org.junit.Test /** * Description: */ -class Fts4ModelTest : BaseUnitTest() { +class FtsModelTest : BaseUnitTest() { @Test fun validate_fts4_created() { @@ -80,4 +80,4 @@ class Fts4ModelTest : BaseUnitTest() { " and cool elsewhere, [minimum] [temperature] 17-20oC. Cold...") } } -} \ No newline at end of file +} diff --git a/tests/src/androidTest/java/com/dbflow5/models/SimpleTestModels.kt b/tests/src/androidTest/java/com/dbflow5/models/SimpleTestModels.kt index ea1e38e1f..e3c3c75ae 100644 --- a/tests/src/androidTest/java/com/dbflow5/models/SimpleTestModels.kt +++ b/tests/src/androidTest/java/com/dbflow5/models/SimpleTestModels.kt @@ -6,6 +6,7 @@ import com.dbflow5.annotation.ColumnIgnore import com.dbflow5.annotation.ConflictAction import com.dbflow5.annotation.ForeignKey import com.dbflow5.annotation.ForeignKeyAction +import com.dbflow5.annotation.Fts3 import com.dbflow5.annotation.Fts4 import com.dbflow5.annotation.ManyToMany import com.dbflow5.annotation.PrimaryKey @@ -236,9 +237,9 @@ class Dog : BaseModel() { @Table(database = TestDatabase::class) data class Currency(@PrimaryKey(autoincrement = true) var id: Long = 0, - @Column @Unique var symbol: String? = null, - @Column var shortName: String? = null, - @Column @Unique var name: String = "") // nullability of fields are respected. We will not assign a null value to this field. + @Column @Unique var symbol: String? = null, + @Column var shortName: String? = null, + @Column @Unique var name: String = "") // nullability of fields are respected. We will not assign a null value to this field. inline class Password(val value: String) inline class Email(val value: String) @@ -266,6 +267,9 @@ class UniqueModel(@PrimaryKey var id: String = "", @Unique(uniqueGroups = [1]) var name: String = "", @ForeignKey @Unique(uniqueGroups = [1]) var model: TypeConverterModel? = null) +@Table(database = TestDatabase::class) +@Fts3 +class Fts3Model(var name: String = "") @Table(database = TestDatabase::class) class Fts4Model( @@ -275,4 +279,4 @@ class Fts4Model( @Table(database = TestDatabase::class) @Fts4(contentTable = Fts4Model::class) -class Fts4VirtualModel2(var name: String = "") \ No newline at end of file +class Fts4VirtualModel2(var name: String = "")