Asterisk - The Open Source Telephony Project GIT-master-55f4e6d
Data Structures | Macros | Functions | Variables
cel_pgsql.c File Reference

PostgreSQL CEL logger. More...

#include "asterisk.h"
#include <libpq-fe.h>
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/cel.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
Include dependency graph for cel_pgsql.c:

Go to the source code of this file.

Data Structures

struct  columns
 
struct  psql_columns
 

Macros

#define CEL_SHOW_USERDEF_DEFAULT   0
 show_user_def is off by default More...
 
#define DATE_FORMAT   "%Y-%m-%d %T.%6q"
 
#define LENGTHEN_BUF(size, var_sql)
 
#define LENGTHEN_BUF1(size)    LENGTHEN_BUF(size, sql);
 
#define LENGTHEN_BUF2(size)    LENGTHEN_BUF(size, sql2);
 
#define PGSQL_BACKEND_NAME   "CEL PGSQL backend"
 
#define PGSQL_MIN_VERSION_SCHEMA   70300
 
#define SEP   (first ? "" : ",")
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int load_module (void)
 
static int my_load_module (int reload)
 
static int my_unload_module (void)
 
static void pgsql_log (struct ast_event *event)
 
static void pgsql_reconnect (void)
 
static int process_my_load_module (struct ast_config *cfg)
 
static int reload (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PostgreSQL CEL Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, .requires = "cel", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static unsigned char cel_show_user_def
 
static char * config = "cel_pgsql.conf"
 
static PGconn * conn = NULL
 
static int connected = 0
 
static int maxsize = 512
 
static int maxsize2 = 512
 
static char * pgappname
 
static char * pgdbname
 
static char * pgdbport
 
static char * pgdbuser
 
static char * pghostname
 
static char * pgpassword
 
static ast_mutex_t pgsql_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static struct psql_columns psql_columns = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
static PGresult * result = NULL
 
static char * schema
 
static char * table
 
static int usegmtime = 0
 

Detailed Description

PostgreSQL CEL logger.

Author
Steve Murphy murf@.nosp@m.digi.nosp@m.um.co.nosp@m.m PostgreSQL http://www.postgresql.org/

Definition in file cel_pgsql.c.

Macro Definition Documentation

◆ CEL_SHOW_USERDEF_DEFAULT

#define CEL_SHOW_USERDEF_DEFAULT   0

show_user_def is off by default

Definition at line 76 of file cel_pgsql.c.

◆ DATE_FORMAT

#define DATE_FORMAT   "%Y-%m-%d %T.%6q"

Definition at line 53 of file cel_pgsql.c.

◆ LENGTHEN_BUF

#define LENGTHEN_BUF (   size,
  var_sql 
)

Definition at line 97 of file cel_pgsql.c.

◆ LENGTHEN_BUF1

#define LENGTHEN_BUF1 (   size)     LENGTHEN_BUF(size, sql);

Definition at line 111 of file cel_pgsql.c.

◆ LENGTHEN_BUF2

#define LENGTHEN_BUF2 (   size)     LENGTHEN_BUF(size, sql2);

Definition at line 113 of file cel_pgsql.c.

◆ PGSQL_BACKEND_NAME

#define PGSQL_BACKEND_NAME   "CEL PGSQL backend"

Definition at line 55 of file cel_pgsql.c.

◆ PGSQL_MIN_VERSION_SCHEMA

#define PGSQL_MIN_VERSION_SCHEMA   70300

Definition at line 57 of file cel_pgsql.c.

◆ SEP

#define SEP   (first ? "" : ",")

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 709 of file cel_pgsql.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 709 of file cel_pgsql.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 709 of file cel_pgsql.c.

◆ load_module()

static int load_module ( void  )
static

Definition at line 692 of file cel_pgsql.c.

693{
694 return my_load_module(0);
695}
static int my_load_module(int reload)
Definition: cel_pgsql.c:665

References my_load_module().

◆ my_load_module()

static int my_load_module ( int  reload)
static

Definition at line 665 of file cel_pgsql.c.

666{
667 struct ast_config *cfg;
668 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
669
670 if ((cfg = ast_config_load(config, config_flags)) == NULL || cfg == CONFIG_STATUS_FILEINVALID) {
671 ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CEL's: %s\n", config);
673 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
675 }
676
677 if (reload) {
679 }
680
683
685 ast_log(LOG_WARNING, "Unable to subscribe to CEL events for pgsql\n");
687 }
688
690}
#define ast_log
Definition: astobj2.c:42
int ast_cel_backend_register(const char *name, ast_cel_backend_cb backend_callback)
Register a CEL backend.
Definition: cel.c:1781
static int process_my_load_module(struct ast_config *cfg)
Definition: cel_pgsql.c:454
static char * config
Definition: cel_pgsql.c:59
static int my_unload_module(void)
Definition: cel_pgsql.c:400
#define PGSQL_BACKEND_NAME
Definition: cel_pgsql.c:55
static void pgsql_log(struct ast_event *event)
Definition: cel_pgsql.c:145
static int reload(void)
Definition: cel_pgsql.c:697
#define ast_config_load(filename, flags)
Load a config file.
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
@ CONFIG_FLAG_FILEUNCHANGED
#define LOG_WARNING
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define NULL
Definition: resample.c:96
Structure used to handle boolean flags.
Definition: utils.h:199

