380{
386 char colbuf[1024], *colptr;
387 SQLHSTMT stmt =
NULL;
388 SQLLEN rows = 0;
389 char *separator;
390 int quoted = 0;
391
392 if (!sql || !sql2) {
393 if (sql)
395 if (sql2)
397 return -1;
398 }
399
404 return -1;
405 }
406
408 separator = "";
409
410 quoted = 0;
412 quoted = 1;
413 }
414
416 if (quoted) {
419 }else{
421 }
422 } else {
423 if (quoted) {
424 ast_str_set(&sql, 0,
"INSERT INTO %c%s%c.%c%s%c (",
427 }else{
429 }
430 }
432
433
436 continue;
437 }
438
440 int datefield = 0;
441 if (strcasecmp(
entry->cdrname,
"start") == 0) {
442 datefield = 1;
443 }
else if (strcasecmp(
entry->cdrname,
"answer") == 0) {
444 datefield = 2;
445 }
else if (strcasecmp(
entry->cdrname,
"end") == 0) {
446 datefield = 3;
447 }
448
449
450 if (
entry->staticvalue) {
452 }
else if (datefield && tableptr->
usegmtime) {
453 struct timeval date_tv = (datefield == 1) ? cdr->
start : (datefield == 2) ? cdr->
answer : cdr->
end;
454 struct ast_tm tm = { 0, };
456 ast_strftime(colbuf,
sizeof(colbuf),
"%Y-%m-%d %H:%M:%S", &tm);
457 colptr = colbuf;
458 } else {
460 }
461
462 if (colptr) {
463
464
465
466
467 if ((
entry->filtervalue && !
entry->negatefiltervalue && strcasecmp(colptr,
entry->filtervalue) != 0) ||
468 (
entry->filtervalue &&
entry->negatefiltervalue && strcasecmp(colptr,
entry->filtervalue) == 0)) {
469 ast_verb(4,
"CDR column '%s' with value '%s' does not match filter of"
470 " %s'%s'. Cancelling this CDR.\n",
471 entry->cdrname, colptr,
entry->negatefiltervalue ?
"!" :
"",
entry->filtervalue);
472 goto early_release;
473 }
474
475
477 continue;
478
480
481 switch (
entry->type) {
482 case SQL_CHAR:
483 case SQL_VARCHAR:
484 case SQL_LONGVARCHAR:
485#ifdef HAVE_ODBC_WCHAR
486 case SQL_WCHAR:
487 case SQL_WVARCHAR:
488 case SQL_WLONGVARCHAR:
489#endif
490 case SQL_BINARY:
491 case SQL_VARBINARY:
492 case SQL_LONGVARBINARY:
493 case SQL_GUID:
494
495
496
497 if (strcasecmp(
entry->name,
"disposition") == 0) {
499 }
else if (strcasecmp(
entry->name,
"amaflags") == 0) {
501 }
502
503
504 if (
entry->type != SQL_GUID) {
505 if (strlen(colptr) >
entry->octetlen) {
506 colptr[
entry->octetlen] =
'\0';
507 }
508 }
509
511
512
519 } else {
521 }
522 }
524 break;
525 case SQL_TYPE_DATE:
527 continue;
528 } else {
529 int year = 0, month = 0, day = 0;
530 if (sscanf(colptr, "%4d-%2d-%2d", &year, &month, &day) != 3 || year <= 0 ||
531 month <= 0 || month > 12 || day < 0 || day > 31 ||
532 ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) ||
533 (month == 2 && year % 400 == 0 && day > 29) ||
534 (month == 2 && year % 100 == 0 && day > 28) ||
535 (month == 2 && year % 4 == 0 && day > 29) ||
536 (month == 2 && year % 4 != 0 && day > 28)) {
538 continue;
539 }
540
541 if (year > 0 && year < 100) {
542 year += 2000;
543 }
544
546 ast_str_append(&sql2, 0,
"%s{ d '%04d-%02d-%02d' }", separator, year, month, day);
547 }
548 break;
549 case SQL_TYPE_TIME:
551 continue;
552 } else {
553 int hour = 0, minute = 0, second = 0;
554 int count = sscanf(colptr, "%2d:%2d:%2d", &hour, &minute, &second);
555
556 if ((count != 2 && count != 3) || hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) {
558 continue;
559 }
560
562 ast_str_append(&sql2, 0,
"%s{ t '%02d:%02d:%02d' }", separator, hour, minute, second);
563 }
564 break;
565 case SQL_TYPE_TIMESTAMP:
566 case SQL_TIMESTAMP:
567 case SQL_DATETIME:
569 continue;
570 } else {
571 int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;
572 int count = sscanf(colptr, "%4d-%2d-%2d %2d:%2d:%2d", &year, &month, &day, &hour, &minute, &second);
573
574 if ((count != 3 && count != 5 && count != 6) || year <= 0 ||
575 month <= 0 || month > 12 || day < 0 || day > 31 ||
576 ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) ||
577 (month == 2 && year % 400 == 0 && day > 29) ||
578 (month == 2 && year % 100 == 0 && day > 28) ||
579 (month == 2 && year % 4 == 0 && day > 29) ||
580 (month == 2 && year % 4 != 0 && day > 28) ||
581 hour > 23 || minute > 59 || second > 59 || hour < 0 || minute < 0 || second < 0) {
583 continue;
584 }
585
586 if (year > 0 && year < 100) {
587 year += 2000;
588 }
589
591 ast_str_append(&sql2, 0,
"%s{ ts '%04d-%02d-%02d %02d:%02d:%02d' }", separator, year, month, day, hour, minute, second);
592 }
593 break;
594 case SQL_INTEGER:
596 continue;
597 } else {
599 if (sscanf(colptr,
"%30d", &
integer) != 1) {
601 continue;
602 }
603
606 }
607 break;
608 case SQL_BIGINT:
610 continue;
611 } else {
613 if (sscanf(colptr,
"%30lld", &
integer) != 1) {
615 continue;
616 }
617
620 }
621 break;
622 case SQL_SMALLINT:
624 continue;
625 } else {
627 if (sscanf(colptr,
"%30hd", &
integer) != 1) {
629 continue;
630 }
631
634 }
635 break;
636 case SQL_TINYINT:
638 continue;
639 } else {
641 if (sscanf(colptr,
"%30hhd", &
integer) != 1) {
643 continue;
644 }
645
648 }
649 break;
650 case SQL_BIT:
652 continue;
653 } else {
655 if (sscanf(colptr,
"%30hhd", &
integer) != 1) {
657 continue;
658 }
661
664 }
665 break;
666 case SQL_NUMERIC:
667 case SQL_DECIMAL:
669 continue;
670 } else {
672
673 if (!strcasecmp(
entry->cdrname,
"billsec")) {
675 snprintf(colbuf, sizeof(colbuf), "%lf",
677 } else {
679 }
680 }
else if (!strcasecmp(
entry->cdrname,
"duration")) {
681 snprintf(colbuf, sizeof(colbuf), "%lf",
683
685 colptr = colbuf;
686 }
687 }
688
689 if (sscanf(colptr,
"%30lf", &
number) != 1) {
691 continue;
692 }
693
696 }
697 break;
698 case SQL_FLOAT:
699 case SQL_REAL:
700 case SQL_DOUBLE:
702 continue;
703 } else {
705
706 if (!strcasecmp(
entry->cdrname,
"billsec")) {
708 snprintf(colbuf, sizeof(colbuf), "%lf",
710 } else {
712 }
713 }
else if (!strcasecmp(
entry->cdrname,
"duration")) {
714 snprintf(colbuf, sizeof(colbuf), "%lf",
716
718 colptr = colbuf;
719 }
720 }
721
722 if (sscanf(colptr,
"%30lf", &
number) != 1) {
724 continue;
725 }
726
729 }
730 break;
731 default:
733 continue;
734 }
735 if (quoted) {
737 } else {
739 }
740 separator = ", ";
741 }
else if (
entry->filtervalue
742 && ((!
entry->negatefiltervalue &&
entry->filtervalue[0] !=
'\0')
743 || (
entry->negatefiltervalue &&
entry->filtervalue[0] ==
'\0'))) {
744 ast_verb(4,
"CDR column '%s' was not set and does not match filter of"
745 " %s'%s'. Cancelling this CDR.\n",
746 entry->cdrname,
entry->negatefiltervalue ?
"!" :
"",
748 goto early_release;
749 }
750 }
751
752
757
759
761 if (stmt) {
762 SQLRowCount(stmt, &rows);
763 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
764 }
765 if (rows == 0) {
767 }
768early_release:
770 }
772
773
776 }
779 }
780
783 return 0;
784}
void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
Format a CDR variable from an already posted CDR.
#define LENGTHEN_BUF2(size)
static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
#define LENGTHEN_BUF1(size)
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
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...
int ast_odbc_backslash_is_escape(struct odbc_obj *obj)
Checks if the database natively supports backslash as an escape character.
SQLHSTMT ast_odbc_prepare_and_execute(struct odbc_obj *obj, SQLHSTMT(*prepare_cb)(struct odbc_obj *obj, void *data), void *data)
Prepares, executes, and returns the resulting statement handle.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Support for dynamic strings.
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.