1
/* ``The contents of this file are subject to the Erlang Public License,
2
* Version 1.1, (the "License"); you may not use this file except in
3
* compliance with the License. You should have received a copy of the
4
* Erlang Public License along with this software. If not, it can be
5
* retrieved via the world wide web at http://www.erlang.org/.
7
* Software distributed under the License is distributed on an "AS IS"
8
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
* the License for the specific language governing rights and limitations
12
* The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
* Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
* AB. All Rights Reserved.''
20
* Purpose: A driver using libpq to connect to Postgres
21
* from erlang, a sample for the driver documentation
24
#include <erl_driver.h>
34
#include "pg_encode2.h"
36
#define L fprintf(stderr, "%d\r\n", __LINE__)
38
/* Driver interface declarations */
39
static ErlDrvData start(ErlDrvPort port, char *command);
40
static void stop(ErlDrvData drv_data);
41
static int control(ErlDrvData drv_data, unsigned int command, char *buf,
42
int len, char **rbuf, int rlen);
43
static void ready_input(ErlDrvData drv_data, ErlDrvEvent event);
45
static ErlDrvEntry pq_driver_entry = {
50
ready_input, /* ready_input */
51
NULL, /* ready_output */
64
typedef struct our_data_t {
73
/* Keep the following definitions in alignment with the FUNC_LIST
78
#define DRV_DISCONNECT 2
81
/* INITIALIZATION AFTER LOADING */
84
* This is the init function called after this driver has been loaded.
85
* It must *not* be declared static. Must return the address to
90
extern "C" { /* this should be in the DRIVER_INIT macro! */
94
return &pq_driver_entry;
100
/* DRIVER INTERFACE */
101
static ErlDrvData start(ErlDrvPort port, char *command)
103
our_data_t* data = driver_alloc(sizeof(our_data_t));
106
return (ErlDrvData)data;
110
static char* get_s(const char* buf, int len);
111
static void free_s(char* s);
113
static int do_connect(const char *s, our_data_t* data);
114
static int do_disconnect(our_data_t* data);
115
static int do_select(const char* s, our_data_t* data);
117
static void stop(ErlDrvData drv_data)
119
do_disconnect((our_data_t*)drv_data);
123
/* Since we are operating in binary mode, the return value from control
124
* is irrelevant, as long as it is not negative.
126
static int control(ErlDrvData drv_data, unsigned int command, char *buf,
127
int len, char **rbuf, int rlen)
135
r = do_connect(s, (our_data_t*)drv_data);
138
r = do_disconnect((our_data_t*)drv_data);
141
r = do_select(s, (our_data_t*)drv_data);
151
static int do_connect(const char *s, our_data_t* data)
154
PGconn* conn = PQconnectdb(s);
156
ei_x_new_with_version(&x);
157
if (PQstatus(conn) != CONNECTION_OK) {
158
encode_error(&x, conn);
163
data->socket = PQsocket(conn);
164
driver_select(data->port, (ErlDrvEvent)data->socket, DO_READ, 1);
166
driver_output(data->port, x.buff, x.index);
172
static int do_disconnect(our_data_t* data)
176
if (data->socket == 0)
178
driver_select(data->port, (ErlDrvEvent)data->socket, DO_READ, 0);
180
PQfinish(data->conn);
182
ei_x_new_with_version(&x);
184
driver_output(data->port, x.buff, x.index);
189
static int do_select(const char* s, our_data_t* data)
191
PGconn* conn = data->conn;
193
/* if there's an error return it now */
194
if (PQsendQueryParams(conn, s, 0, NULL, NULL, NULL, NULL, 1) == 0) {
196
ei_x_new_with_version(&x);
197
encode_error(&x, conn);
198
driver_output(data->port, x.buff, x.index);
201
/* else wait for ready_output to get results */
205
static void ready_input(ErlDrvData drv_data, ErlDrvEvent event)
207
our_data_t* data = (our_data_t*)drv_data;
208
PGconn* conn = data->conn;
212
PQconsumeInput(conn);
215
ei_x_new_with_version(&x);
216
res = PQgetResult(conn);
217
encode_result(&x, res, conn);
218
driver_output(data->port, x.buff, x.index);
222
res = PQgetResult(conn);
231
static char* get_s(const char* buf, int len)
234
if (len < 1 || len > 1000) return NULL;
235
result = driver_alloc(len+1);
236
memcpy(result, buf, len);
241
static void free_s(char* s)