References ast_cel_backend_register(), ast_config_destroy(), ast_config_load, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, LOG_WARNING, my_unload_module(), NULL, PGSQL_BACKEND_NAME, pgsql_log(), process_my_load_module(), and reload().

Referenced by load_module(), and reload().

◆ my_unload_module()

static int my_unload_module ( void  )
static

Definition at line 400 of file cel_pgsql.c.

401{
402 struct columns *current;
403
406 if (conn) {
407 PQfinish(conn);
408 conn = NULL;
409 }
410 if (pghostname) {
413 }
414 if (pgdbname) {
416 pgdbname = NULL;
417 }
418 if (pgdbuser) {
420 pgdbuser = NULL;
421 }
422 if (pgpassword) {
425 }
426 if (pgappname) {
428 pgappname = NULL;
429 }
430 if (pgdbport) {
432 pgdbport = NULL;
433 }
434 if (table) {
436 table = NULL;
437 }
438 if (schema) {
440 schema = NULL;
441 }
444 }
446 return 0;
447}
#define ast_free(a)
Definition: astmm.h:180
int ast_cel_backend_unregister(const char *name)
Unregister a CEL backend.
Definition: cel.c:1769
static char * pgdbuser
Definition: cel_pgsql.c:63
static char * schema
Definition: cel_pgsql.c:68
static char * pgappname
Definition: cel_pgsql.c:65
static char * pgdbport
Definition: cel_pgsql.c:66
static char * pgdbname
Definition: cel_pgsql.c:62
static char * table
Definition: cel_pgsql.c:67
static char * pghostname
Definition: cel_pgsql.c:61
static char * pgpassword
Definition: cel_pgsql.c:64
static PGconn * conn
Definition: cel_pgsql.c:83
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_RWLIST_REMOVE_HEAD
Definition: linkedlists.h:844
size_t current
Definition: main/cli.c:113
struct columns::@4 list

References ast_cel_backend_unregister(), ast_free, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, conn, current, columns::list, NULL, pgappname, pgdbname, pgdbport, pgdbuser, pghostname, pgpassword, PGSQL_BACKEND_NAME, schema, and table.

Referenced by my_load_module(), and unload_module().

◆ pgsql_log()

static void pgsql_log ( struct ast_event event)
static

Definition at line 145 of file cel_pgsql.c.

