Merge "cel/cel_pgsql.c: Use the 'SEP' macro when appending a column name"
authorJoshua Colp <jcolp@digium.com>
Thu, 14 May 2015 10:02:13 +0000 (05:02 -0500)
committerGerrit Code Review <gerrit2@gerrit.digium.api>
Thu, 14 May 2015 10:02:14 +0000 (05:02 -0500)
CHANGES
Makefile
addons/res_config_mysql.c
apps/app_voicemail.c
cdr/cdr_pgsql.c
cel/cel_pgsql.c
channels/sig_pri.c
configs/samples/cel_pgsql.conf.sample

diff --git a/CHANGES b/CHANGES
index 1609e50..26bcb49 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -159,6 +159,10 @@ cel_pgsql
  * Added a new option, 'usegmtime', which causes timestamps in CEL events
    to be logged in GMT.
 
+ * Added support to set schema where located the table cel. This settings is
+   configurable for cel_pgsql via the 'schema' in configuration file
+   cel_pgsql.conf.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.3.0 to Asterisk 13.4.0 ------------
 ------------------------------------------------------------------------------
index 17a2551..7157107 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -941,7 +941,7 @@ nmenuselect: menuselect/nmenuselect menuselect-tree menuselect.makeopts
        -@menuselect/nmenuselect menuselect.makeopts && (echo "menuselect changes saved!"; rm -f channels/h323/Makefile.ast main/asterisk) || echo "menuselect changes NOT saved!"
 
 # options for make in menuselect/
-MAKE_MENUSELECT=CC="$(CC)" CXX="$(CXX)" LD="" AR="" RANLIB="" \
+MAKE_MENUSELECT=CC="$(BUILD_CC)" CXX="$(CXX)" LD="" AR="" RANLIB="" \
                CFLAGS="$(BUILD_CFLAGS)" LDFLAGS="$(BUILD_LDFLAGS)" \
                $(MAKE) -C menuselect CONFIGURE_SILENT="--silent"
 
index 299fe56..76bdeed 100644 (file)
@@ -1202,38 +1202,44 @@ static int require_mysql(const char *database, const char *tablename, va_list ap
                                                        PICK_WHICH_ALTER_ACTION(bigint)
                                                }
                                        }
-                               } else if (strncmp(column->type, "float", 5) == 0 && !ast_rq_is_int(type) && type != RQ_FLOAT) {
-                                       if (table->database->requirements == RQ_WARN) {
-                                               ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type);
-                                               res = -1;
-                                       } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) {
-                                               table_altered = 1;
-                                       } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) {
-                                               table_altered = 1;
-                                       } else {
-                                               res = -1;
+                               } else if (strncmp(column->type, "float", 5) == 0) {
+                                       if (!ast_rq_is_int(type) && type != RQ_FLOAT) {
+                                               if (table->database->requirements == RQ_WARN) {
+                                                       ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type);
+                                                       res = -1;
+                                               } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) {
+                                                       table_altered = 1;
+                                               } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) {
+                                                       table_altered = 1;
+                                               } else {
+                                                       res = -1;
+                                               }
                                        }
-                               } else if ((strncmp(column->type, "datetime", 8) == 0 || strncmp(column->type, "timestamp", 9) == 0) && type != RQ_DATETIME) {
-                                       if (table->database->requirements == RQ_WARN) {
-                                               ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type);
-                                               res = -1;
-                                       } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) {
-                                               table_altered = 1;
-                                       } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) {
-                                               table_altered = 1;
-                                       } else {
-                                               res = -1;
+                               } else if (strncmp(column->type, "datetime", 8) == 0 || strncmp(column->type, "timestamp", 9) == 0) {
+                                       if (type != RQ_DATETIME) {
+                                               if (table->database->requirements == RQ_WARN) {
+                                                       ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type);
+                                                       res = -1;
+                                               } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) {
+                                                       table_altered = 1;
+                                               } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) {
+                                                       table_altered = 1;
+                                               } else {
+                                                       res = -1;
+                                               }
                                        }
