prestogres 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ChangeLog +16 -0
- data/README.md +30 -2
- data/VERSION +1 -1
- data/bin/prestogres +15 -7
- data/pgpool2/child.c +54 -0
- data/pgpool2/pool.h +2 -0
- data/pgpool2/pool_hba.c +18 -10
- data/pgpool2/pool_process_query.c +46 -19
- data/pgpool2/pool_proto_modules.c +3 -10
- data/pgpool2/pool_query_context.c +222 -112
- data/pgsql/presto_client.py +16 -16
- data/pgsql/prestogres.py +282 -148
- data/pgsql/setup.sql +28 -0
- metadata +16 -25
- data/pgsql/setup_functions.sql +0 -21
- data/pgsql/setup_language.sql +0 -3
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fdbbafba90e2dde6d7340746b30d369eda073ed9
|
4
|
+
data.tar.gz: 57d91cbb2bb74c2ce53132ea9309eb9a0cb47e09
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f166e0435a473ec6930522f0a139733f24227a8b0045725fc1e89f4afda25c6fd589c2dc121a46e99c82f79bba135c601b42fec45651c66c185a0aaae6f52eb6
|
7
|
+
data.tar.gz: c351d1a8fe7c59cc7b9a2ec603935766141958df839d4f7179a9921e9410b2da513f6b05beab2f6b5d3d96be309542df876b01fce42f4021f0692d40ceb84652
|
data/ChangeLog
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
2014-01-24 version 0.2.0:
|
3
|
+
|
4
|
+
* Authentication mechanisms support pg_database and pg_user options to
|
5
|
+
overwrite connecting PostgreSQL database and role name
|
6
|
+
* Forward error message from PostgreSQL to clients instead of killing the
|
7
|
+
session so that clients can know the reason
|
8
|
+
* Reject 'P' (Parse) command to reject extended query protocol immediately
|
9
|
+
* Enabled timeout in Presto HTTP client
|
10
|
+
* Queries to system catalogs delete created tables by rollbacking
|
11
|
+
subtransaction so that other sessions does not conflict
|
12
|
+
|
13
|
+
2014-01-15 version 0.1.0:
|
14
|
+
|
15
|
+
* First release
|
16
|
+
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ With Prestogres, you can use PostgreSQL clients to run queries on Presto:
|
|
12
12
|
* [PostgreSQL JDBC driver](http://jdbc.postgresql.org/)
|
13
13
|
* other PostgreSQL client libraries
|
14
14
|
|
15
|
-
Prestogres also offers password-based
|
15
|
+
Prestogres also offers password-based authentication and SSL.
|
16
16
|
|
17
17
|
## How it works?
|
18
18
|
|
@@ -130,6 +130,8 @@ host altdb pg 0.0.0.0/0 prestogres_md5 s
|
|
130
130
|
host all all 0.0.0.0/0 prestogres_external auth_prog:/opt/prestogres/auth.py
|
131
131
|
```
|
132
132
|
|
133
|
+
See also *Creating database* section.
|
134
|
+
|
133
135
|
#### prestogres_md5 method
|
134
136
|
|
135
137
|
This authentication method uses a password file **\<data_dir\>/pgpool2/pool_passwd** to authenticate an user. You can use `prestogres passwd` command to add an user to this file:
|
@@ -145,6 +147,8 @@ In pool_hba.conf file, you can set following options to OPTIONS field:
|
|
145
147
|
* **catalog**: Catalog (connector) name of Presto, which overwrites `presto_catalog` parameter in pgpool.conf.
|
146
148
|
* **schema**: Schema name of Presto, which overwrites `presto_schema` parameter in pgpool.conf.
|
147
149
|
* **user**: User name to run queries on Presto. By default, Prestogres uses the same user name used to login to pgpool-II.
|
150
|
+
* **pg_database**: Overwrite database to connect to PostgreSQL.
|
151
|
+
* **pg_user**: Overwrite user name to connect to PostgreSQL.
|
148
152
|
|
149
153
|
|
150
154
|
#### prestogres_external method
|
@@ -164,18 +168,41 @@ address:IPADDR
|
|
164
168
|
|
165
169
|
```
|
166
170
|
|
167
|
-
If you want to allow this connection, the program optionally prints following
|
171
|
+
If you want to allow this connection, the program optionally prints parameters as following to STDOUT, and exists with status code 0:
|
168
172
|
|
169
173
|
```
|
170
174
|
server:PRESTO_SERVER_ADDRESS
|
171
175
|
catalog:PRESTO_CATALOG_NAME
|
172
176
|
schema:PRESTO_SCHEMA_NAME
|
177
|
+
user:USER_NAME
|
178
|
+
pg_database:DATABASE
|
179
|
+
pg_user:USER_NAME
|
173
180
|
|
174
181
|
```
|
175
182
|
|
183
|
+
See *pgool.conf file* section for available parameters.
|
184
|
+
|
176
185
|
If you want to reject this connection, the program exists with non-0 status code.
|
177
186
|
|
178
187
|
|
188
|
+
### Creating database on PostgreSQL
|
189
|
+
|
190
|
+
Prestogres setups a database named *postgres* on PostgreSQL by default. But you may want to create other databases
|
191
|
+
to take advantage of above authentication mechanism.
|
192
|
+
|
193
|
+
To create new databases:
|
194
|
+
|
195
|
+
1. Create a new PostgreSQL database using `createdb` command. Port number is **6432** because you login to PostgreSQL directly:
|
196
|
+
```
|
197
|
+
$ createdb -h localhost -p 6432 -U pg newdb
|
198
|
+
```
|
199
|
+
|
200
|
+
2. Initialize the database using statements shown by `prestogres show_init_sql` command:
|
201
|
+
```
|
202
|
+
$ prestogres show_init_sql | psql -h localhost -p 6432 -U pg newdb
|
203
|
+
```
|
204
|
+
|
205
|
+
|
179
206
|
### prestogres command
|
180
207
|
|
181
208
|
Usage of `prestogres` command:
|
@@ -191,6 +218,7 @@ commands:
|
|
191
218
|
pg_ctl stop stop postgres server daemon process
|
192
219
|
postgres start postgres server as a foreground process
|
193
220
|
passwd <USER NAME> add new md5 password entry for an user
|
221
|
+
show_init_sql display statements to initialize a new PostgreSQL database
|
194
222
|
```
|
195
223
|
|
196
224
|
## Development
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/bin/prestogres
CHANGED
@@ -17,6 +17,7 @@ def usage(error=nil)
|
|
17
17
|
puts " pg_ctl stop stop postgres server daemon process"
|
18
18
|
puts " postgres start postgres server as a foreground process"
|
19
19
|
puts " passwd <USER NAME> add new md5 password entry for an user"
|
20
|
+
puts " show_init_sql display statements to initialize a new PostgreSQL database"
|
20
21
|
puts ""
|
21
22
|
puts "error: #{error}" if error
|
22
23
|
exit 0
|
@@ -53,6 +54,9 @@ ARGV.each_with_index do |a,i|
|
|
53
54
|
when "passwd"
|
54
55
|
config[:command] = :passwd
|
55
56
|
break
|
57
|
+
when "show_init_sql"
|
58
|
+
config[:command] = :show_init_sql
|
59
|
+
break
|
56
60
|
end
|
57
61
|
end
|
58
62
|
|
@@ -97,13 +101,14 @@ when :setup
|
|
97
101
|
puts "** setup failed **"
|
98
102
|
puts "******************"
|
99
103
|
puts ""
|
100
|
-
puts "-D directory is inconsistent."
|
101
|
-
puts "
|
104
|
+
puts " * -D directory is inconsistent."
|
105
|
+
puts ""
|
106
|
+
puts " * If you're running command on Mac OS X, you might need to run following commands:"
|
102
107
|
puts ""
|
103
|
-
puts "
|
104
|
-
puts "
|
108
|
+
puts " $ sudo sysctl -w kern.sysv.shmmax=1073741824"
|
109
|
+
puts " $ sudo sysctl -w kern.sysv.shmall=1073741824"
|
105
110
|
puts ""
|
106
|
-
puts "Please delete the directory (rm -rf) first before retrying."
|
111
|
+
puts " * Please delete the directory (rm -rf) first before retrying."
|
107
112
|
puts ""
|
108
113
|
exit 1
|
109
114
|
end
|
@@ -143,8 +148,7 @@ when :setup
|
|
143
148
|
begin
|
144
149
|
sleep 1
|
145
150
|
|
146
|
-
run_setup_command "psql -h 127.0.0.1 -p #{setup_params[:backend_port]} -U pg postgres < #{File.join(pgsql_dir, "
|
147
|
-
run_setup_command "psql -h 127.0.0.1 -p #{setup_params[:backend_port]} -U pg postgres < #{File.join(pgsql_dir, "setup_functions.sql")}"
|
151
|
+
run_setup_command "psql -h 127.0.0.1 -p #{setup_params[:backend_port]} -U pg postgres < #{File.join(pgsql_dir, "setup.sql")}"
|
148
152
|
ensure
|
149
153
|
run_setup_command %w[pg_ctl -D] + [File.join(data_dir, 'postgres')] + %w[stop]
|
150
154
|
end
|
@@ -210,6 +214,10 @@ when :passwd
|
|
210
214
|
exit $?.exitstatus
|
211
215
|
end
|
212
216
|
|
217
|
+
when :show_init_sql
|
218
|
+
pgsql_dir = File.join(File.dirname(__FILE__), "..", "pgsql")
|
219
|
+
STDOUT.write File.read(File.join(pgsql_dir, "setup.sql"))
|
220
|
+
|
213
221
|
else
|
214
222
|
unless config[:data_dir]
|
215
223
|
usage "-D option is required"
|
data/pgpool2/child.c
CHANGED
@@ -95,6 +95,46 @@ volatile sig_atomic_t got_sighup = 0;
|
|
95
95
|
char remote_host[NI_MAXHOST]; /* client host */
|
96
96
|
char remote_port[NI_MAXSERV]; /* client port */
|
97
97
|
|
98
|
+
static void rebuild_startup_packet(StartupPacket *sp)
|
99
|
+
{
|
100
|
+
if (sp->major == PROTO_MAJOR_V2) {
|
101
|
+
StartupPacket_v2 *sp2 = (StartupPacket_v2 *)(sp->startup_packet);
|
102
|
+
strncpy(sp2->database, sp2->database, SM_DATABASE);
|
103
|
+
strncpy(sp2->user, sp->user, SM_USER);
|
104
|
+
|
105
|
+
} else if (sp->major == PROTO_MAJOR_V3) {
|
106
|
+
int append_size;
|
107
|
+
char *data, *p;
|
108
|
+
|
109
|
+
append_size = strlen("database") + strlen("user") + strlen(sp->database) + strlen(sp->user) + 4;
|
110
|
+
|
111
|
+
data = malloc(sp->len + append_size);
|
112
|
+
if (data == NULL) {
|
113
|
+
pool_error("rebuild_startup_packet: out of memory");
|
114
|
+
exit(1);
|
115
|
+
}
|
116
|
+
memcpy(data, sp->startup_packet, sp->len);
|
117
|
+
p = data + sp->len - 1; /* remove last terminator byte */
|
118
|
+
|
119
|
+
strcpy(p, "database");
|
120
|
+
p += (strlen("database") + 1);
|
121
|
+
strcpy(p, sp->database);
|
122
|
+
p += (strlen(sp->database) + 1);
|
123
|
+
|
124
|
+
strcpy(p, "user");
|
125
|
+
p += (strlen("user") + 1);
|
126
|
+
strcpy(p, sp->user);
|
127
|
+
p += (strlen(sp->user) + 1);
|
128
|
+
|
129
|
+
*p = '\0'; /* add terminator byte */
|
130
|
+
|
131
|
+
free(sp->startup_packet);
|
132
|
+
sp->startup_packet = data;
|
133
|
+
|
134
|
+
sp->len = sp->len + append_size;
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
98
138
|
/*
|
99
139
|
* child main loop
|
100
140
|
*/
|
@@ -276,6 +316,20 @@ void do_child(int unix_fd, int inet_fd)
|
|
276
316
|
child_exit(1);
|
277
317
|
}
|
278
318
|
ClientAuthentication(frontend);
|
319
|
+
|
320
|
+
/* ClientAuthentication can overwrite database and user */
|
321
|
+
if (strcmp(sp->database, frontend->database) || strcmp(sp->user, frontend->username)) {
|
322
|
+
free(sp->database);
|
323
|
+
sp->database = strdup(frontend->database);
|
324
|
+
free(sp->user);
|
325
|
+
sp->user = strdup(frontend->username);
|
326
|
+
if (frontend->username == NULL)
|
327
|
+
{
|
328
|
+
pool_error("do_child: strdup failed: %s\n", strerror(errno));
|
329
|
+
child_exit(1);
|
330
|
+
}
|
331
|
+
rebuild_startup_packet(sp);
|
332
|
+
}
|
279
333
|
}
|
280
334
|
|
281
335
|
/* this should run after ClientAuthentication */
|
data/pgpool2/pool.h
CHANGED
@@ -605,9 +605,11 @@ extern void reset_connection(void);
|
|
605
605
|
extern void per_node_statement_log(POOL_CONNECTION_POOL *backend, int node_id, char *query);
|
606
606
|
extern void per_node_error_log(POOL_CONNECTION_POOL *backend, int node_id, char *query, char *prefix, bool unread);
|
607
607
|
extern int pool_extract_error_message(bool read_kind, POOL_CONNECTION *backend, int major, bool unread, char **message);
|
608
|
+
extern int pool_extract_error_message_with_errcode(bool read_kind, POOL_CONNECTION *backend, int major, bool unread, char **message, char **errcode);
|
608
609
|
extern POOL_STATUS do_command(POOL_CONNECTION *frontend, POOL_CONNECTION *backend,
|
609
610
|
char *query, int protoMajor, int pid, int key, int no_ready_for_query);
|
610
611
|
extern POOL_STATUS do_query(POOL_CONNECTION *backend, char *query, POOL_SELECT_RESULT **result, int major);
|
612
|
+
extern POOL_STATUS do_query_or_get_error_message(POOL_CONNECTION *backend, char *query, POOL_SELECT_RESULT **result, int major, char **error_message, char **errcode);
|
611
613
|
extern void free_select_result(POOL_SELECT_RESULT *result);
|
612
614
|
extern int compare(const void *p1, const void *p2);
|
613
615
|
extern POOL_STATUS do_error_execute_command(POOL_CONNECTION_POOL *backend, int node_id, int major);
|
data/pgpool2/pool_hba.c
CHANGED
@@ -75,8 +75,8 @@ const char* presto_catalog = NULL;
|
|
75
75
|
const char* presto_schema = NULL;
|
76
76
|
const char* presto_external_auth_prog = NULL;
|
77
77
|
|
78
|
-
static bool prestogres_hba_set_session_info(const char* key, const char* value);
|
79
|
-
static void prestogres_hba_parse_arg(const char* arg);
|
78
|
+
static bool prestogres_hba_set_session_info(POOL_CONNECTION *frontend, const char* key, const char* value);
|
79
|
+
static void prestogres_hba_parse_arg(POOL_CONNECTION *frontend, const char* arg);
|
80
80
|
static POOL_STATUS pool_prestogres_hba_auth_md5(POOL_CONNECTION *frontend);
|
81
81
|
static POOL_STATUS pool_prestogres_hba_auth_external(POOL_CONNECTION *frontend);
|
82
82
|
|
@@ -1497,9 +1497,9 @@ static POOL_STATUS CheckMd5Auth(char *username)
|
|
1497
1497
|
return POOL_CONTINUE;
|
1498
1498
|
}
|
1499
1499
|
|
1500
|
-
static bool prestogres_hba_set_session_info(const char* key, const char* value)
|
1500
|
+
static bool prestogres_hba_set_session_info(POOL_CONNECTION *frontend, const char* key, const char* value)
|
1501
1501
|
{
|
1502
|
-
pool_debug("presto_external_auth_prog: key
|
1502
|
+
pool_debug("presto_external_auth_prog: key '%s' value '%s'", key, value);
|
1503
1503
|
|
1504
1504
|
if (strcmp(key, "server") == 0) {
|
1505
1505
|
presto_server = value;
|
@@ -1513,6 +1513,14 @@ static bool prestogres_hba_set_session_info(const char* key, const char* value)
|
|
1513
1513
|
} else if (strcmp(key, "schema") == 0) {
|
1514
1514
|
presto_schema = value;
|
1515
1515
|
return true;
|
1516
|
+
} else if (strcmp(key, "pg_user") == 0) {
|
1517
|
+
free(frontend->username);
|
1518
|
+
frontend->username = strdup(value);
|
1519
|
+
return true;
|
1520
|
+
} else if (strcmp(key, "pg_database") == 0) {
|
1521
|
+
free(frontend->database);
|
1522
|
+
frontend->database = strdup(value);
|
1523
|
+
return true;
|
1516
1524
|
} else if (strcmp(key, "auth_prog") == 0) {
|
1517
1525
|
presto_external_auth_prog = value;
|
1518
1526
|
return true;
|
@@ -1522,7 +1530,7 @@ static bool prestogres_hba_set_session_info(const char* key, const char* value)
|
|
1522
1530
|
return false;
|
1523
1531
|
}
|
1524
1532
|
|
1525
|
-
static void prestogres_hba_parse_arg(const char* arg)
|
1533
|
+
static void prestogres_hba_parse_arg(POOL_CONNECTION *frontend, const char* arg)
|
1526
1534
|
{
|
1527
1535
|
char *str, *tok;
|
1528
1536
|
|
@@ -1539,7 +1547,7 @@ static void prestogres_hba_parse_arg(const char* arg)
|
|
1539
1547
|
break;
|
1540
1548
|
}
|
1541
1549
|
*p = '\0';
|
1542
|
-
prestogres_hba_set_session_info(tok, p + 1);
|
1550
|
+
prestogres_hba_set_session_info(frontend, tok, p + 1);
|
1543
1551
|
}
|
1544
1552
|
}
|
1545
1553
|
|
@@ -1551,7 +1559,7 @@ static POOL_STATUS pool_prestogres_hba_auth_md5(POOL_CONNECTION *frontend)
|
|
1551
1559
|
static char encbuf[POOL_PASSWD_LEN+1];
|
1552
1560
|
char salt[4];
|
1553
1561
|
|
1554
|
-
prestogres_hba_parse_arg(frontend->auth_arg);
|
1562
|
+
prestogres_hba_parse_arg(frontend, frontend->auth_arg);
|
1555
1563
|
|
1556
1564
|
pool_passwd = pool_get_passwd(frontend->username);
|
1557
1565
|
pool_random_salt(salt);
|
@@ -1659,7 +1667,7 @@ static bool do_external_auth(POOL_CONNECTION* frontend, const char* password)
|
|
1659
1667
|
pos += strlen(line);
|
1660
1668
|
}
|
1661
1669
|
|
1662
|
-
prestogres_hba_parse_arg(buffer);
|
1670
|
+
prestogres_hba_parse_arg(frontend, buffer);
|
1663
1671
|
|
1664
1672
|
if (waitpid(pid, &status, 0) < 0) {
|
1665
1673
|
pool_error("waitpid() failed. reason: %s", strerror(errno));
|
@@ -1673,12 +1681,12 @@ static POOL_STATUS pool_prestogres_hba_auth_external(POOL_CONNECTION *frontend)
|
|
1673
1681
|
{
|
1674
1682
|
char *passwd;
|
1675
1683
|
|
1676
|
-
prestogres_hba_parse_arg(frontend->auth_arg);
|
1684
|
+
prestogres_hba_parse_arg(frontend, frontend->auth_arg);
|
1677
1685
|
|
1678
1686
|
if (presto_external_auth_prog == NULL) {
|
1679
1687
|
presto_external_auth_prog = pool_config->presto_external_auth_prog;
|
1680
1688
|
if (presto_external_auth_prog == NULL) {
|
1681
|
-
pool_error("pool_prestogres_hba_auth_external: '
|
1689
|
+
pool_error("pool_prestogres_hba_auth_external: 'auth_prog:' argument is not set to pool_hba entry for user '%s'", frontend->username);
|
1682
1690
|
exit(1);
|
1683
1691
|
}
|
1684
1692
|
}
|
@@ -2367,6 +2367,11 @@ void free_select_result(POOL_SELECT_RESULT *result)
|
|
2367
2367
|
* insert_lock(), and the qury is either LOCK or SELECT for UPDATE.
|
2368
2368
|
*/
|
2369
2369
|
POOL_STATUS do_query(POOL_CONNECTION *backend, char *query, POOL_SELECT_RESULT **result, int major)
|
2370
|
+
{
|
2371
|
+
return do_query_or_get_error_message(backend, query, result, major, NULL, NULL);
|
2372
|
+
}
|
2373
|
+
|
2374
|
+
POOL_STATUS do_query_or_get_error_message(POOL_CONNECTION *backend, char *query, POOL_SELECT_RESULT **result, int major, char **error_message, char **errcode)
|
2370
2375
|
{
|
2371
2376
|
#define DO_QUERY_ALLOC_NUM 1024 /* memory allocation unit for POOL_SELECT_RESULT */
|
2372
2377
|
|
@@ -2586,23 +2591,27 @@ POOL_STATUS do_query(POOL_CONNECTION *backend, char *query, POOL_SELECT_RESULT *
|
|
2586
2591
|
{
|
2587
2592
|
char *message;
|
2588
2593
|
|
2589
|
-
if (
|
2594
|
+
if (pool_extract_error_message_with_errcode(false, backend, major, true, &message, errcode))
|
2590
2595
|
{
|
2591
|
-
|
2592
|
-
|
2593
|
-
|
2594
|
-
|
2595
|
-
|
2596
|
-
|
2597
|
-
|
2598
|
-
|
2599
|
-
|
2600
|
-
|
2601
|
-
|
2602
|
-
|
2603
|
-
|
2604
|
-
|
2605
|
-
|
2596
|
+
if (error_message != NULL) {
|
2597
|
+
*error_message = message;
|
2598
|
+
} else {
|
2599
|
+
pool_error("do_query: error message from backend: %s. Exit this session.", message);
|
2600
|
+
/*
|
2601
|
+
* This is fatal. Because: If we operate extended
|
2602
|
+
* query, backend would not accept subsequent commands
|
2603
|
+
* until "sync" message issued. However, if sync
|
2604
|
+
* message issued, unnamed statement/unnamed portal
|
2605
|
+
* will disappear and will cause lots of problems. If
|
2606
|
+
* we do not operate extended query, ongoing
|
2607
|
+
* transaction is aborted, and subsequent query would
|
2608
|
+
* not accepted. In summary there's no transparent
|
2609
|
+
* way for frontend to handle error case. The only way
|
2610
|
+
* is closing this session.
|
2611
|
+
*/
|
2612
|
+
child_exit(1);
|
2613
|
+
return POOL_END;
|
2614
|
+
}
|
2606
2615
|
}
|
2607
2616
|
}
|
2608
2617
|
|
@@ -4585,6 +4594,11 @@ static int detect_error(POOL_CONNECTION *backend, char *error_code, int major, c
|
|
4585
4594
|
* extract error message -1: error)
|
4586
4595
|
*/
|
4587
4596
|
int pool_extract_error_message(bool read_kind, POOL_CONNECTION *backend, int major, bool unread, char **message)
|
4597
|
+
{
|
4598
|
+
return pool_extract_error_message_with_errcode(read_kind, backend, major, unread, message, NULL);
|
4599
|
+
}
|
4600
|
+
|
4601
|
+
int pool_extract_error_message_with_errcode(bool read_kind, POOL_CONNECTION *backend, int major, bool unread, char **message, char **errcode)
|
4588
4602
|
{
|
4589
4603
|
char kind;
|
4590
4604
|
int readlen = 0, len;
|
@@ -4617,6 +4631,7 @@ int pool_extract_error_message(bool read_kind, POOL_CONNECTION *backend, int maj
|
|
4617
4631
|
if (major == PROTO_MAJOR_V3)
|
4618
4632
|
{
|
4619
4633
|
char *e;
|
4634
|
+
char *bufpos, *bufpos_end;
|
4620
4635
|
|
4621
4636
|
if (pool_read(backend, &len, sizeof(len)) < 0)
|
4622
4637
|
return -1;
|
@@ -4649,15 +4664,27 @@ int pool_extract_error_message(bool read_kind, POOL_CONNECTION *backend, int maj
|
|
4649
4664
|
* (xxxxxx is error message).
|
4650
4665
|
*/
|
4651
4666
|
e = str;
|
4667
|
+
*message = message_buf;
|
4668
|
+
bufpos = message_buf;
|
4669
|
+
bufpos_end = message_buf + sizeof(message_buf);
|
4670
|
+
bufpos[0] = '\0';
|
4652
4671
|
while (*e)
|
4653
4672
|
{
|
4654
4673
|
if (*e == 'M')
|
4655
4674
|
{
|
4656
4675
|
e++;
|
4657
|
-
|
4658
|
-
|
4676
|
+
strlcpy(bufpos, e, bufpos_end - bufpos - 1);
|
4677
|
+
*message = bufpos;
|
4678
|
+
bufpos += strlen(bufpos) + 1;
|
4659
4679
|
break;
|
4660
4680
|
}
|
4681
|
+
else if (errcode != NULL && *e == 'C')
|
4682
|
+
{
|
4683
|
+
e++;
|
4684
|
+
strlcpy(bufpos, e, bufpos_end - bufpos - 1);
|
4685
|
+
*errcode = bufpos;
|
4686
|
+
bufpos += strlen(bufpos) + 1;
|
4687
|
+
}
|
4661
4688
|
else
|
4662
4689
|
e = e + strlen(e) + 1;
|
4663
4690
|
}
|
@@ -4678,6 +4705,7 @@ int pool_extract_error_message(bool read_kind, POOL_CONNECTION *backend, int maj
|
|
4678
4705
|
memcpy(p, str, len);
|
4679
4706
|
memcpy(message_buf, str, len);
|
4680
4707
|
message_buf[len] = '\0';
|
4708
|
+
*message = message_buf;
|
4681
4709
|
}
|
4682
4710
|
|
4683
4711
|
if (unread)
|
@@ -4687,7 +4715,6 @@ int pool_extract_error_message(bool read_kind, POOL_CONNECTION *backend, int maj
|
|
4687
4715
|
return -1;
|
4688
4716
|
}
|
4689
4717
|
|
4690
|
-
*message = message_buf;
|
4691
4718
|
return 1;
|
4692
4719
|
}
|
4693
4720
|
|