146{
147 struct ast_tm tm;
148 char timestr[128];
149 char *pgerror;
150 struct ast_cel_event_record record = {
152 };
153
154 if (ast_cel_fill_record(event, &record)) {
155 return;
156 }
157
159
160 ast_localtime(&record.event_time, &tm, usegmtime ? "GMT" : NULL);
161 ast_strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
162
163 if ((!connected) && pghostname && pgdbuser && pgpassword && pgdbname) {
165 if (PQstatus(conn) != CONNECTION_BAD) {
166 connected = 1;
167 } else {
168 pgerror = PQerrorMessage(conn);
169 ast_log(LOG_ERROR, "cel_pgsql: Unable to connect to database server %s. Calls will not be logged!\n", pghostname);
170 ast_log(LOG_ERROR, "cel_pgsql: Reason: %s\n", pgerror);
171 PQfinish(conn);
172 conn = NULL;
173 }
174 }
175 if (connected) {
176 struct columns *cur;
177 struct ast_str *sql = ast_str_create(maxsize), *sql2 = ast_str_create(maxsize2);
178 char buf[257];
179 char *escapebuf = NULL;
180 const char *value;
181 int first = 1;
182 size_t bufsize = 513;
183
184 escapebuf = ast_malloc(bufsize);
185 if (!escapebuf || !sql || !sql2) {
186 goto ast_log_cleanup;
187 }
188
189 ast_str_set(&sql, 0, "INSERT INTO %s (", table);
190 ast_str_set(&sql2, 0, " VALUES (");
191
192#define SEP (first ? "" : ",")
193
195 AST_RWLIST_TRAVERSE(&psql_columns, cur, list) {
196 LENGTHEN_BUF1(strlen(cur->name) + 2);
197 ast_str_append(&sql, 0, "%s\"%s\"", SEP, cur->name);
198
199 if (strcmp(cur->name, "eventtime") == 0) {
200 if (strncmp(cur->type, "int", 3) == 0) {
201 LENGTHEN_BUF2(13);
202 ast_str_append(&sql2, 0, "%s%ld", SEP, (long) record.event_time.tv_sec);
203 } else if (strncmp(cur->type, "float", 5) == 0) {
204 LENGTHEN_BUF2(31);
205 ast_str_append(&sql2, 0, "%s%f",
206 SEP,
207 (double) record.event_time.tv_sec +
208 (double) record.event_time.tv_usec / 1000000.0);
209 } else {
210 /* char, hopefully */
211 LENGTHEN_BUF2(31);
212 ast_localtime(&record.event_time, &tm, usegmtime ? "GMT" : NULL);
213 ast_strftime(buf, sizeof(buf), DATE_FORMAT, &tm);
214 ast_str_append(&sql2, 0, "%s'%s'", SEP, buf);
215 }
216 } else if (strcmp(cur->name, "eventtype") == 0) {
217 if (cur->type[0] == 'i') {
218 /* Get integer, no need to escape anything */
219 LENGTHEN_BUF2(5);
220 ast_str_append(&sql2, 0, "%s%d", SEP, (int) record.event_type);
221 } else if (strncmp(cur->type, "float", 5) == 0) {
222 LENGTHEN_BUF2(31);
223 ast_str_append(&sql2, 0, "%s%f", SEP, (double) record.event_type);
224 } else {
225 /* Char field, probably */
226 const char *event_name;
227
228 event_name = (!cel_show_user_def
229 && record.event_type == AST_CEL_USER_DEFINED)
230 ? record.user_defined_name : record.event_name;
231 LENGTHEN_BUF2(strlen(event_name) + 1);
232 ast_str_append(&sql2, 0, "%s'%s'", SEP, event_name);
233 }
234 } else if (strcmp(cur->name, "amaflags") == 0) {
235 if (strncmp(cur->type, "int", 3) == 0) {
236 /* Integer, no need to escape anything */
237 LENGTHEN_BUF2(13);
238 ast_str_append(&sql2, 0, "%s%u", SEP, record.amaflag);
239 } else {
240 /* Although this is a char field, there are no special characters in the values for these fields */
241 LENGTHEN_BUF2(31);
242 ast_str_append(&sql2, 0, "%s'%u'", SEP, record.amaflag);
243 }
244 } else {
245 /* Arbitrary field, could be anything */
246 if (strcmp(cur->name, "userdeftype") == 0) {
247 value = record.user_defined_name;
248 } else if (strcmp(cur->name, "cid_name") == 0) {
249 value = record.caller_id_name;
250 } else if (strcmp(cur->name, "cid_num") == 0) {
251 value = record.caller_id_num;
252 } else if (strcmp(cur->name, "cid_ani") == 0) {
253 value = record.caller_id_ani;
254 } else if (strcmp(cur->name, "cid_rdnis") == 0) {
255 value = record.caller_id_rdnis;
256 } else if (strcmp(cur->name, "cid_dnid") == 0) {
257 value = record.caller_id_dnid;
258 } else if (strcmp(cur->name, "exten") == 0) {
259 value = record.extension;
260 } else if (strcmp(cur->name, "context") == 0) {
261 value = record.context;
262 } else if (strcmp(cur->name, "channame") == 0) {
263 value = record.channel_name;
264 } else if (strcmp(cur->name, "appname") == 0) {
265 value = record.application_name;
266 } else if (strcmp(cur->name, "appdata") == 0) {
267 value = record.application_data;
268 } else if (strcmp(cur->name, "accountcode") == 0) {
269 value = record.account_code;
270 } else if (strcmp(cur->name, "peeraccount") == 0) {
271 value = record.peer_account;
272 } else if (strcmp(cur->name, "uniqueid") == 0) {
273 value = record.unique_id;
274 } else if (strcmp(cur->name, "linkedid") == 0) {
275 value = record.linked_id;
276 } else if (strcmp(cur->name, "userfield") == 0) {
277 value = record.user_field;
278 } else if (strcmp(cur->name, "peer") == 0) {
279 value = record.peer;
280 } else if (strcmp(cur->name, "extra") == 0) {
281 value = record.extra;
282 } else {
283 value = NULL;
284 }
285
286 if (value == NULL) {
287 ast_str_append(&sql2, 0, "%sDEFAULT", SEP);
288 } else if (strncmp(cur->type, "int", 3) == 0) {
289 long long whatever;
290 if (value && sscanf(value, "%30lld", &whatever) == 1) {
291 LENGTHEN_BUF2(26);
292 ast_str_append(&sql2, 0, "%s%lld", SEP, whatever);
293 } else {
294 LENGTHEN_BUF2(2);
295 ast_str_append(&sql2, 0, "%s0", SEP);
296 }
297 } else if (strncmp(cur->type, "float", 5) == 0) {
298 long double whatever;
299 if (value && sscanf(value, "%30Lf", &whatever) == 1) {
300 LENGTHEN_BUF2(51);
301 ast_str_append(&sql2, 0, "%s%30Lf", SEP, whatever);
302 } else {
303 LENGTHEN_BUF2(2);
304 ast_str_append(&sql2, 0, "%s0", SEP);
305 }
306 /* XXX Might want to handle dates, times, and other misc fields here XXX */
307 } else {
308 if (value) {
309 size_t required_size = strlen(value) * 2 + 1;
310
311 /* If our argument size exceeds our buffer, grow it,
312 * as PQescapeStringConn() expects the buffer to be
313 * adequitely sized and does *NOT* do size checking.
314 */
315 if (required_size > bufsize) {
316 char *tmpbuf = ast_realloc(escapebuf, required_size);
317
318 if (!tmpbuf) {
320 goto ast_log_cleanup;
321 }
322
323 escapebuf = tmpbuf;
324 bufsize = required_size;
325 }
326 PQescapeStringConn(conn, escapebuf, value, strlen(value), NULL);
327 } else {
328 escapebuf[0] = '\0';
329 }
330 LENGTHEN_BUF2(strlen(escapebuf) + 3);
331 ast_str_append(&sql2, 0, "%s'%s'", SEP, escapebuf);
332 }
333 }
334 first = 0;
335 }
337 LENGTHEN_BUF1(ast_str_strlen(sql2) + 2);
338 ast_str_append(&sql, 0, ")%s)", ast_str_buffer(sql2));
339
340 ast_debug(3, "Inserting a CEL record: [%s].\n", ast_str_buffer(sql));
341 /* Test to be sure we're still connected... */
342 /* If we're connected, and connection is working, good. */
343 /* Otherwise, attempt reconnect. If it fails... sorry... */
344 if (PQstatus(conn) == CONNECTION_OK) {
345 connected = 1;
346 } else {
347 ast_log(LOG_WARNING, "Connection was lost... attempting to reconnect.\n");
348 PQreset(conn);
349 if (PQstatus(conn) == CONNECTION_OK) {
350 ast_log(LOG_NOTICE, "Connection reestablished.\n");
351 connected = 1;
352 } else {
353 pgerror = PQerrorMessage(conn);
354 ast_log(LOG_ERROR, "Unable to reconnect to database server %s. Calls will not be logged!\n", pghostname);
355 ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
356 PQfinish(conn);
357 conn = NULL;
358 connected = 0;
359 goto ast_log_cleanup;
360 }
361 }
362 result = PQexec(conn, ast_str_buffer(sql));
363 if (PQresultStatus(result) != PGRES_COMMAND_OK) {
364 pgerror = PQresultErrorMessage(result);
365 ast_log(LOG_WARNING, "Failed to insert call detail record into database!\n");
366 ast_log(LOG_WARNING, "Reason: %s\n", pgerror);
367 ast_log(LOG_WARNING, "Connection may have been lost... attempting to reconnect.\n");
368 PQreset(conn);
369 if (PQstatus(conn) == CONNECTION_OK) {
370 ast_log(LOG_NOTICE, "Connection reestablished.\n");
371 connected = 1;
372 PQclear(result);
373 result = PQexec(conn, ast_str_buffer(sql));
374 if (PQresultStatus(result) != PGRES_COMMAND_OK) {
375 pgerror = PQresultErrorMessage(result);
376 ast_log(LOG_ERROR, "HARD ERROR! Attempted reconnection failed. DROPPING CALL RECORD!\n");
377 ast_log(LOG_ERROR, "Reason: %s\n", pgerror);
378 }
379 }
380 }
381 PQclear(result);
382
383 /* Next time, just allocate buffers that are that big to start with. */
384 if (ast_str_strlen(sql) > maxsize) {
385 maxsize = ast_str_strlen(sql);
386 }
387 if (ast_str_strlen(sql2) > maxsize2) {
388 maxsize2 = ast_str_strlen(sql2);
389 }
390
391ast_log_cleanup:
392 ast_free(sql);
393 ast_free(sql2);
394 ast_free(escapebuf);
395 }
396
398}
struct sla_ringing_trunk * first
Definition: app_sla.c:332
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:226
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
@ AST_CEL_USER_DEFINED
a user-defined event, the event name field should be set
Definition: cel.h:69
int ast_cel_fill_record(const struct ast_event *event, struct ast_cel_event_record *r)
Fill in an ast_cel_event_record from a CEL event.
Definition: cel.c:821
#define AST_CEL_EVENT_RECORD_VERSION
struct ABI version
Definition: cel.h:143
#define LENGTHEN_BUF2(size)
Definition: cel_pgsql.c:113
static int maxsize2
Definition: cel_pgsql.c:72
static int maxsize
Definition: cel_pgsql.c:72
static void pgsql_reconnect(void)
Definition: cel_pgsql.c:116
#define SEP
static int connected
Definition: cel_pgsql.c:70
static ast_mutex_t pgsql_lock
Definition: cel_pgsql.c:81
static unsigned char cel_show_user_def
Definition: cel_pgsql.c:79
static int usegmtime
Definition: cel_pgsql.c:73
static PGresult * result
Definition: cel_pgsql.c:84
#define DATE_FORMAT
Definition: cel_pgsql.c:53
#define LENGTHEN_BUF1(size)
Definition: cel_pgsql.c:111
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
Helper struct for getting the fields out of a CEL event.
Definition: cel.h:138
const char * caller_id_dnid
Definition: cel.h:157
const char * application_data
Definition: cel.h:162
const char * account_code
Definition: cel.h:163
const char * caller_id_rdnis
Definition: cel.h:156
const char * extra
Definition: cel.h:170
const char * extension
Definition: cel.h:158
const char * caller_id_num
Definition: cel.h:154
const char * channel_name
Definition: cel.h:160
const char * linked_id
Definition: cel.h:166
const char * peer_account
Definition: cel.h:164
const char * peer
Definition: cel.h:169
enum ast_cel_event_type event_type
Definition: cel.h:149
const char * unique_id
Definition: cel.h:165
const char * user_defined_name
Definition: cel.h:152
const char * context
Definition: cel.h:159
const char * application_name
Definition: cel.h:161
struct timeval event_time
Definition: cel.h:150
uint32_t version
struct ABI version
Definition: cel.h:148
const char * user_field
Definition: cel.h:168
const char * caller_id_ani
Definition: cel.h:155
const char * caller_id_name
Definition: cel.h:153
const char * event_name
Definition: cel.h:151
Support for dynamic strings.
Definition: strings.h:623
Definition: astman.c:222
int value
Definition: syslog.c:37