-                               } else if ((strncmp(column->type, "date", 4) == 0) && type != RQ_DATE) {
-                                       if (table->database->requirements == RQ_WARN) {
-                                               ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type);
-                                               res = -1;
-                                       } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) {
-                                               table_altered = 1;
-                                       } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) {
-                                               table_altered = 1;
-                                       } else {
-                                               res = -1;
+                               } else if (strncmp(column->type, "date", 4) == 0) {
+                                       if (type != RQ_DATE) {
+                                               if (table->database->requirements == RQ_WARN) {
+                                                       ast_log(LOG_WARNING, "Realtime table %s@%s: Column %s cannot be a %s\n", tablename, database, column->name, column->type);
+                                                       res = -1;
+                                               } else if (table->database->requirements == RQ_CREATECLOSE && modify_mysql(database, tablename, column, type, size) == 0) {
+                                                       table_altered = 1;
+                                               } else if (table->database->requirements == RQ_CREATECHAR && modify_mysql(database, tablename, column, RQ_CHAR, size) == 0) {
+                                                       table_altered = 1;
+                                               } else {
+                                                       res = -1;
+                                               }
                                        }
                                } else { /* Other, possibly unsupported types? */
                                        if (table->database->requirements == RQ_WARN) {
index 532275e..3ea8fa5 100644 (file)
@@ -617,6 +617,7 @@ static AST_LIST_HEAD_STATIC(vmstates, vmstate);
 #define VM_MESSAGEWRAP   (1 << 17)  /*!< Wrap around from the last message to the first, and vice-versa */
 #define VM_FWDURGAUTO    (1 << 18)  /*!< Autoset of Urgent flag on forwarded Urgent messages set globally */
 #define ERROR_LOCK_PATH  -100
+#define ERROR_MAX_MSGS   -101
 #define OPERATOR_EXIT     300
 
 enum vm_box {
@@ -7093,7 +7094,7 @@ static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg
        } else {
                if (x >= vmu->maxmsg) {
                        ast_unlock_path(ddir);
-                       return -1;
+                       return ERROR_MAX_MSGS;
                }
        }
        make_file(sfn, sizeof(sfn), dir, msg);
@@ -8918,7 +8919,7 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
                } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) {
                        /* Move to old folder before deleting */
                        res = save_to_folder(vmu, vms, x, 1, NULL, 0);
-                       if (res == ERROR_LOCK_PATH) {
+                       if (res == ERROR_LOCK_PATH || res == ERROR_MAX_MSGS) {
                                /* If save failed do not delete the message */
                                ast_log(AST_LOG_WARNING, "Save failed.  Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full");
                                vms->deleted[x] = 0;
index fb069ee..37bc084 100644 (file)
@@ -75,6 +75,7 @@ static char *encoding;
 static char *tz;
 
 static int connected = 0;
+/* Optimization to reduce number of memory allocations */
 static int maxsize = 512, maxsize2 = 512;
 static time_t connect_time = 0;
 static int totalrecords = 0;
@@ -453,6 +454,15 @@ static int pgsql_log(struct ast_cdr *cdr)
                        records++;
                }
                PQclear(result);
+
+               /* Next time, just allocate buffers that are that big to start with. */
+               if (ast_str_strlen(sql) > maxsize) {
+                       maxsize = ast_str_strlen(sql);
+               }
+               if (ast_str_strlen(sql2) > maxsize2) {
+                       maxsize2 = ast_str_strlen(sql2);
+               }
+
                ast_free(sql);
                ast_free(sql2);
        }
index bc76b27..f495947 100644 (file)
@@ -60,6 +60,8 @@ ASTERISK_REGISTER_FILE()
 
 #define PGSQL_BACKEND_NAME "CEL PGSQL backend"
 
+#define PGSQL_MIN_VERSION_SCHEMA 70300
+
 static char *config = "cel_pgsql.conf";
 
 static char *pghostname;
@@ -69,8 +71,10 @@ static char *pgpassword;
 static char *pgappname;
 static char *pgdbport;
 static char *table;
+static char *schema;
 
 static int connected = 0;
+/* Optimization to reduce number of memory allocations */
 static int maxsize = 512, maxsize2 = 512;
 static int usegmtime = 0;
 
@@ -372,6 +376,14 @@ static void pgsql_log(struct ast_event *event)
                }
                PQclear(result);
 
+               /* Next time, just allocate buffers that are that big to start with. */
+               if (ast_str_strlen(sql) > maxsize) {
+                       maxsize = ast_str_strlen(sql);
+               }
+               if (ast_str_strlen(sql2) > maxsize2) {
+                       maxsize2 = ast_str_strlen(sql2);
+               }
+
 ast_log_cleanup:
                ast_free(sql);
                ast_free(sql2);
@@ -418,6 +430,10 @@ static int my_unload_module(void)
                ast_free(table);
                table = NULL;
        }
+       if (schema) {
+               ast_free(schema);
+               schema = NULL;
+       }
        while ((current = AST_RWLIST_REMOVE_HEAD(&psql_columns, list))) {
                ast_free(current);
        }
@@ -521,6 +537,16 @@ static int process_my_load_module(struct ast_config *cfg)
        } else {
                usegmtime = 0;
        }
