@@ -81,3 +81,87 @@ function execute(
81
81
Result (copy_end_result, jl_conn, kwargs... ); throw_error= throw_error
82
82
)
83
83
end
84
+
85
+ """
86
+ CopyOut!(data, query) -> CopyOut!
87
+
88
+ Create a `CopyOut!` query instance which can be executed to receive data from PostgreSQL via a
89
+ `COPY <table_name> TO STDIN` query.
90
+
91
+ `query` must be a `COPY TO STDIN` query as described in the [PostgreSQL documentation](https://www.postgresql.org/docs/10/sql-copy.html).
92
+ `COPY TO` queries which use a file or `PROGRAM` source can instead use the standard
93
+ [`execute`](@ref) query interface.
94
+
95
+ `data` is an IOBuffer where strings of data received from PostgreSQL are written to.
96
+ The data is received as text in CSV format.
97
+ """
98
+ struct CopyOut!
99
+ data:: IOBuffer
100
+ query:: String
101
+ end
102
+
103
+ """
104
+ execute(jl_conn::Connection, copyout::CopyOut!, args...;
105
+ throw_error::Bool=true, kwargs...
106
+ ) -> Result
107
+
108
+ Runs [`execute`](@ref execute(::Connection, ::String)) on `copyout`'s query, then fills
109
+ `copyout`'s data from the server.
110
+
111
+ All other arguments are passed through to the `execute` call for the initial query.
112
+ """
113
+ function execute (
114
+ jl_conn:: Connection ,
115
+ copy:: CopyOut! ,
116
+ parameters= nothing ;
117
+ throw_error= true ,
118
+ kwargs... ,
119
+ )
120
+ level = throw_error ? error : warn
121
+ if parameters != = nothing
122
+ string_params = string_parameters (parameters)
123
+ pointer_params = parameter_pointers (string_params)
124
+ end
125
+
126
+ copy_end_result = lock (jl_conn) do
127
+ if parameters === nothing
128
+ result = _execute (jl_conn. conn, copy. query)
129
+ else
130
+ result = _execute (jl_conn. conn, copy. query, pointer_params)
131
+ end
132
+ result_status = libpq_c. PQresultStatus (result)
133
+
134
+ if result_status != libpq_c. PGRES_COPY_OUT
135
+ if ! (result_status in (libpq_c. PGRES_BAD_RESPONSE, libpq_c. PGRES_FATAL_ERROR))
136
+ level (LOGGER, Errors. JLResultError (
137
+ " Expected PGRES_COPY_OUT after COPY query, got $result_status "
138
+ ))
139
+ end
140
+ return result
141
+ end
142
+
143
+ io = copy. data # store csv string
144
+ async:: Cint = 0 # blocking call
145
+ rowRef = Ref {Cstring} ()
146
+ status_code = Cint (0 )
147
+ while (status_code = libpq_c. PQgetCopyData (jl_conn. conn, rowRef, async)) > 0
148
+ rowPtr = rowRef[]
149
+ write (io, unsafe_string (rowPtr))
150
+ if rowPtr != C_NULL
151
+ libpq_c. PQfreemem (convert (Ptr{Cvoid}, rowPtr))
152
+ end
153
+ end
154
+ seekstart (io) # rewind iobuffer so future user read will begin from start
155
+ if - 2 == status_code
156
+ level (LOGGER, Errors. JLResultError (
157
+ " PQgetCopyData error: $(error_message (jl_conn)) "
158
+ ))
159
+ end
160
+
161
+ libpq_c. PQgetResult (jl_conn. conn)
162
+ end
163
+
164
+ return handle_result (
165
+ Result (copy_end_result, jl_conn, kwargs... ); throw_error= throw_error
166
+ )
167
+ end
0 commit comments