References ast_cel_event_record::account_code, ast_cel_event_record::amaflag, ast_cel_event_record::application_data, ast_cel_event_record::application_name, AST_CEL_EVENT_RECORD_VERSION, ast_cel_fill_record(), AST_CEL_USER_DEFINED, ast_debug, ast_free, ast_localtime(), ast_log, ast_malloc, ast_mutex_lock, ast_mutex_unlock, ast_realloc, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_str_strlen(), ast_strftime(), buf, ast_cel_event_record::caller_id_ani, ast_cel_event_record::caller_id_dnid, ast_cel_event_record::caller_id_name, ast_cel_event_record::caller_id_num, ast_cel_event_record::caller_id_rdnis, cel_show_user_def, ast_cel_event_record::channel_name, conn, connected, ast_cel_event_record::context, DATE_FORMAT, ast_cel_event_record::event_name, ast_cel_event_record::event_time, ast_cel_event_record::event_type, ast_cel_event_record::extension, ast_cel_event_record::extra, first, LENGTHEN_BUF1, LENGTHEN_BUF2, ast_cel_event_record::linked_id, LOG_ERROR, LOG_NOTICE, LOG_WARNING, maxsize, maxsize2, columns::name, NULL, ast_cel_event_record::peer, ast_cel_event_record::peer_account, pgdbname, pgdbuser, pghostname, pgpassword, pgsql_lock, pgsql_reconnect(), result, SEP, table, columns::type, ast_cel_event_record::unique_id, usegmtime, ast_cel_event_record::user_defined_name, ast_cel_event_record::user_field, value, and ast_cel_event_record::version.