+       if (!(tmp = ast_variable_retrieve(cfg, "global", "schema"))) {
+               tmp = "";
+       }
+       if (schema) {
+               ast_free(schema);
+       }
+       if (!(schema = ast_strdup(tmp))) {
+               ast_log(LOG_WARNING,"PostgreSQL Ran out of memory copying schema info\n");
+               return AST_MODULE_LOAD_DECLINE;
+       }
        if (option_debug) {
                if (ast_strlen_zero(pghostname)) {
                        ast_debug(3, "cel_pgsql: using default unix socket\n");
@@ -538,23 +564,50 @@ static int process_my_load_module(struct ast_config *cfg)
 
        pgsql_reconnect();
        if (PQstatus(conn) != CONNECTION_BAD) {
-               char sqlcmd[512];
-               char *fname, *ftype, *flen, *fnotnull, *fdef;
-               char *tableptr;
-               int i, rows;
+               char sqlcmd[768];
+               char *fname, *ftype, *flen, *fnotnull, *fdef, *tablename, *tmp_tablename;
+               int i, rows, version;
 
                ast_debug(1, "Successfully connected to PostgreSQL database.\n");
                connected = 1;
 
+               version = PQserverVersion(conn);
                /* Remove any schema name from the table */
-               if ((tableptr = strrchr(table, '.'))) {
-                       tableptr++;
+               if ((tmp_tablename = strrchr(table, '.'))) {
+                       tmp_tablename++;
                } else {
-                       tableptr = table;
+                       tmp_tablename = table;
+               }
+               tablename = ast_alloca(strlen(tmp_tablename) * 2 + 1);
+               PQescapeStringConn(conn, tablename, tmp_tablename, strlen(tmp_tablename), NULL);
+               if (version >= PGSQL_MIN_VERSION_SCHEMA) {
+                       char *schemaname;
+                       int lenschema;
+                       lenschema = strlen(schema);
+                       schemaname = ast_alloca(lenschema * 2 + 1);
+                       PQescapeStringConn(conn, schemaname, schema, lenschema, NULL);
+
+                       snprintf(sqlcmd, sizeof(sqlcmd),
+                       "SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod "
+                       "FROM (((pg_catalog.pg_class c INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace "
+                                "AND c.relname = '%s' AND n.nspname = %s%s%s) "
+                              "INNER JOIN pg_catalog.pg_attribute a ON ("
+                                  "NOT a.attisdropped) AND a.attnum > 0 AND a.attrelid = c.oid) "
+                           "INNER JOIN pg_catalog.pg_type t ON t.oid = a.atttypid) "
+                       "LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid "
+                         "AND d.adnum = a.attnum "
+                       "ORDER BY n.nspname, c.relname, attnum",
+                               tablename,
+                               lenschema == 0 ? "" : "'", lenschema == 0 ? "current_schema()" : schemaname, lenschema == 0 ? "" : "'");
+               } else {
+                       snprintf(sqlcmd, sizeof(sqlcmd),
+                       "SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod "
+                       "FROM pg_class c, pg_type t, pg_attribute a "
+                       "LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid "
+                       "AND d.adnum = a.attnum WHERE c.oid = a.attrelid AND a.atttypid = t.oid "
+                       "AND (a.attnum > 0) AND c.relname = '%s' ORDER BY c.relname, attnum", tablename);
                }
-
                /* Query the columns */
-               snprintf(sqlcmd, sizeof(sqlcmd), "select a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc from pg_class c, pg_type t, pg_attribute a left outer join pg_attrdef d on a.atthasdef and d.adrelid = a.attrelid and d.adnum = a.attnum where c.oid = a.attrelid and a.atttypid = t.oid and (a.attnum > 0) and c.relname = '%s' order by c.relname, attnum", tableptr);
                result = PQexec(conn, sqlcmd);
                if (PQresultStatus(result) != PGRES_TUPLES_OK) {
                        pgerror = PQresultErrorMessage(result);
index c58a3f3..71e7e23 100644 (file)
@@ -7090,10 +7090,11 @@ static void *pri_dchannel(void *vpri)
                                                break;
                                        }
                                        if (pri->pvts[chanpos]->owner) {
-                                               int do_hangup = 0;
-
                                                snprintf(cause_str, sizeof(cause_str), "PRI PRI_EVENT_HANGUP (%d)", e->hangup.cause);
                                                pri_queue_pvt_cause_data(pri, chanpos, cause_str, e->hangup.cause);
+                                       }
+                                       if (pri->pvts[chanpos]->owner) {
+                                               int do_hangup = 0;
 
                                                /* Queue a BUSY instead of a hangup if our cause is appropriate */
                                                ast_channel_hangupcause_set(pri->pvts[chanpos]->owner, e->hangup.cause);
@@ -7234,10 +7235,11 @@ static void *pri_dchannel(void *vpri)
                                        break;
                                }
                                if (pri->pvts[chanpos]->owner) {
-                                       int do_hangup = 0;
-
                                        snprintf(cause_str, sizeof(cause_str), "PRI PRI_EVENT_HANGUP_REQ (%d)", e->hangup.cause);
                                        pri_queue_pvt_cause_data(pri, chanpos, cause_str, e->hangup.cause);
+                               }
+                               if (pri->pvts[chanpos]->owner) {
+                                       int do_hangup = 0;
 
                                        ast_channel_hangupcause_set(pri->pvts[chanpos]->owner, e->hangup.cause);
                                        switch (ast_channel_state(pri->pvts[chanpos]->owner)) {
index 30c789e..13fe069 100644 (file)
@@ -68,4 +68,6 @@
 ;password=password
 ;user=postgres
 ;table=cel             ;SQL table where CEL's will be inserted
+;schema=public ;Schema where CEL's table is located.  Optional parameter.
+               ;If schema support is present the default value used will be current_schema().
 ;appname=asterisk   ; Postgres application_name support (optional). Whitespace not allowed.