16
16
17
17
package com.ctrip.sqllin.driver
18
18
19
+ import com.ctrip.sqllin.driver.platform.separatorChar
20
+ import kotlin.jvm.JvmInline
21
+
19
22
/* *
20
23
* SQLite extension function
21
24
* @author yaqiao
@@ -62,4 +65,108 @@ public inline fun <T> DatabaseConnection.withQuery(
62
65
}
63
66
}
64
67
65
- public expect fun deleteDatabase (path : DatabasePath , name : String ): Boolean
68
+ public expect fun deleteDatabase (path : DatabasePath , name : String ): Boolean
69
+
70
+ internal infix fun DatabaseConnection.updateSynchronousMode (mode : SynchronousMode ) {
71
+ val currentJournalMode = withQuery(" PRAGMA synchronous;" ) {
72
+ it.next()
73
+ it.getInt(0 )
74
+ }
75
+ if (currentJournalMode != mode.value)
76
+ execSQL(" PRAGMA synchronous=${mode.value} ;" )
77
+ }
78
+
79
+ internal infix fun DatabaseConnection.updateJournalMode (mode : JournalMode ) {
80
+ val currentJournalMode = withQuery(" PRAGMA journal_mode;" ) {
81
+ it.next()
82
+ it.getString(0 )
83
+ }
84
+ if (! currentJournalMode.equals(mode.name, ignoreCase = true ))
85
+ withQuery(" PRAGMA journal_mode=${mode.name} ;" ) {}
86
+ }
87
+
88
+ internal fun DatabaseConnection.migrateIfNeeded (
89
+ create : (DatabaseConnection ) -> Unit ,
90
+ upgrade : (DatabaseConnection , Int , Int ) -> Unit ,
91
+ version : Int ,
92
+ ) = withTransaction {
93
+ val initialVersion = withQuery(" PRAGMA user_version;" ) {
94
+ it.next()
95
+ it.getInt(0 )
96
+ }
97
+ if (initialVersion == 0 ) {
98
+ create(this )
99
+ execSQL(" PRAGMA user_version = $version ;" )
100
+ } else if (initialVersion != version) {
101
+ if (initialVersion > version) {
102
+ throw IllegalStateException (" Database version $initialVersion newer than config version $version " )
103
+ }
104
+ upgrade(this , initialVersion, version)
105
+ execSQL(" PRAGMA user_version = $version ;" )
106
+ }
107
+ }
108
+
109
+ internal fun DatabaseConfiguration.diskOrMemoryPath (): String =
110
+ if (inMemory) {
111
+ if (name.isBlank())
112
+ " :memory:"
113
+ else
114
+ " file:$name ?mode=memory&cache=shared"
115
+ } else {
116
+ require(name.isNotBlank()) { " Database name cannot be blank" }
117
+ getDatabaseFullPath((path as StringDatabasePath ).pathString, name)
118
+ }
119
+
120
+ internal fun getDatabaseFullPath (dirPath : String , name : String ): String {
121
+ val param = when {
122
+ dirPath.isEmpty() -> name
123
+ name.isEmpty() -> dirPath
124
+ else -> join(dirPath, name)
125
+ }
126
+ return fixSlashes(param)
127
+ }
128
+
129
+ private fun join (prefix : String , suffix : String ): String {
130
+ val haveSlash = (prefix.isNotEmpty() && prefix.last() == separatorChar)
131
+ || (suffix.isNotEmpty() && suffix.first() == separatorChar)
132
+ return buildString {
133
+ append(prefix)
134
+ if (! haveSlash)
135
+ append(separatorChar)
136
+ append(suffix)
137
+ }
138
+ }
139
+
140
+ private fun fixSlashes (origPath : String ): String {
141
+ // Remove duplicate adjacent slashes.
142
+ var lastWasSlash = false
143
+ val newPath = origPath.toCharArray()
144
+ val length = newPath.size
145
+ var newLength = 0
146
+ val initialIndex = if (origPath.startsWith(" file://" , true )) 7 else 0
147
+ for (i in initialIndex .. < length) {
148
+ val ch = newPath[i]
149
+ if (ch == separatorChar) {
150
+ if (! lastWasSlash) {
151
+ newPath[newLength++ ] = separatorChar
152
+ lastWasSlash = true
153
+ }
154
+ } else {
155
+ newPath[newLength++ ] = ch
156
+ lastWasSlash = false
157
+ }
158
+ }
159
+ // Remove any trailing slash (unless this is the root of the file system).
160
+ if (lastWasSlash && newLength > 1 ) {
161
+ newLength--
162
+ }
163
+
164
+ // Reuse the original string if possible.
165
+ return if (newLength != length) buildString(newLength) {
166
+ append(newPath)
167
+ setLength(newLength)
168
+ } else origPath
169
+ }
170
+
171
+ @JvmInline
172
+ internal value class StringDatabasePath (val pathString : String ) : DatabasePath
0 commit comments