Referenced by my_load_module().

◆ pgsql_reconnect()

static void pgsql_reconnect ( void  )
static

Definition at line 116 of file cel_pgsql.c.

117{
118 struct ast_str *conn_info = ast_str_create(128);
119 if (!conn_info) {
120 ast_log(LOG_ERROR, "Failed to allocate memory for connection string.\n");
121 return;
122 }
123
124 if (conn) {
125 PQfinish(conn);
126 conn = NULL;
127 }
128
129 ast_str_set(&conn_info, 0, "host=%s port=%s dbname=%s user=%s",
131
133 ast_str_append(&conn_info, 0, " application_name=%s", pgappname);
134 }
135
137 ast_str_append(&conn_info, 0, " password=%s", pgpassword);
138 }
139
140 conn = PQconnectdb(ast_str_buffer(conn_info));
141 ast_free(conn_info);
142}
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65

References ast_free, ast_log, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_strlen_zero(), conn, LOG_ERROR, NULL, pgappname, pgdbname, pgdbport, pgdbuser, pghostname, and pgpassword.

Referenced by pgsql_log(), and process_my_load_module().

◆ process_my_load_module()

static int process_my_load_module ( struct ast_config cfg)
static

Definition at line 454 of file cel_pgsql.c.

455{
456 struct ast_variable *var;
457 char *pgerror;
458 const char *tmp;
459 PGresult *result;
460 struct columns *cur;
461
462 if (!(var = ast_variable_browse(cfg, "global"))) {
463 ast_log(LOG_WARNING,"CEL pgsql config file missing global section.\n");
465 }
466 if (!(tmp = ast_variable_retrieve(cfg,"global","hostname"))) {
467 ast_log(LOG_WARNING,"PostgreSQL server hostname not specified. Assuming unix socket connection\n");
468 tmp = ""; /* connect via UNIX-socket by default */
469 }
470 if (pghostname)
472 if (!(pghostname = ast_strdup(tmp))) {
473 ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying host info\n");
475 }
476 if (!(tmp = ast_variable_retrieve(cfg, "global", "dbname"))) {
477 ast_log(LOG_WARNING,"PostgreSQL database not specified. Assuming asterisk\n");
478 tmp = "asteriskceldb";
479 }
480 if (pgdbname)
482 if (!(pgdbname = ast_strdup(tmp))) {
483 ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying dbname info\n");
485 }
486 if (!(tmp = ast_variable_retrieve(cfg, "global", "user"))) {
487 ast_log(LOG_WARNING,"PostgreSQL database user not specified. Assuming asterisk\n");
488 tmp = "asterisk";
489 }
490 if (pgdbuser)
492 if (!(pgdbuser = ast_strdup(tmp))) {
493 ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying user info\n");
495 }
496 if (!(tmp = ast_variable_retrieve(cfg, "global", "password"))) {
497 ast_log(LOG_WARNING, "PostgreSQL database password not specified. Assuming blank\n");
498 tmp = "";
499 }
500 if (pgpassword)
502 if (!(pgpassword = ast_strdup(tmp))) {
503 ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying password info\n");
505 }
506 if (!(tmp = ast_variable_retrieve(cfg, "global", "appname"))) {
507 tmp = "";
508 }
509 if (pgappname) {
511 }
512 if (!(pgappname = ast_strdup(tmp))) {
513 ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying appname info\n");
515 }
516
517 if (!(tmp = ast_variable_retrieve(cfg,"global","port"))) {
518 ast_log(LOG_WARNING,"PostgreSQL database port not specified. Using default 5432.\n");
519 tmp = "5432";
520 }
521 if (pgdbport)
523 if (!(pgdbport = ast_strdup(tmp))) {
524 ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying port info\n");
526 }
527 if (!(tmp = ast_variable_retrieve(cfg, "global", "table"))) {
528 ast_log(LOG_WARNING,"CEL table not specified. Assuming cel\n");
529 tmp = "cel";
530 }
531 if (table)
533 if (!(table = ast_strdup(tmp))) {
535 }
537 if ((tmp = ast_variable_retrieve(cfg, "global", "show_user_defined"))) {
538 cel_show_user_def = ast_true(tmp) ? 1 : 0;
539 }
540 if ((tmp = ast_variable_retrieve(cfg, "global", "usegmtime"))) {
542 } else {
543 usegmtime = 0;
544 }
545 if (!(tmp = ast_variable_retrieve(cfg, "global", "schema"))) {
546 tmp = "";
547 }
548 if (schema) {
550 }
551 if (!(schema = ast_strdup(tmp))) {
552 ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying schema info\n");
554 }
555 if (DEBUG_ATLEAST(3)) {
557 ast_log(LOG_DEBUG, "cel_pgsql: using default unix socket\n");
558 } else {
559 ast_log(LOG_DEBUG, "cel_pgsql: got hostname of %s\n", pghostname);
560 }
561 ast_log(LOG_DEBUG, "cel_pgsql: got port of %s\n", pgdbport);
562 ast_log(LOG_DEBUG, "cel_pgsql: got user of %s\n", pgdbuser);
563 ast_log(LOG_DEBUG, "cel_pgsql: got dbname of %s\n", pgdbname);
564 ast_log(LOG_DEBUG, "cel_pgsql: got password of %s\n", pgpassword);
565 ast_log(LOG_DEBUG, "cel_pgsql: got sql table name of %s\n", table);
566 ast_log(LOG_DEBUG, "cel_pgsql: got show_user_defined of %s\n",
567 cel_show_user_def ? "Yes" : "No");
568 }
569
571 if (PQstatus(conn) != CONNECTION_BAD) {
572 char sqlcmd[768];
573 char *fname, *ftype, *flen, *fnotnull, *fdef, *tablename, *tmp_tablename;
574 int i, rows, version;
575
576 ast_debug(1, "Successfully connected to PostgreSQL database.\n");
577 connected = 1;
578
579 version = PQserverVersion(conn);
580 /* Remove any schema name from the table */
581 if ((tmp_tablename = strrchr(table, '.'))) {
582 tmp_tablename++;
583 } else {
584 tmp_tablename = table;
585 }
586 tablename = ast_alloca(strlen(tmp_tablename) * 2 + 1);
587 PQescapeStringConn(conn, tablename, tmp_tablename, strlen(tmp_tablename), NULL);
589 char *schemaname;
590 int lenschema;
591 lenschema = strlen(schema);
592 schemaname = ast_alloca(lenschema * 2 + 1);
593 PQescapeStringConn(conn, schemaname, schema, lenschema, NULL);
594
595 snprintf(sqlcmd, sizeof(sqlcmd),
596 "SELECT a.attname, t.typname, a.attlen, a.attnotnull, pg_catalog.pg_get_expr(d.adbin, d.adrelid) adsrc, a.atttypmod "
597 "FROM (((pg_catalog.pg_class c INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace "
598 "AND c.relname = '%s' AND n.nspname = %s%s%s) "
599 "INNER JOIN pg_catalog.pg_attribute a ON ("
600 "NOT a.attisdropped) AND a.attnum > 0 AND a.attrelid = c.oid) "
601 "INNER JOIN pg_catalog.pg_type t ON t.oid = a.atttypid) "
602 "LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid "
603 "AND d.adnum = a.attnum "
604 "ORDER BY n.nspname, c.relname, attnum",
605 tablename,
606 lenschema == 0 ? "" : "'", lenschema == 0 ? "current_schema()" : schemaname, lenschema == 0 ? "" : "'");
607 } else {
608 snprintf(sqlcmd, sizeof(sqlcmd),
609 "SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod "
610 "FROM pg_class c, pg_type t, pg_attribute a "
611 "LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid "
612 "AND d.adnum = a.attnum WHERE c.oid = a.attrelid AND a.atttypid = t.oid "
613 "AND (a.attnum > 0) AND c.relname = '%s' ORDER BY c.relname, attnum", tablename);
614 }
615 /* Query the columns */
616 result = PQexec(conn, sqlcmd);
617 if (PQresultStatus(result) != PGRES_TUPLES_OK) {
618 pgerror = PQresultErrorMessage(result);
619 ast_log(LOG_ERROR, "Failed to query database columns: %s\n", pgerror);
620 PQclear(result);
623 }
624
625 rows = PQntuples(result);
626 for (i = 0; i < rows; i++) {
627 fname = PQgetvalue(result, i, 0);
628 ftype = PQgetvalue(result, i, 1);
629 flen = PQgetvalue(result, i, 2);
630 fnotnull = PQgetvalue(result, i, 3);
631 fdef = PQgetvalue(result, i, 4);
632 ast_verb(4, "Found column '%s' of type '%s'\n", fname, ftype);
633 cur = ast_calloc(1, sizeof(*cur) + strlen(fname) + strlen(ftype) + 2);
634 if (cur) {
635 sscanf(flen, "%30d", &cur->len);
636 cur->name = (char *)cur + sizeof(*cur);
637 cur->type = (char *)cur + sizeof(*cur) + strlen(fname) + 1;
638 strcpy(cur->name, fname);
639 strcpy(cur->type, ftype);
640 if (*fnotnull == 't') {
641 cur->notnull = 1;
642 } else {
643 cur->notnull = 0;
644 }
645 if (!ast_strlen_zero(fdef)) {
646 cur->hasdefault = 1;
647 } else {
648 cur->hasdefault = 0;
649 }
651 }
652 }
653 PQclear(result);
654 } else {
655 pgerror = PQerrorMessage(conn);
656 ast_log(LOG_ERROR, "cel_pgsql: Unable to connect to database server %s. CALLS WILL NOT BE LOGGED!!\n", pghostname);
657 ast_log(LOG_ERROR, "cel_pgsql: Reason: %s\n", pgerror);
658 connected = 0;
659 PQfinish(conn);
660 conn = NULL;
661 }
663}
#define var
Definition: ast_expr2f.c:605
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
static int tmp()
Definition: bt_open.c:389
#define CEL_SHOW_USERDEF_DEFAULT
show_user_def is off by default
Definition: cel_pgsql.c:76
#define PGSQL_MIN_VERSION_SCHEMA
Definition: cel_pgsql.c:57
static int unload_module(void)
Definition: cel_pgsql.c:449
static char version[AST_MAX_EXTENSION]
Definition: chan_ooh323.c:391
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:783
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
#define ast_verb(level,...)
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:741
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
Structure for variables, used for configurations and for channel variables.
unsigned int hasdefault
Definition: cdr_pgsql.c:94
unsigned int notnull
Definition: cdr_pgsql.c:93

