Asterisk - The Open Source Telephony Project  GIT-master-a24979a
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 
682  ast_config_destroy(cfg);
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:1740
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.
@ CONFIG_FLAG_FILEUNCHANGED
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
#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().

◆ 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) {
412  pghostname = NULL;
413  }
414  if (pgdbname) {
416  pgdbname = NULL;
417  }
418  if (pgdbuser) {
420  pgdbuser = NULL;
421  }
422  if (pgpassword) {
424  pgpassword = NULL;
425  }
426  if (pgappname) {
428  pgappname = NULL;
429  }
430  if (pgdbport) {
432  pgdbport = NULL;
433  }
434  if (table) {
435  ast_free(table);
436  table = NULL;
437  }
438  if (schema) {
439  ast_free(schema);
440  schema = NULL;
441  }
443  ast_free(current);
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:1728
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) {
164  pgsql_reconnect();
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 
391 ast_log_cleanup:
392  ast_free(sql);
393  ast_free(sql2);
394  ast_free(escapebuf);
395  }
396 
398 }
struct sla_ringing_trunk * first
Definition: app_meetme.c:1094
#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:819
#define AST_CEL_EVENT_RECORD_VERSION
struct ABI version
Definition: cel.h:141
#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
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
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
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define ast_mutex_lock(a)
Definition: lock.h:187
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:1117
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:739
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:640
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:1091
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:711
Helper struct for getting the fields out of a CEL event.
Definition: cel.h:136
const char * caller_id_dnid
Definition: cel.h:155
const char * application_data
Definition: cel.h:160
const char * account_code
Definition: cel.h:161
const char * caller_id_rdnis
Definition: cel.h:154
const char * extra
Definition: cel.h:168
const char * extension
Definition: cel.h:156
const char * caller_id_num
Definition: cel.h:152
const char * channel_name
Definition: cel.h:158
const char * linked_id
Definition: cel.h:164
const char * peer_account
Definition: cel.h:162
const char * peer
Definition: cel.h:167
enum ast_cel_event_type event_type
Definition: cel.h:147
const char * unique_id
Definition: cel.h:163
const char * user_defined_name
Definition: cel.h:150
const char * context
Definition: cel.h:157
const char * application_name
Definition: cel.h:159
struct timeval event_time
Definition: cel.h:148
uint32_t version
struct ABI version
Definition: cel.h:146
const char * user_field
Definition: cel.h:166
const char * caller_id_ani
Definition: cel.h:153
const char * caller_id_name
Definition: cel.h:151
const char * event_name
Definition: cel.h:149
Support for dynamic strings.
Definition: strings.h:604
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 
132  if (!ast_strlen_zero(pgappname)) {
133  ast_str_append(&conn_info, 0, " application_name=%s", pgappname);
134  }
135 
136  if (!ast_strlen_zero(pgpassword)) {
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)
532  ast_free(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) {
549  ast_free(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 
570  pgsql_reconnect();
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);
621  unload_module();
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:614
#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:768
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: main/utils.c:2097
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 }

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 697 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(), agi_handle_command(), ast_app_parse_timelen(), ast_build_string(), ast_build_string_va(), ast_config_internal_load(), ast_config_load2(), 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_get_encoded_char(), ast_get_encoded_str(), ast_gethostbyname(), ast_mktime(), ast_module_reload(), ast_msg_has_destination(), ast_parse_arg(), ast_privacy_check(), ast_rtp_instance_available_formats(), ast_sip_str_to_dtmf(), ast_sip_will_uri_survive_restart(), ast_sockaddr_apply_netmask(), ast_speech_results_free(), ast_stir_shaken_add_verification(), 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(), chat(), check_add_remove_channel(), check_eval(), check_match(), check_sip_domain(), check_translation_path(), cli_complete_registration(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), conf_find_bridge_profile(), conf_find_menu_entry_by_sequence(), conf_find_user_profile(), config_module(), config_mysql(), config_pgsql(), configuration_parse_unsigned_integer(), cops_connect(), 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(), fax_detect_framehook(), fax_gateway_attach(), fax_gateway_detect_t38(), fax_gateway_framehook(), fax_gateway_start(), find_result(), find_table(), gen_match_to_pattern(), generic_fax_exec(), getremainingfilelength(), gmtsub(), handle_request_invite(), handle_response(), handle_results(), handle_standard_bridge_enter_message(), iax2_codec_pref_index(), inform(), internal_dnsmgr_lookup(), ldap_loadentry(), lintocodec2_frameout(), lintogsm_frameout(), lintolpc10_frameout(), lintospeex_frameout(), listfilter(), loadresult2str(), localized_config_load(), localized_config_load_with_comments(), localsub(), mallocconcat(), malloccopy(), match_filter(), mgcp_get_codec(), mgcpsock_read(), mwi_thread(), odbc_datastore_free(), ogg_speex_open(), ogg_vorbis_open(), ooh323_get_codec(), op_func(), P3(), parse_srv(), parsedoublearg(), parsefilearg(), parsefreq(), parseintarg(), parsetime(), parsetimearg(), parsevolarg(), parsevolume(), pgsql_exec(), pgsql_log(), phoneprov_callback(), process_my_load_module(), publish_load_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(), sdp_crypto_alloc(), sendfax_exec(), sip_get_codec(), sip_report_security_event(), sorcery_memory_cache_complete_name(), sorcery_memory_cache_complete_object_name(), sort_result(), speech_grammar(), speech_score(), speech_text(), stasis_message_type_create(), stir_shaken_verification_result_to_string(), store_pgsql(), t30_phase_e_handler(), test_results(), transaction_end(), typeof(), tzload(), update2_pgsql(), update_pgsql(), 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().