mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 20:20:07 +00:00
Handle numeric columns for eventtype properly in cel_odbc
Patch also implements correct handling of datetime2 and datetimeoffset new datatypes in SQL Server 2008 and 2008 R2. (closes issue ASTERISK-17548) Review: https://reviewboard.asterisk.org/r/1160/ Review: https://reviewboard.asterisk.org/r/1804/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@358576 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
180
cel/cel_odbc.c
180
cel/cel_odbc.c
@@ -80,6 +80,7 @@ struct tables {
|
|||||||
char *connection;
|
char *connection;
|
||||||
char *table;
|
char *table;
|
||||||
unsigned int usegmtime:1;
|
unsigned int usegmtime:1;
|
||||||
|
unsigned int allowleapsec:1;
|
||||||
AST_LIST_HEAD_NOLOCK(odbc_columns, columns) columns;
|
AST_LIST_HEAD_NOLOCK(odbc_columns, columns) columns;
|
||||||
AST_RWLIST_ENTRY(tables) list;
|
AST_RWLIST_ENTRY(tables) list;
|
||||||
};
|
};
|
||||||
@@ -97,7 +98,7 @@ static int load_config(void)
|
|||||||
char columnname[80];
|
char columnname[80];
|
||||||
char connection[40];
|
char connection[40];
|
||||||
char table[40];
|
char table[40];
|
||||||
int lenconnection, lentable, usegmtime = 0;
|
int lenconnection, lentable;
|
||||||
SQLLEN sqlptr;
|
SQLLEN sqlptr;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
SQLHSTMT stmt = NULL;
|
SQLHSTMT stmt = NULL;
|
||||||
@@ -134,10 +135,6 @@ static int load_config(void)
|
|||||||
ast_copy_string(connection, tmp, sizeof(connection));
|
ast_copy_string(connection, tmp, sizeof(connection));
|
||||||
lenconnection = strlen(connection);
|
lenconnection = strlen(connection);
|
||||||
|
|
||||||
if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg, catg, "usegmtime"))) {
|
|
||||||
usegmtime = ast_true(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When loading, we want to be sure we can connect. */
|
/* When loading, we want to be sure we can connect. */
|
||||||
obj = ast_odbc_request_obj(connection, 1);
|
obj = ast_odbc_request_obj(connection, 1);
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
@@ -174,12 +171,21 @@ static int load_config(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
tableptr->usegmtime = usegmtime;
|
|
||||||
tableptr->connection = (char *)tableptr + sizeof(*tableptr);
|
tableptr->connection = (char *)tableptr + sizeof(*tableptr);
|
||||||
tableptr->table = (char *)tableptr + sizeof(*tableptr) + lenconnection + 1;
|
tableptr->table = (char *)tableptr + sizeof(*tableptr) + lenconnection + 1;
|
||||||
ast_copy_string(tableptr->connection, connection, lenconnection + 1);
|
ast_copy_string(tableptr->connection, connection, lenconnection + 1);
|
||||||
ast_copy_string(tableptr->table, table, lentable + 1);
|
ast_copy_string(tableptr->table, table, lentable + 1);
|
||||||
|
|
||||||
|
tableptr->usegmtime = 0;
|
||||||
|
if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg, catg, "usegmtime"))) {
|
||||||
|
tableptr->usegmtime = ast_true(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
tableptr->allowleapsec = 1;
|
||||||
|
if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg, catg, "allowleapsecond"))) {
|
||||||
|
tableptr->allowleapsec = ast_true(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
ast_verb(3, "Found CEL table %s@%s.\n", tableptr->table, tableptr->connection);
|
ast_verb(3, "Found CEL table %s@%s.\n", tableptr->table, tableptr->connection);
|
||||||
|
|
||||||
/* Check for filters first */
|
/* Check for filters first */
|
||||||
@@ -407,6 +413,7 @@ static void odbc_log(const struct ast_event *event, void *userdata)
|
|||||||
|
|
||||||
AST_LIST_TRAVERSE(&(tableptr->columns), entry, list) {
|
AST_LIST_TRAVERSE(&(tableptr->columns), entry, list) {
|
||||||
int datefield = 0;
|
int datefield = 0;
|
||||||
|
int unknown = 0;
|
||||||
if (strcasecmp(entry->celname, "eventtime") == 0) {
|
if (strcasecmp(entry->celname, "eventtime") == 0) {
|
||||||
datefield = 1;
|
datefield = 1;
|
||||||
}
|
}
|
||||||
@@ -418,7 +425,17 @@ static void odbc_log(const struct ast_event *event, void *userdata)
|
|||||||
struct timeval date_tv = record.event_time;
|
struct timeval date_tv = record.event_time;
|
||||||
struct ast_tm tm = { 0, };
|
struct ast_tm tm = { 0, };
|
||||||
ast_localtime(&date_tv, &tm, tableptr->usegmtime ? "UTC" : NULL);
|
ast_localtime(&date_tv, &tm, tableptr->usegmtime ? "UTC" : NULL);
|
||||||
ast_strftime(colbuf, sizeof(colbuf), "%Y-%m-%d %H:%M:%S", &tm);
|
/* SQL server 2008 added datetime2 and datetimeoffset data types, that
|
||||||
|
are reported to SQLColumns() as SQL_WVARCHAR, according to "Enhanced
|
||||||
|
Date/Time Type Behavior with Previous SQL Server Versions (ODBC)".
|
||||||
|
Here we format the event time with fraction seconds, so these new
|
||||||
|
column types will be set to high-precision event time. However, 'date'
|
||||||
|
and 'time' columns, also newly introduced, reported as SQL_WVARCHAR
|
||||||
|
too, and insertion of the value formatted here into these will fail.
|
||||||
|
This should be ok, however, as nobody is going to store just event
|
||||||
|
date or just time for CDR purposes.
|
||||||
|
*/
|
||||||
|
ast_strftime(colbuf, sizeof(colbuf), "%Y-%m-%d %H:%M:%S.%q", &tm);
|
||||||
colptr = colbuf;
|
colptr = colbuf;
|
||||||
} else {
|
} else {
|
||||||
if (strcmp(entry->celname, "userdeftype") == 0) {
|
if (strcmp(entry->celname, "userdeftype") == 0) {
|
||||||
@@ -459,13 +476,16 @@ static void odbc_log(const struct ast_event *event, void *userdata)
|
|||||||
snprintf(colbuf, sizeof(colbuf), "%d", record.amaflag);
|
snprintf(colbuf, sizeof(colbuf), "%d", record.amaflag);
|
||||||
} else if (strcmp(entry->celname, "extra") == 0) {
|
} else if (strcmp(entry->celname, "extra") == 0) {
|
||||||
ast_copy_string(colbuf, record.extra, sizeof(colbuf));
|
ast_copy_string(colbuf, record.extra, sizeof(colbuf));
|
||||||
|
} else if (strcmp(entry->celname, "eventtype") == 0) {
|
||||||
|
snprintf(colbuf, sizeof(colbuf), "%d", record.event_type);
|
||||||
} else {
|
} else {
|
||||||
colbuf[0] = 0;
|
colbuf[0] = 0;
|
||||||
|
unknown = 1;
|
||||||
}
|
}
|
||||||
colptr = colbuf;
|
colptr = colbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colptr) {
|
if (colptr && !unknown) {
|
||||||
/* Check first if the column filters this entry. Note that this
|
/* Check first if the column filters this entry. Note that this
|
||||||
* is very specifically NOT ast_strlen_zero(), because the filter
|
* is very specifically NOT ast_strlen_zero(), because the filter
|
||||||
* could legitimately specify that the field is blank, which is
|
* could legitimately specify that the field is blank, which is
|
||||||
@@ -536,24 +556,32 @@ static void odbc_log(const struct ast_event *event, void *userdata)
|
|||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
int year = 0, month = 0, day = 0;
|
int year = 0, month = 0, day = 0;
|
||||||
if (sscanf(colptr, "%4d-%2d-%2d", &year, &month, &day) != 3 || year <= 0 ||
|
if (strcasecmp(entry->name, "eventdate") == 0) {
|
||||||
month <= 0 || month > 12 || day < 0 || day > 31 ||
|
struct ast_tm tm;
|
||||||
((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) ||
|
ast_localtime(&record.event_time, &tm, tableptr->usegmtime ? "UTC" : NULL);
|
||||||
(month == 2 && year % 400 == 0 && day > 29) ||
|
year = tm.tm_year + 1900;
|
||||||
(month == 2 && year % 100 == 0 && day > 28) ||
|
month = tm.tm_mon + 1;
|
||||||
(month == 2 && year % 4 == 0 && day > 29) ||
|
day = tm.tm_mday;
|
||||||
(month == 2 && year % 4 != 0 && day > 28)) {
|
} else {
|
||||||
ast_log(LOG_WARNING, "CEL variable %s is not a valid date ('%s').\n", entry->name, colptr);
|
if (sscanf(colptr, "%4d-%2d-%2d", &year, &month, &day) != 3 || year <= 0 ||
|
||||||
continue;
|
month <= 0 || month > 12 || day < 0 || day > 31 ||
|
||||||
}
|
((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) ||
|
||||||
|
(month == 2 && year % 400 == 0 && day > 29) ||
|
||||||
|
(month == 2 && year % 100 == 0 && day > 28) ||
|
||||||
|
(month == 2 && year % 4 == 0 && day > 29) ||
|
||||||
|
(month == 2 && year % 4 != 0 && day > 28)) {
|
||||||
|
ast_log(LOG_WARNING, "CEL variable %s is not a valid date ('%s').\n", entry->name, colptr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (year > 0 && year < 100) {
|
if (year > 0 && year < 100) {
|
||||||
year += 2000;
|
year += 2000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
|
ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
|
||||||
LENGTHEN_BUF2(17);
|
LENGTHEN_BUF2(17);
|
||||||
ast_str_append(&sql2, 0, "%s{ d '%04d-%02d-%02d' }", first ? "" : ",", year, month, day);
|
ast_str_append(&sql2, 0, "%s{d '%04d-%02d-%02d'}", first ? "" : ",", year, month, day);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SQL_TYPE_TIME:
|
case SQL_TYPE_TIME:
|
||||||
@@ -561,16 +589,24 @@ static void odbc_log(const struct ast_event *event, void *userdata)
|
|||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
int hour = 0, minute = 0, second = 0;
|
int hour = 0, minute = 0, second = 0;
|
||||||
int count = sscanf(colptr, "%2d:%2d:%2d", &hour, &minute, &second);
|
if (strcasecmp(entry->name, "eventdate") == 0) {
|
||||||
|
struct ast_tm tm;
|
||||||
|
ast_localtime(&record.event_time, &tm, tableptr->usegmtime ? "UTC" : NULL);
|
||||||
|
hour = tm.tm_hour;
|
||||||
|
minute = tm.tm_min;
|
||||||
|
second = (tableptr->allowleapsec || tm.tm_sec < 60) ? tm.tm_sec : 59;
|
||||||
|
} else {
|
||||||
|
int count = sscanf(colptr, "%2d:%2d:%2d", &hour, &minute, &second);
|
||||||
|
|
||||||
if ((count != 2 && count != 3) || hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) {
|
if ((count != 2 && count != 3) || hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > (tableptr->allowleapsec ? 60 : 59)) {
|
||||||
ast_log(LOG_WARNING, "CEL variable %s is not a valid time ('%s').\n", entry->name, colptr);
|
ast_log(LOG_WARNING, "CEL variable %s is not a valid time ('%s').\n", entry->name, colptr);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
|
ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
|
||||||
LENGTHEN_BUF2(15);
|
LENGTHEN_BUF2(15);
|
||||||
ast_str_append(&sql2, 0, "%s{ t '%02d:%02d:%02d' }", first ? "" : ",", hour, minute, second);
|
ast_str_append(&sql2, 0, "%s{t '%02d:%02d:%02d'}", first ? "" : ",", hour, minute, second);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SQL_TYPE_TIMESTAMP:
|
case SQL_TYPE_TIMESTAMP:
|
||||||
@@ -579,37 +615,44 @@ static void odbc_log(const struct ast_event *event, void *userdata)
|
|||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;
|
int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;
|
||||||
int count = sscanf(colptr, "%4d-%2d-%2d %2d:%2d:%2d", &year, &month, &day, &hour, &minute, &second);
|
if (strcasecmp(entry->name, "eventdate") == 0) {
|
||||||
|
struct ast_tm tm;
|
||||||
|
ast_localtime(&record.event_time, &tm, tableptr->usegmtime ? "UTC" : NULL);
|
||||||
|
year = tm.tm_year + 1900;
|
||||||
|
month = tm.tm_mon + 1;
|
||||||
|
day = tm.tm_mday;
|
||||||
|
hour = tm.tm_hour;
|
||||||
|
minute = tm.tm_min;
|
||||||
|
second = (tableptr->allowleapsec || tm.tm_sec < 60) ? tm.tm_sec : 59;
|
||||||
|
} else {
|
||||||
|
int count = sscanf(colptr, "%4d-%2d-%2d %2d:%2d:%2d", &year, &month, &day, &hour, &minute, &second);
|
||||||
|
|
||||||
if ((count != 3 && count != 5 && count != 6) || year <= 0 ||
|
if ((count != 3 && count != 5 && count != 6) || year <= 0 ||
|
||||||
month <= 0 || month > 12 || day < 0 || day > 31 ||
|
month <= 0 || month > 12 || day < 0 || day > 31 ||
|
||||||
((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) ||
|
((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) ||
|
||||||
(month == 2 && year % 400 == 0 && day > 29) ||
|
(month == 2 && year % 400 == 0 && day > 29) ||
|
||||||
(month == 2 && year % 100 == 0 && day > 28) ||
|
(month == 2 && year % 100 == 0 && day > 28) ||
|
||||||
(month == 2 && year % 4 == 0 && day > 29) ||
|
(month == 2 && year % 4 == 0 && day > 29) ||
|
||||||
(month == 2 && year % 4 != 0 && day > 28) ||
|
(month == 2 && year % 4 != 0 && day > 28) ||
|
||||||
hour > 23 || minute > 59 || second > 59 || hour < 0 || minute < 0 || second < 0) {
|
hour > 23 || minute > 59 || second > (tableptr->allowleapsec ? 60 : 59) || hour < 0 || minute < 0 || second < 0) {
|
||||||
ast_log(LOG_WARNING, "CEL variable %s is not a valid timestamp ('%s').\n", entry->name, colptr);
|
ast_log(LOG_WARNING, "CEL variable %s is not a valid timestamp ('%s').\n", entry->name, colptr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (year > 0 && year < 100) {
|
if (year > 0 && year < 100) {
|
||||||
year += 2000;
|
year += 2000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
|
ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
|
||||||
LENGTHEN_BUF2(26);
|
LENGTHEN_BUF2(27);
|
||||||
ast_str_append(&sql2, 0, "%s{ ts '%04d-%02d-%02d %02d:%02d:%02d' }", first ? "" : ",", year, month, day, hour, minute, second);
|
ast_str_append(&sql2, 0, "%s{ts '%04d-%02d-%02d %02d:%02d:%02d'}", first ? "" : ",", year, month, day, hour, minute, second);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SQL_INTEGER:
|
case SQL_INTEGER:
|
||||||
{
|
{
|
||||||
int integer = 0;
|
int integer = 0;
|
||||||
if (strcasecmp(entry->name, "eventtype") == 0) {
|
if (sscanf(colptr, "%30d", &integer) != 1) {
|
||||||
integer = (int) record.event_type;
|
|
||||||
} else if (ast_strlen_zero(colptr)) {
|
|
||||||
continue;
|
|
||||||
} else if (sscanf(colptr, "%30d", &integer) != 1) {
|
|
||||||
ast_log(LOG_WARNING, "CEL variable %s is not an integer.\n", entry->name);
|
ast_log(LOG_WARNING, "CEL variable %s is not an integer.\n", entry->name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -622,12 +665,9 @@ static void odbc_log(const struct ast_event *event, void *userdata)
|
|||||||
case SQL_BIGINT:
|
case SQL_BIGINT:
|
||||||
{
|
{
|
||||||
long long integer = 0;
|
long long integer = 0;
|
||||||
if (strcasecmp(entry->name, "eventtype") == 0) {
|
int ret;
|
||||||
integer = (long long) record.event_type;
|
if ((ret = sscanf(colptr, "%30lld", &integer)) != 1) {
|
||||||
} else if (ast_strlen_zero(colptr)) {
|
ast_log(LOG_WARNING, "CEL variable %s is not an integer. (%d - '%s')\n", entry->name, ret, colptr);
|
||||||
continue;
|
|
||||||
} else if (sscanf(colptr, "%30lld", &integer) != 1) {
|
|
||||||
ast_log(LOG_WARNING, "CEL variable %s is not an integer.\n", entry->name);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,28 +679,20 @@ static void odbc_log(const struct ast_event *event, void *userdata)
|
|||||||
case SQL_SMALLINT:
|
case SQL_SMALLINT:
|
||||||
{
|
{
|
||||||
short integer = 0;
|
short integer = 0;
|
||||||
if (strcasecmp(entry->name, "eventtype") == 0) {
|
if (sscanf(colptr, "%30hd", &integer) != 1) {
|
||||||
integer = (short) record.event_type;
|
|
||||||
} else if (ast_strlen_zero(colptr)) {
|
|
||||||
continue;
|
|
||||||
} else if (sscanf(colptr, "%30hd", &integer) != 1) {
|
|
||||||
ast_log(LOG_WARNING, "CEL variable %s is not an integer.\n", entry->name);
|
ast_log(LOG_WARNING, "CEL variable %s is not an integer.\n", entry->name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
|
ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
|
||||||
LENGTHEN_BUF2(6);
|
LENGTHEN_BUF2(7);
|
||||||
ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", integer);
|
ast_str_append(&sql2, 0, "%s%d", first ? "" : ",", integer);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SQL_TINYINT:
|
case SQL_TINYINT:
|
||||||
{
|
{
|
||||||
char integer = 0;
|
char integer = 0;
|
||||||
if (strcasecmp(entry->name, "eventtype") == 0) {
|
if (sscanf(colptr, "%30hhd", &integer) != 1) {
|
||||||
integer = (char) record.event_type;
|
|
||||||
} else if (ast_strlen_zero(colptr)) {
|
|
||||||
continue;
|
|
||||||
} else if (sscanf(colptr, "%30hhd", &integer) != 1) {
|
|
||||||
ast_log(LOG_WARNING, "CEL variable %s is not an integer.\n", entry->name);
|
ast_log(LOG_WARNING, "CEL variable %s is not an integer.\n", entry->name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -673,11 +705,7 @@ static void odbc_log(const struct ast_event *event, void *userdata)
|
|||||||
case SQL_BIT:
|
case SQL_BIT:
|
||||||
{
|
{
|
||||||
char integer = 0;
|
char integer = 0;
|
||||||
if (strcasecmp(entry->name, "eventtype") == 0) {
|
if (sscanf(colptr, "%30hhd", &integer) != 1) {
|
||||||
integer = (char) record.event_type;
|
|
||||||
} else if (ast_strlen_zero(colptr)) {
|
|
||||||
continue;
|
|
||||||
} else if (sscanf(colptr, "%30hhd", &integer) != 1) {
|
|
||||||
ast_log(LOG_WARNING, "CEL variable %s is not an integer.\n", entry->name);
|
ast_log(LOG_WARNING, "CEL variable %s is not an integer.\n", entry->name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -693,17 +721,13 @@ static void odbc_log(const struct ast_event *event, void *userdata)
|
|||||||
case SQL_DECIMAL:
|
case SQL_DECIMAL:
|
||||||
{
|
{
|
||||||
double number = 0.0;
|
double number = 0.0;
|
||||||
if (strcasecmp(entry->name, "eventtype") == 0) {
|
if (sscanf(colptr, "%30lf", &number) != 1) {
|
||||||
number = (double)record.event_type;
|
|
||||||
} else if (ast_strlen_zero(colptr)) {
|
|
||||||
continue;
|
|
||||||
} else if (sscanf(colptr, "%30lf", &number) != 1) {
|
|
||||||
ast_log(LOG_WARNING, "CEL variable %s is not an numeric type.\n", entry->name);
|
ast_log(LOG_WARNING, "CEL variable %s is not an numeric type.\n", entry->name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
|
ast_str_append(&sql, 0, "%s%s", first ? "" : ",", entry->name);
|
||||||
LENGTHEN_BUF2(entry->decimals);
|
LENGTHEN_BUF2(entry->decimals + 2);
|
||||||
ast_str_append(&sql2, 0, "%s%*.*lf", first ? "" : ",", entry->decimals, entry->radix, number);
|
ast_str_append(&sql2, 0, "%s%*.*lf", first ? "" : ",", entry->decimals, entry->radix, number);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -712,11 +736,7 @@ static void odbc_log(const struct ast_event *event, void *userdata)
|
|||||||
case SQL_DOUBLE:
|
case SQL_DOUBLE:
|
||||||
{
|
{
|
||||||
double number = 0.0;
|
double number = 0.0;
|
||||||
if (strcasecmp(entry->name, "eventtype") == 0) {
|
if (sscanf(colptr, "%30lf", &number) != 1) {
|
||||||
number = (double) record.event_type;
|
|
||||||
} else if (ast_strlen_zero(colptr)) {
|
|
||||||
continue;
|
|
||||||
} else if (sscanf(colptr, "%30lf", &number) != 1) {
|
|
||||||
ast_log(LOG_WARNING, "CEL variable %s is not an numeric type.\n", entry->name);
|
ast_log(LOG_WARNING, "CEL variable %s is not an numeric type.\n", entry->name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@@ -92,6 +92,7 @@
|
|||||||
;connection=sqlserver
|
;connection=sqlserver
|
||||||
;table=AsteriskCEL
|
;table=AsteriskCEL
|
||||||
;usegmtime=yes ; defaults to no
|
;usegmtime=yes ; defaults to no
|
||||||
|
;allowleapsecond=no ; allow leap second in SQL column for eventtime, default yes.
|
||||||
;alias src => source
|
;alias src => source
|
||||||
;alias channel => source_channel
|
;alias channel => source_channel
|
||||||
;alias dst => dest
|
;alias dst => dest
|
||||||
|
Reference in New Issue
Block a user