References ast_alloca, ast_calloc, ast_debug, ast_free, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, AST_RWLIST_INSERT_TAIL, ast_strdup, ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, cel_show_user_def, CEL_SHOW_USERDEF_DEFAULT, conn, connected, DEBUG_ATLEAST, columns::hasdefault, columns::len, columns::list, LOG_DEBUG, LOG_ERROR, LOG_WARNING, columns::name, columns::notnull, NULL, pgappname, pgdbname, pgdbport, pgdbuser, pghostname, pgpassword, PGSQL_MIN_VERSION_SCHEMA, pgsql_reconnect(), result, schema, table, tmp(), columns::type, unload_module(), usegmtime, var, and version.

Referenced by my_load_module().

◆ reload()

static int reload ( void  )
static

Definition at line 697 of file cel_pgsql.c.

698{
699 return my_load_module(1);
700}

References my_load_module().

Referenced by my_load_module().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 449 of file cel_pgsql.c.

450{
451 return my_unload_module();
452}

References my_unload_module().

Referenced by process_my_load_module().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PostgreSQL CEL Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, .requires = "cel", }
static

Definition at line 709 of file cel_pgsql.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 709 of file cel_pgsql.c.

◆ cel_show_user_def

unsigned char cel_show_user_def
static

TRUE if we should set the eventtype field to USER_DEFINED on user events.

