Skip to content

Commit a2eaeef

Browse files
authored
Implement Copy Support (#18)
Co-authored-by: hfhbd <[email protected]>
1 parent 552d145 commit a2eaeef

File tree

5 files changed

+70
-7
lines changed

5 files changed

+70
-7
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ kotlin {
4848
commonTest {
4949
dependencies {
5050
implementation(kotlin("test"))
51+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.2")
5152
}
5253
}
5354
}

src/commonMain/kotlin/app/softwork/sqldelight/postgresdriver/PostgresNativeDriver.kt

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,14 @@ class PostgresNativeDriver(private var conn: CPointer<PGconn>) : SqlDriver {
8383
)
8484
}
8585
}.check(conn)
86-
val rows = PQcmdTuples(result)!!.toKString()
87-
result.clear()
88-
val resultRows = rows.toLongOrNull() ?: 0
89-
return QueryResult.Value(value = resultRows)
86+
87+
return QueryResult.Value(value = result.rows)
88+
}
89+
90+
private val CPointer<PGresult>.rows: Long get() {
91+
val rows = PQcmdTuples(this)!!.toKString()
92+
clear()
93+
return rows.toLongOrNull() ?: 0
9094
}
9195

9296
private fun preparedStatementExists(identifier: Int): Boolean {
@@ -194,6 +198,19 @@ class PostgresNativeDriver(private var conn: CPointer<PGconn>) : SqlDriver {
194198
transaction = enclosingTransaction
195199
}
196200
}
201+
202+
fun copy(stdin: String): Long {
203+
val status = PQputCopyData(conn, stdin, stdin.encodeToByteArray().size)
204+
check(status == 1) {
205+
conn.error()
206+
}
207+
val end = PQputCopyEnd(conn, null)
208+
check(end == 1) {
209+
conn.error()
210+
}
211+
val result = PQgetResult(conn).check(conn)
212+
return result.rows
213+
}
197214
}
198215

199216
private fun CPointer<PGconn>?.error(): String {
@@ -214,7 +231,7 @@ private fun CPointer<PGconn>.exec(sql: String) {
214231

215232
private fun CPointer<PGresult>?.check(conn: CPointer<PGconn>): CPointer<PGresult> {
216233
val status = PQresultStatus(this)
217-
check(status == PGRES_TUPLES_OK || status == PGRES_COMMAND_OK) {
234+
check(status == PGRES_TUPLES_OK || status == PGRES_COMMAND_OK || status == PGRES_COPY_IN) {
218235
conn.error()
219236
}
220237
return this!!

src/commonTest/kotlin/app/softwork/sqldelight/postgresdriver/PostgresNativeDriverTest.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,20 @@ class PostgresNativeDriverTest {
119119
)
120120
}
121121
}
122+
123+
@Test
124+
fun copyTest() {
125+
val driver = PostgresNativeDriver(
126+
host = "localhost",
127+
port = 5432,
128+
user = "postgres",
129+
database = "postgres",
130+
password = "password"
131+
)
132+
assertEquals(0, driver.execute(null, "DROP TABLE IF EXISTS copying;", parameters = 0).value)
133+
assertEquals(0, driver.execute(null, "CREATE TABLE copying(a int primary key);", parameters = 0).value)
134+
driver.execute(42, "COPY copying FROM STDIN (FORMAT CSV);", 0)
135+
val results = driver.copy("1\n2\n")
136+
assertEquals(2, results)
137+
}
122138
}

testing/src/commonMain/sqldelight/app/softwork/sqldelight/postgresdriver/Foo.sq

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@ INSERT INTO foo VALUES ?;
33

44
get:
55
SELECT * FROM foo;
6+
7+
copy:
8+
COPY foo FROM STDIN (FORMAT CSV);

testing/src/commonTest/kotlin/app/softwork/sqldelight/postgresdriver/PostgresNativeDriverTest.kt

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,36 @@ class PostgresNativeDriverTest {
2525
date = LocalDate(2020, Month.DECEMBER, 12),
2626
timestamp = LocalDateTime(2014, Month.AUGUST, 1, 12, 1, 2, 0),
2727
instant = Instant.fromEpochMilliseconds(10L),
28-
uuid = UUID.NIL,
29-
interval = 42.seconds
28+
interval = 42.seconds,
29+
uuid = UUID.NIL
3030
)
3131
queries.create(foo)
3232
assertEquals(foo, queries.get().executeAsOne())
3333
}
34+
35+
@Test
36+
fun copyTest() {
37+
val driver = PostgresNativeDriver(
38+
host = "localhost",
39+
port = 5432,
40+
user = "postgres",
41+
database = "postgres",
42+
password = "password"
43+
)
44+
val queries = NativePostgres(driver).fooQueries
45+
NativePostgres.Schema.migrate(driver, 0, NativePostgres.Schema.version)
46+
queries.copy()
47+
val result = driver.copy("42,answer,2020-12-12,2014-08-01T12:01:02.0000,1970-01-01T00:00:00.010Z,PT42S,00000000-0000-0000-0000-000000000000")
48+
assertEquals(1, result)
49+
val foo = Foo(
50+
a = 42,
51+
b = "answer",
52+
date = LocalDate(2020, Month.DECEMBER, 12),
53+
timestamp = LocalDateTime(2014, Month.AUGUST, 1, 12, 1, 2, 0),
54+
instant = Instant.fromEpochMilliseconds(10L),
55+
interval = 42.seconds,
56+
uuid = UUID.NIL,
57+
)
58+
assertEquals(foo, queries.get().executeAsOne())
59+
}
3460
}

0 commit comments

Comments
 (0)