prestogres 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|