Definition at line 79 of file cel_pgsql.c.

Referenced by pgsql_log(), and process_my_load_module().

◆ config

char* config = "cel_pgsql.conf"
static

Definition at line 59 of file cel_pgsql.c.

Referenced by my_load_module().

◆ conn

PGconn* conn = NULL
static

Definition at line 83 of file cel_pgsql.c.

Referenced by my_unload_module(), pgsql_log(), pgsql_reconnect(), and process_my_load_module().

◆ connected

int connected = 0
static

Definition at line 70 of file cel_pgsql.c.

Referenced by pgsql_log(), and process_my_load_module().

◆ maxsize

int maxsize = 512
static

Definition at line 72 of file cel_pgsql.c.

Referenced by pgsql_log().

◆ maxsize2

int maxsize2 = 512
static

Definition at line 72 of file cel_pgsql.c.

Referenced by pgsql_log().

◆ pgappname

char* pgappname
static

Definition at line 65 of file cel_pgsql.c.

Referenced by my_unload_module(), pgsql_reconnect(), and process_my_load_module().

◆ pgdbname

char* pgdbname
static

Definition at line 62 of file cel_pgsql.c.

Referenced by my_unload_module(), pgsql_log(), pgsql_reconnect(), and process_my_load_module().

◆ pgdbport

char* pgdbport
static

Definition at line 66 of file cel_pgsql.c.

Referenced by my_unload_module(), pgsql_reconnect(), and process_my_load_module().

◆ pgdbuser

char* pgdbuser
static

Definition at line 63 of file cel_pgsql.c.

Referenced by my_unload_module(), pgsql_log(), pgsql_reconnect(), and process_my_load_module().

◆ pghostname

char* pghostname
static

Definition at line 61 of file cel_pgsql.c.

Referenced by my_unload_module(), pgsql_log(), pgsql_reconnect(), and process_my_load_module().

◆ pgpassword

char* pgpassword
static

Definition at line 64 of file cel_pgsql.c.

Referenced by my_unload_module(), pgsql_log(), pgsql_reconnect(), and process_my_load_module().

◆ pgsql_lock

ast_mutex_t pgsql_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 81 of file cel_pgsql.c.

Referenced by pgsql_log().

◆ psql_columns

struct psql_columns psql_columns = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

◆ result

PGresult* result = NULL
static

Definition at line 84 of file cel_pgsql.c.

