Skip to content

Commit 2c32d3e

Browse files
authored
fix: improve error handling (#14)
1 parent fe08b00 commit 2c32d3e

File tree

4 files changed

+76
-20
lines changed

4 files changed

+76
-20
lines changed

.editorconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# EditorConfig helps maintain consistent coding styles across editors and IDEs
2+
3+
root = true
4+
5+
[*]
6+
indent_style = space
7+
indent_size = 4
8+
end_of_line = lf
9+
charset = utf-8
10+
trim_trailing_whitespace = true
11+
insert_final_newline = true
12+
max_line_length = 80

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
.idea
22
.env.sh
3+
compile_commands.json
4+
*.o
5+
*.so

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ docker exec -it postgres psql -U postgres postgres
6262
docker exec -it postgres psql -U any_username any_database_name
6363
```
6464

65+
## Development
66+
67+
You can use [bear](https://github.com/rizsotto/Bear) to generate a `compile_commands.json` which is
68+
understood by IDE's like CLion.
69+
70+
```shell
71+
bear -- make
72+
```
73+
6574
## References
6675

6776
See https://github.com/taminomara/psql-hooks for the unofficial documentation of Postgresql hooks

ensure_role_and_database_exists.c

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,79 @@
1-
#include <stdlib.h>
2-
31
#include "postgres.h"
42
#include "fmgr.h"
53

64
#include "libpq/auth.h"
7-
#include <unistd.h>
5+
#include "executor/spi.h"
6+
#include "miscadmin.h"
87

98
PG_MODULE_MAGIC;
109

1110
static ClientAuthentication_hook_type original_client_auth_hook = NULL;
1211

12+
static void execute_command(const char *cmd) {
13+
int result = system(cmd);
14+
15+
if (result != 0) {
16+
ereport(ERROR, (
17+
errmsg("command failed"),
18+
errdetail("Command: %s\nExit code: %d", cmd, WEXITSTATUS(result))
19+
)
20+
);
21+
}
22+
}
23+
1324
static void ensure_role_and_database_exists(Port *port, int status) {
14-
char *cmd;
15-
char *postgres_user;
16-
char *role_attributes;
25+
char *cmd = NULL;
26+
const char *postgres_user = getenv("POSTGRES_USER");
27+
const char *role_attributes = getenv("POSTGRES_ROLE_ATTRIBUTES");
1728

1829
if (original_client_auth_hook) {
1930
original_client_auth_hook(port, status);
2031
}
2132

22-
postgres_user = getenv("POSTGRES_USER");
33+
if (!postgres_user) {
34+
ereport(ERROR, errmsg("POSTGRES_USER environment variable is not set."));
35+
}
2336

24-
fprintf(stderr, "handling connection for username '%s' to database '%s'\n", port->user_name, port->database_name);
37+
if (!role_attributes) {
38+
ereport(ERROR, errmsg("POSTGRES_ROLE_ATTRIBUTES environment variable is not set."));
39+
}
2540

2641
// don't infinitely recurse when connecting as superuser
27-
if (strcmp(port->database_name, postgres_user) == 0 && strcmp(port->user_name, postgres_user) == 0) {
42+
if (strcmp(port->user_name, postgres_user) == 0 && strcmp(port->database_name, postgres_user) == 0) {
2843
return;
2944
}
3045

31-
role_attributes = getenv("POSTGRES_ROLE_ATTRIBUTES");
46+
elog(LOG, "handling connection for username '%s' to database '%s'", port->user_name, port->database_name);
47+
48+
elog(LOG, "ensuring user_name '%s' exists with attributes '%s'", port->user_name, role_attributes);
49+
if (asprintf(&cmd,
50+
"echo \"SELECT 'CREATE ROLE %s WITH %s' WHERE NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '%s')\\gexec\" | psql -U %s -d %s",
51+
port->user_name,
52+
role_attributes,
53+
port->user_name,
54+
postgres_user,
55+
postgres_user
56+
) < 0) {
57+
ereport(ERROR, errmsg("failed to allocate command string"));
58+
}
3259

33-
fprintf(stderr, "ensuring user_name '%s' exists with attributes '%s'\n", port->user_name, role_attributes);
34-
asprintf(&cmd,
35-
"echo \"SELECT 'CREATE ROLE %s WITH %s' WHERE NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '%s')\\gexec\" | psql -U %s -d %s",
36-
port->user_name, role_attributes, port->user_name, postgres_user, postgres_user);
37-
system(cmd);
60+
execute_command(cmd);
3861
free(cmd);
3962

40-
fprintf(stderr, "ensuring database '%s' exists\n", port->database_name);
41-
asprintf(&cmd,
42-
"echo \"SELECT 'CREATE DATABASE %s WITH OWNER = %s' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '%s')\\gexec\" | psql -U %s -d %s",
43-
port->database_name, port->user_name, port->database_name, postgres_user, postgres_user);
44-
system(cmd);
63+
elog(LOG, "ensuring database '%s' exists", port->database_name);
64+
65+
if (asprintf(&cmd,
66+
"echo \"SELECT 'CREATE DATABASE %s WITH OWNER = %s' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '%s')\\gexec\" | psql -U %s -d %s",
67+
port->database_name,
68+
port->user_name,
69+
port->database_name,
70+
postgres_user,
71+
postgres_user
72+
) < 0) {
73+
ereport(ERROR, errmsg("failed to allocate command string"));
74+
}
75+
76+
execute_command(cmd);
4577
free(cmd);
4678
}
4779

0 commit comments

Comments
 (0)