Skip to content

Commit 5fbf014

Browse files
committed
Fix bugs about null values and String elements
1 parent 5bc84a2 commit 5fbf014

File tree

14 files changed

+111
-56
lines changed

14 files changed

+111
-56
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
- Date format: YYYY-MM-dd
44

5+
## v1.3.1 / 2024-04-xx
6+
7+
### sqllin-dsl
8+
9+
* Fix a crash when a data class doesn't contain any `String` element.
10+
* Fix the [issue#81](https://github.com/ctripcorp/SQLlin/issues/81) about insert and query null values
11+
512
## v1.3.0 / 2024-04-21
613

714
### All

sqllin-driver/src/androidMain/kotlin/com/ctrip/sqllin/driver/AndroidCursor.kt

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,33 @@ import android.database.Cursor
2525

2626
internal class AndroidCursor(private val cursor: Cursor) : CommonCursor {
2727

28-
override fun getInt(columnIndex: Int): Int = cursor.getInt(columnIndex)
29-
override fun getLong(columnIndex: Int): Long = cursor.getLong(columnIndex)
30-
override fun getFloat(columnIndex: Int): Float = cursor.getFloat(columnIndex)
31-
override fun getDouble(columnIndex: Int): Double = cursor.getDouble(columnIndex)
28+
override fun getInt(columnIndex: Int): Int? = try {
29+
cursor.getInt(columnIndex)
30+
} catch (e: Exception) {
31+
e.printStackTrace()
32+
null
33+
}
34+
35+
override fun getLong(columnIndex: Int): Long? = try {
36+
cursor.getLong(columnIndex)
37+
} catch (e: Exception) {
38+
e.printStackTrace()
39+
null
40+
}
41+
42+
override fun getFloat(columnIndex: Int): Float? = try {
43+
cursor.getFloat(columnIndex)
44+
} catch (e: Exception) {
45+
e.printStackTrace()
46+
null
47+
}
48+
49+
override fun getDouble(columnIndex: Int): Double? = try {
50+
cursor.getDouble(columnIndex)
51+
} catch (e: Exception) {
52+
e.printStackTrace()
53+
null
54+
}
3255

3356
override fun getString(columnIndex: Int): String? = try {
3457
cursor.getString(columnIndex)

sqllin-driver/src/commonMain/kotlin/com/ctrip/sqllin/driver/CommonCursor.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ package com.ctrip.sqllin.driver
2424
@OptIn(ExperimentalStdlibApi::class)
2525
public interface CommonCursor : AutoCloseable {
2626

27-
public fun getInt(columnIndex: Int): Int
28-
public fun getLong(columnIndex: Int): Long
29-
public fun getFloat(columnIndex: Int): Float
30-
public fun getDouble(columnIndex: Int): Double
27+
public fun getInt(columnIndex: Int): Int?
28+
public fun getLong(columnIndex: Int): Long?
29+
public fun getFloat(columnIndex: Int): Float?
30+
public fun getDouble(columnIndex: Int): Double?
3131
public fun getString(columnIndex: Int): String?
3232
public fun getByteArray(columnIndex: Int): ByteArray?
3333

sqllin-driver/src/commonMain/kotlin/com/ctrip/sqllin/driver/Extension.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ internal fun DatabaseConnection.migrateIfNeeded(
9393
) = withTransaction {
9494
val initialVersion = withQuery("PRAGMA user_version;") {
9595
it.next()
96-
it.getInt(0)
96+
it.getInt(0) ?: 0
9797
}
9898
if (initialVersion == 0) {
9999
create(this)

sqllin-driver/src/jvmMain/kotlin/com/ctrip/sqllin/driver/JdbcCursor.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,17 @@ import java.sql.ResultSet
2424
*/
2525
internal class JdbcCursor(private val resultSet: ResultSet) : CommonCursor {
2626

27-
override fun getInt(columnIndex: Int): Int = resultSet.getInt(columnIndex + 1)
27+
override fun getInt(columnIndex: Int): Int? =
28+
resultSet.getInt(columnIndex + 1).takeUnless { resultSet.wasNull() }
2829

29-
override fun getLong(columnIndex: Int): Long = resultSet.getLong(columnIndex + 1)
30+
override fun getLong(columnIndex: Int): Long? =
31+
resultSet.getLong(columnIndex + 1).takeUnless { resultSet.wasNull() }
3032

31-
override fun getFloat(columnIndex: Int): Float = resultSet.getFloat(columnIndex + 1)
33+
override fun getFloat(columnIndex: Int): Float? =
34+
resultSet.getFloat(columnIndex + 1).takeUnless { resultSet.wasNull() }
3235

33-
override fun getDouble(columnIndex: Int): Double = resultSet.getDouble(columnIndex + 1)
36+
override fun getDouble(columnIndex: Int): Double? =
37+
resultSet.getDouble(columnIndex + 1).takeUnless { resultSet.wasNull() }
3438

3539
override fun getString(columnIndex: Int): String? = resultSet.getString(columnIndex + 1)
3640

sqllin-driver/src/nativeMain/kotlin/com/ctrip/sqllin/driver/ConcurrentStatement.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,19 @@ internal class ConcurrentStatement(
3030
private val accessLock: Lock,
3131
) : SQLiteStatement {
3232

33-
override fun columnGetLong(columnIndex: Int): Long = accessLock.withLock {
33+
override fun columnGetLong(columnIndex: Int): Long? = accessLock.withLock {
3434
delegateStatement.columnGetLong(columnIndex)
3535
}
3636

37-
override fun columnGetDouble(columnIndex: Int): Double = accessLock.withLock {
37+
override fun columnGetDouble(columnIndex: Int): Double? = accessLock.withLock {
3838
delegateStatement.columnGetDouble(columnIndex)
3939
}
4040

41-
override fun columnGetString(columnIndex: Int): String = accessLock.withLock {
41+
override fun columnGetString(columnIndex: Int): String? = accessLock.withLock {
4242
delegateStatement.columnGetString(columnIndex)
4343
}
4444

45-
override fun columnGetBlob(columnIndex: Int): ByteArray = accessLock.withLock {
45+
override fun columnGetBlob(columnIndex: Int): ByteArray? = accessLock.withLock {
4646
delegateStatement.columnGetBlob(columnIndex)
4747
}
4848

sqllin-driver/src/nativeMain/kotlin/com/ctrip/sqllin/driver/NativeCursor.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,17 @@ internal class NativeCursor(
2525
private val statement: SQLiteStatement
2626
) : CommonCursor {
2727

28-
override fun getInt(columnIndex: Int): Int = getLong(columnIndex).toInt()
28+
override fun getInt(columnIndex: Int): Int? = getLong(columnIndex)?.toInt()
2929

30-
override fun getLong(columnIndex: Int): Long = statement.columnGetLong(columnIndex)
30+
override fun getLong(columnIndex: Int): Long? = statement.columnGetLong(columnIndex)
3131

32-
override fun getFloat(columnIndex: Int): Float = getDouble(columnIndex).toFloat()
32+
override fun getFloat(columnIndex: Int): Float? = getDouble(columnIndex)?.toFloat()
3333

34-
override fun getDouble(columnIndex: Int): Double = statement.columnGetDouble(columnIndex)
34+
override fun getDouble(columnIndex: Int): Double? = statement.columnGetDouble(columnIndex)
3535

36-
override fun getString(columnIndex: Int): String = statement.columnGetString(columnIndex)
36+
override fun getString(columnIndex: Int): String? = statement.columnGetString(columnIndex)
3737

38-
override fun getByteArray(columnIndex: Int): ByteArray = statement.columnGetBlob(columnIndex)
38+
override fun getByteArray(columnIndex: Int): ByteArray? = statement.columnGetBlob(columnIndex)
3939

4040
override fun getColumnIndex(columnName: String): Int = columnNames[columnName] ?: throw IllegalArgumentException("Col for $columnName not found")
4141

sqllin-driver/src/nativeMain/kotlin/com/ctrip/sqllin/driver/SQLiteStatement.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ package com.ctrip.sqllin.driver
2323

2424
internal interface SQLiteStatement {
2525

26-
fun columnGetLong(columnIndex: Int): Long
26+
fun columnGetLong(columnIndex: Int): Long?
2727

28-
fun columnGetDouble(columnIndex: Int): Double
28+
fun columnGetDouble(columnIndex: Int): Double?
2929

30-
fun columnGetString(columnIndex: Int): String
30+
fun columnGetString(columnIndex: Int): String?
3131

32-
fun columnGetBlob(columnIndex: Int): ByteArray
32+
fun columnGetBlob(columnIndex: Int): ByteArray?
3333

3434
fun columnCount(): Int
3535

sqllin-driver/src/nativeMain/kotlin/com/ctrip/sqllin/driver/cinterop/NativeStatement.kt

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,28 +66,31 @@ internal class NativeStatement(
6666
) : SQLiteStatement {
6767

6868
// Cursor methods
69-
fun isNull(index: Int): Boolean =
69+
private fun isNull(index: Int): Boolean =
7070
sqlite3_column_type(cStatementPointer, index) == SQLITE_NULL
7171

72-
override fun columnGetLong(columnIndex: Int): Long =
73-
sqlite3_column_int64(cStatementPointer, columnIndex)
72+
override fun columnGetLong(columnIndex: Int): Long? =
73+
if (isNull(columnIndex)) null else sqlite3_column_int64(cStatementPointer, columnIndex)
7474

75-
override fun columnGetDouble(columnIndex: Int): Double =
76-
sqlite3_column_double(cStatementPointer, columnIndex)
75+
override fun columnGetDouble(columnIndex: Int): Double? =
76+
if (isNull(columnIndex)) null else sqlite3_column_double(cStatementPointer, columnIndex)
7777

78-
override fun columnGetString(columnIndex: Int): String =
79-
sqlite3_column_text(cStatementPointer, columnIndex)
80-
?.reinterpret<ByteVar>()
81-
?.let { bytesToString(it) }
82-
?: ""
78+
override fun columnGetString(columnIndex: Int): String? =
79+
if (isNull(columnIndex))
80+
null
81+
else
82+
sqlite3_column_text(cStatementPointer, columnIndex)
83+
?.reinterpret<ByteVar>()
84+
?.let { bytesToString(it) }
8385

84-
override fun columnGetBlob(columnIndex: Int): ByteArray {
86+
override fun columnGetBlob(columnIndex: Int): ByteArray? {
87+
if (isNull(columnIndex))
88+
return null
8589
val blobSize = sqlite3_column_bytes(cStatementPointer, columnIndex)
8690
return if (blobSize == 0)
87-
byteArrayOf()
91+
null
8892
else
8993
sqlite3_column_blob(cStatementPointer, columnIndex)?.readBytes(blobSize)
90-
?: throw sqliteException("Byte array size/type issue col $columnIndex")
9194
}
9295

9396
override fun columnCount(): Int = sqlite3_column_count(cStatementPointer)

sqllin-dsl/src/commonMain/kotlin/com/ctrip/sqllin/dsl/sql/compiler/AbstractValuesEncoder.kt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.ctrip.sqllin.dsl.sql.compiler
1818

1919
import kotlinx.serialization.ExperimentalSerializationApi
20+
import kotlinx.serialization.SerializationStrategy
2021
import kotlinx.serialization.descriptors.SerialDescriptor
2122
import kotlinx.serialization.encoding.AbstractEncoder
2223
import kotlinx.serialization.modules.EmptySerializersModule
@@ -44,8 +45,7 @@ internal abstract class AbstractValuesEncoder : AbstractEncoder() {
4445
get() = sqlStrBuilder.toString()
4546

4647
override fun encodeElement(descriptor: SerialDescriptor, index: Int): Boolean {
47-
if (index == 0)
48-
elementsCount = descriptor.elementsCount
48+
elementsCount = descriptor.elementsCount
4949
elementsIndex = index
5050
return true
5151
}
@@ -83,5 +83,19 @@ internal abstract class AbstractValuesEncoder : AbstractEncoder() {
8383
sqlStrBuilder.append(value).appendTail()
8484
}
8585

86+
override fun <T : Any> encodeNullableSerializableElement(
87+
descriptor: SerialDescriptor,
88+
index: Int,
89+
serializer: SerializationStrategy<T>,
90+
value: T?
91+
) {
92+
if (value == null) {
93+
elementsCount = descriptor.elementsCount
94+
elementsIndex = index
95+
sqlStrBuilder.append("NULL").appendTail()
96+
} else
97+
super.encodeNullableSerializableElement(descriptor, index, serializer, value)
98+
}
99+
86100
override fun encodeEnum(enumDescriptor: SerialDescriptor, index: Int) = encodeInt(index)
87101
}

0 commit comments

Comments
 (0)