Referenced by __ast_channel_alloc(), __ast_string_field_alloc_space(), __astman_get_header(), _pgsql_exec(), acf_meetme_info(), action_updateconfig(), aeap_transaction_end(), ast_app_parse_timelen(), ast_apply_ha(), ast_build_string(), ast_build_string_va(), ast_channel_publish_varset(), ast_config_internal_load(), ast_config_load2(), ast_db_exists(), ast_dns_resolve(), ast_dns_resolve_ipv6_and_ipv4(), ast_dns_result_free(), ast_dns_result_get_answer(), ast_dns_result_get_bogus(), ast_dns_result_get_canonical(), ast_dns_result_get_lowest_ttl(), ast_dns_result_get_rcode(), ast_dns_result_get_records(), ast_dns_result_get_secure(), ast_dnsmgr_get(), ast_dnsmgr_get_family(), ast_dnsmgr_lookup(), ast_dnsmgr_lookup_cb(), ast_format_cap_get_compatible(), ast_format_cap_get_compatible_format(), ast_format_cap_get_format_framing(), ast_geoloc_civicaddr_validate_varlist(), ast_geoloc_eprofile_to_uri(), ast_geoloc_gml_validate_varlist(), ast_geoloc_validate_result_to_str(), ast_get_encoded_char(), ast_get_encoded_str(), ast_gethostbyname(), ast_msg_has_destination(), ast_parse_arg(), ast_privacy_check(), ast_rtp_instance_available_formats(), ast_sip_str_to_dtmf(), ast_sip_str_to_security_mechanism_type(), ast_sip_will_uri_survive_restart(), ast_sockaddr_apply_netmask(), ast_speech_results_free(), ast_str_substitute_variables_full2(), AST_TEST_DEFINE(), ast_translate_available_formats(), ast_websocket_client_create(), ast_websocket_client_create_with_options(), ast_xml_query(), ast_xml_query_with_namespaces(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), blackfilter_cmp_fn(), chan_pjsip_get_codec(), chan_rtp_get_codec(), chat(), check_add_remove_channel(), check_eval(), check_match(), check_translation_path(), cli_complete_registration(), conf_find_bridge_profile(), conf_find_menu_entry_by_sequence(), conf_find_user_profile(), config_module(), config_mysql(), config_pgsql(), configuration_parse_unsigned_integer(), db_get_common(), destroy_pgsql(), detect_callback(), detzcode(), detzcode64(), dial_exec_full(), dns_naptr_sort(), dns_query_recurring_resolution_callback(), dns_srv_sort(), dtmf_to_str(), dundi_lookup(), dundi_lookup_internal(), error(), evaluate_history_entry(), evaluate_like(), fax_detect_framehook(), fax_gateway_attach(), fax_gateway_detect_t38(), fax_gateway_framehook(), fax_gateway_start(), find_result(), find_table(), function_db_keys(), gen_match_to_pattern(), generic_fax_exec(), geoloc_config_cli_reload(), geoloc_config_list_locations(), geoloc_config_list_profiles(), geoloc_config_load(), geoloc_config_show_profiles(), geoloc_location_apply_handler(), geoloc_profile_apply_handler(), getremainingfilelength(), gmtsub(), handle_msg_cb(), handle_results(), handle_speechrecognize(), handle_standard_bridge_enter_message(), handle_updates(), iax2_codec_pref_index(), inform(), internal_dnsmgr_lookup(), invalid_record_test(), launch_ha_netscript(), ldap_loadentry(), lintocodec2_frameout(), lintogsm_frameout(), lintoilbc_frameout(), lintolpc10_frameout(), lintospeex_frameout(), listfilter(), loadresult2str(), localized_config_load(), localized_config_load_with_comments(), localsub(), mallocconcat(), malloccopy(), match_filter(), mwi_thread(), nominal_test(), odbc_datastore_free(), off_nominal_test(), ogg_speex_open(), ogg_vorbis_open(), ooh323_get_codec(), op_func(), P3(), parse_node(), parse_srv(), parsedoublearg(), parsefilearg(), parsefreq(), parseintarg(), parsetime(), parsetimearg(), parsevolarg(), parsevolume(), pgsql_exec(), pgsql_log(), phoneprov_callback(), process_my_load_module(), publish_async_exec_end(), publish_load_message(), publish_reload_message(), radius_log(), read_credentials(), read_mf_digits(), read_packet(), read_sf_digits(), realtime_arguments_to_fields2(), realtime_ldap_base_ap(), realtime_multi_mysql(), realtime_multi_pgsql(), realtime_mysql(), realtime_pgsql(), receivefax_exec(), require_pgsql(), rfcomm_read_and_append_char(), rfcomm_read_and_expect_char(), say(), scan_exec(), sdp_crypto_alloc(), sendfax_exec(), set_id_from_hdr(), sorcery_memory_cache_complete_name(), sorcery_memory_cache_complete_object_name(), sort_result(), speech_grammar(), speech_read(), speech_score(), speech_text(), stasis_message_type_create(), store_pgsql(), t30_phase_e_handler(), test_expected_result(), test_results(), testtime_write(), tmcomp(), transaction_end(), typeof(), tzload(), update2_pgsql(), update_pgsql(), validate_location_info(), wait_exec(), wait_for_answer(), websocket_client_args_create(), websocket_client_create(), and whitefilter_cmp_fn().

◆ schema

char* schema
static

Definition at line 68 of file cel_pgsql.c.

Referenced by load_config(), my_unload_module(), and process_my_load_module().

◆ table

char* table
static

Definition at line 67 of file cel_pgsql.c.

Referenced by my_unload_module(), pgsql_log(), and process_my_load_module().

◆ usegmtime

int usegmtime = 0
static

Definition at line 73 of file cel_pgsql.c.

Referenced by pgsql_log(), and process_my_load_module().