1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package androidx.room.util
17 
18 import androidx.annotation.IntDef
19 import androidx.annotation.RestrictTo
20 import androidx.room.ColumnInfo.SQLiteTypeAffinity
21 import androidx.sqlite.SQLiteConnection
22 import kotlin.jvm.JvmStatic
23 
24 /**
25  * A data class that holds the information about a table.
26  *
27  * It directly maps to the result of `PRAGMA table_info(<table_name>)`. Check the
28  * [PRAGMA table_info](http://www.sqlite.org/pragma.html#pragma_table_info) documentation for more
29  * details.
30  *
31  * Even though SQLite column names are case insensitive, this class uses case sensitive matching.
32  */
33 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) // used in generated code
34 actual class TableInfo
35 actual constructor(
36     /** The table name. */
37     actual val name: String,
38     actual val columns: Map<String, Column>,
39     actual val foreignKeys: Set<ForeignKey>,
40     actual val indices: Set<Index>?
41 ) {
42     /** Identifies from where the info object was created. */
43     @Retention(AnnotationRetention.SOURCE)
44     @IntDef(value = [CREATED_FROM_UNKNOWN, CREATED_FROM_ENTITY, CREATED_FROM_DATABASE])
45     internal annotation class CreatedFrom()
46 
equalsnull47     actual override fun equals(other: Any?) = equalsCommon(other)
48 
49     actual override fun hashCode() = hashCodeCommon()
50 
51     actual override fun toString() = toStringCommon()
52 
53     actual companion object {
54         /** Identifier for when the info is created from an unknown source. */
55         actual const val CREATED_FROM_UNKNOWN = 0
56 
57         /**
58          * Identifier for when the info is created from an entity definition, such as generated code
59          * by the compiler or at runtime from a schema bundle, parsed from a schema JSON file.
60          */
61         actual const val CREATED_FROM_ENTITY = 1
62 
63         /**
64          * Identifier for when the info is created from the database itself, reading information
65          * from a PRAGMA, such as table_info.
66          */
67         actual const val CREATED_FROM_DATABASE = 2
68 
69         /**
70          * Reads the table information from the given database.
71          *
72          * @param connection The database connection to read the information from.
73          * @param tableName The table name.
74          * @return A TableInfo containing the schema information for the provided table name.
75          */
76         @JvmStatic
77         actual fun read(connection: SQLiteConnection, tableName: String): TableInfo {
78             return readTableInfo(connection, tableName)
79         }
80     }
81 
82     /** Holds the information about a database column. */
83     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) // used in generated code
84     actual class Column
85     actual constructor(
86         /** The column name. */
87         actual val name: String,
88         /** The column type affinity. */
89         actual val type: String,
90         /** Whether or not the column can be NULL. */
91         actual val notNull: Boolean,
92         actual val primaryKeyPosition: Int,
93         actual val defaultValue: String?,
94         @CreatedFrom actual val createdFrom: Int
95     ) {
96         /**
97          * The column type after it is normalized to one of the basic types according to
98          * https://www.sqlite.org/datatype3.html Section 3.1.
99          *
100          * This is the value Room uses for equality check.
101          */
102         @SQLiteTypeAffinity actual val affinity: Int = findAffinity(type)
103 
104         /**
105          * Returns whether this column is part of the primary key or not.
106          *
107          * @return True if this column is part of the primary key, false otherwise.
108          */
109         actual val isPrimaryKey: Boolean
110             get() = primaryKeyPosition > 0
111 
equalsnull112         actual override fun equals(other: Any?) = equalsCommon(other)
113 
114         actual override fun hashCode() = hashCodeCommon()
115 
116         actual override fun toString() = toStringCommon()
117     }
118 
119     /** Holds the information about an SQLite foreign key */
120     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) // used in generated code
121     actual class ForeignKey
122     actual constructor(
123         actual val referenceTable: String,
124         actual val onDelete: String,
125         actual val onUpdate: String,
126         actual val columnNames: List<String>,
127         actual val referenceColumnNames: List<String>
128     ) {
129         actual override fun equals(other: Any?) = equalsCommon(other)
130 
131         actual override fun hashCode() = hashCodeCommon()
132 
133         actual override fun toString() = toStringCommon()
134     }
135 
136     /** Holds the information about an SQLite index */
137     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX) // used in generated code
138     actual class Index
139     actual constructor(
140         actual val name: String,
141         actual val unique: Boolean,
142         actual val columns: List<String>,
143         actual var orders: List<String>
144     ) {
145         init {
<lambda>null146             orders = orders.ifEmpty { List(columns.size) { androidx.room.Index.Order.ASC.name } }
147         }
148 
149         actual companion object {
150             // should match the value in Index.kt
151             actual const val DEFAULT_PREFIX = "index_"
152         }
153 
equalsnull154         actual override fun equals(other: Any?) = equalsCommon(other)
155 
156         actual override fun hashCode() = hashCodeCommon()
157 
158         actual override fun toString() = toStringCommon()
159     }
160 }
161