|
1 | | -#include "pg_prelude.h" |
2 | 1 | #include "privileged_extensions.h" |
3 | | -#include "utils.h" |
4 | | - |
5 | | -// Prevent recursively running custom scripts |
6 | | -static bool running_custom_script = false; |
7 | | - |
8 | | -// This produces a char surrounded by a triple single quote like '''x''' |
9 | | -// This is so when it gets interpreted by SQL it converts to a single quote surround: 'x' |
10 | | -// To see an example, do `select 'x';` vs `select '''x''';` on psql. |
11 | | -static char *sql_literal(const char *str){ |
12 | | - return str == NULL? |
13 | | - "'null'": // also handle the NULL cstr case |
14 | | - quote_literal_cstr(quote_literal_cstr(str)); |
15 | | -} |
16 | | - |
17 | | -static void run_custom_script(const char *filename, const char *extname, |
18 | | - const char *extschema, const char *extversion, |
19 | | - bool extcascade) { |
20 | | - if (running_custom_script) { |
21 | | - return; |
22 | | - } |
23 | | - running_custom_script = true; |
24 | | - |
25 | | - static const char sql_replace_template[] = "\ |
26 | | - do $_$\ |
27 | | - begin\ |
28 | | - execute replace(replace(replace(replace(\ |
29 | | - pg_read_file(%s)\ |
30 | | - , '@extname@', %s)\ |
31 | | - , '@extschema@', %s)\ |
32 | | - , '@extversion@', %s)\ |
33 | | - , '@extcascade@', %s);\ |
34 | | - exception\ |
35 | | - when undefined_file then\ |
36 | | - null;\ |
37 | | - end; $_$"; |
38 | | - |
39 | | - static const size_t max_sql_len |
40 | | - = sizeof (sql_replace_template) |
41 | | - + MAXPGPATH // max size of a file path |
42 | | - + 3 * (NAMEDATALEN + 6) // 3 *(identifier + 6 single quotes of the SQL literal, see sql_literal) |
43 | | - + sizeof ("false") // max size of a bool string value |
44 | | - ; |
45 | | - |
46 | | - char sql[max_sql_len]; |
47 | | - |
48 | | - snprintf(sql, |
49 | | - max_sql_len, |
50 | | - sql_replace_template, |
51 | | - quote_literal_cstr(filename), |
52 | | - sql_literal(extname), |
53 | | - sql_literal(extschema), |
54 | | - sql_literal(extversion), |
55 | | - extcascade?"'true'":"'false'"); |
56 | | - |
57 | | - PushActiveSnapshot(GetTransactionSnapshot()); |
58 | | - SPI_connect(); |
59 | | - |
60 | | - int rc = SPI_execute(sql, false, 0); |
61 | | - if (rc != SPI_OK_UTILITY) { |
62 | | - elog(ERROR, "SPI_execute failed with error code %d", rc); |
63 | | - } |
64 | | - SPI_finish(); |
65 | | - PopActiveSnapshot(); |
66 | | - running_custom_script = false; |
67 | | -} |
68 | | - |
69 | | -void run_global_before_create_script(char *extname, List *options, const char *privileged_extensions_custom_scripts_path){ |
70 | | - DefElem *d_schema = NULL, *d_new_version = NULL, *d_cascade = NULL; |
71 | | - char *extschema = NULL, *extversion = NULL; |
72 | | - bool extcascade = false; |
73 | | - char filename[MAXPGPATH]; |
74 | | - |
75 | | - ListCell *option_cell = NULL; |
76 | | - |
77 | | - foreach (option_cell, options) { |
78 | | - DefElem *defel = (DefElem *)lfirst(option_cell); |
79 | | - |
80 | | - if (strcmp(defel->defname, "schema") == 0) { |
81 | | - d_schema = defel; |
82 | | - extschema = defGetString(d_schema); |
83 | | - } else if (strcmp(defel->defname, "new_version") == 0) { |
84 | | - d_new_version = defel; |
85 | | - extversion = defGetString(d_new_version); |
86 | | - } else if (strcmp(defel->defname, "cascade") == 0) { |
87 | | - d_cascade = defel; |
88 | | - extcascade = defGetBoolean(d_cascade); |
89 | | - } |
90 | | - } |
91 | | - |
92 | | - snprintf(filename, MAXPGPATH, "%s/before-create.sql", |
93 | | - privileged_extensions_custom_scripts_path); |
94 | | - run_custom_script(filename, extname, extschema, extversion, |
95 | | - extcascade); |
96 | | -} |
97 | | - |
98 | | -void run_ext_before_create_script(char *extname, List *options, const char *privileged_extensions_custom_scripts_path){ |
99 | | - DefElem *d_schema = NULL; |
100 | | - DefElem *d_new_version = NULL; |
101 | | - DefElem *d_cascade = NULL; |
102 | | - char *extschema = NULL; |
103 | | - char *extversion = NULL; |
104 | | - bool extcascade = false; |
105 | | - ListCell *option_cell = NULL; |
106 | | - char filename[MAXPGPATH]; |
107 | | - |
108 | | - foreach (option_cell, options) { |
109 | | - DefElem *defel = (DefElem *)lfirst(option_cell); |
110 | | - |
111 | | - if (strcmp(defel->defname, "schema") == 0) { |
112 | | - d_schema = defel; |
113 | | - extschema = defGetString(d_schema); |
114 | | - } else if (strcmp(defel->defname, "new_version") == 0) { |
115 | | - d_new_version = defel; |
116 | | - extversion = defGetString(d_new_version); |
117 | | - } else if (strcmp(defel->defname, "cascade") == 0) { |
118 | | - d_cascade = defel; |
119 | | - extcascade = defGetBoolean(d_cascade); |
120 | | - } |
121 | | - } |
122 | | - |
123 | | - |
124 | | - snprintf(filename, MAXPGPATH, "%s/%s/before-create.sql", |
125 | | - privileged_extensions_custom_scripts_path, extname); |
126 | | - run_custom_script(filename, extname, extschema, extversion, |
127 | | - extcascade); |
128 | | -} |
129 | | - |
130 | | -void run_ext_after_create_script(char *extname, List *options, const char *privileged_extensions_custom_scripts_path){ |
131 | | - DefElem *d_schema = NULL; |
132 | | - DefElem *d_new_version = NULL; |
133 | | - DefElem *d_cascade = NULL; |
134 | | - char *extschema = NULL; |
135 | | - char *extversion = NULL; |
136 | | - bool extcascade = false; |
137 | | - ListCell *option_cell = NULL; |
138 | | - char filename[MAXPGPATH]; |
139 | | - |
140 | | - foreach (option_cell, options) { |
141 | | - DefElem *defel = (DefElem *)lfirst(option_cell); |
142 | | - |
143 | | - if (strcmp(defel->defname, "schema") == 0) { |
144 | | - d_schema = defel; |
145 | | - extschema = defGetString(d_schema); |
146 | | - } else if (strcmp(defel->defname, "new_version") == 0) { |
147 | | - d_new_version = defel; |
148 | | - extversion = defGetString(d_new_version); |
149 | | - } else if (strcmp(defel->defname, "cascade") == 0) { |
150 | | - d_cascade = defel; |
151 | | - extcascade = defGetBoolean(d_cascade); |
152 | | - } |
153 | | - } |
154 | | - |
155 | | - snprintf(filename, MAXPGPATH, "%s/%s/after-create.sql", |
156 | | - privileged_extensions_custom_scripts_path, extname); |
157 | | - run_custom_script(filename, extname, extschema, extversion, |
158 | | - extcascade); |
159 | | -} |
160 | 2 |
|
161 | 3 | bool all_extensions_are_privileged(List *objects, const char *privileged_extensions){ |
162 | 4 | ListCell *lc; |
|
0 commit comments