347{
352 char *tmp;
353 char colbuf[1024], *colptr;
354 SQLHSTMT stmt =
NULL;
355 char *separator;
356 int quoted = 0;
357 int res;
358
359 if (!sql || !sql2) {
360 if (sql)
362 if (sql2)
364 return -1;
365 }
366
371 return -1;
372 }
373
375 separator = "";
376
377 quoted = 0;
379 quoted = 1;
380 }
381
383 if (quoted) {
386 }else{
388 }
389 } else {
390 if (quoted) {
391 ast_str_set(&sql, 0,
"INSERT INTO %c%s%c.%c%s%c (",
394 }else{
396 }
397 }
399
400
403 continue;
404 }
405
407 int datefield = 0;
408 if (strcasecmp(entry->
cdrname,
"start") == 0) {
409 datefield = 1;
410 }
else if (strcasecmp(entry->
cdrname,
"answer") == 0) {
411 datefield = 2;
412 }
else if (strcasecmp(entry->
cdrname,
"end") == 0) {
413 datefield = 3;
414 }
415
416
419 }
else if (datefield && tableptr->
usegmtime) {
420 struct timeval date_tv = (datefield == 1) ? cdr->
start : (datefield == 2) ? cdr->
answer : cdr->
end;
421 struct ast_tm tm = { 0, };
423 ast_strftime(colbuf,
sizeof(colbuf),
"%Y-%m-%d %H:%M:%S", &tm);
424 colptr = colbuf;
425 } else {
427 }
428
429 if (colptr) {
430
431
432
433
436 ast_verb(4,
"CDR column '%s' with value '%s' does not match filter of"
437 " %s'%s'. Cancelling this CDR.\n",
439 goto early_release;
440 }
441
442
444 continue;
445
447
448 switch (entry->
type) {
449 case SQL_CHAR:
450 case SQL_VARCHAR:
451 case SQL_LONGVARCHAR:
452#ifdef HAVE_ODBC_WCHAR
453 case SQL_WCHAR:
454 case SQL_WVARCHAR:
455 case SQL_WLONGVARCHAR:
456#endif
457 case SQL_BINARY:
458 case SQL_VARBINARY:
459 case SQL_LONGVARBINARY:
460 case SQL_GUID:
461
462
463
464 if (strcasecmp(entry->
name,
"disposition") == 0) {
466 }
else if (strcasecmp(entry->
name,
"amaflags") == 0) {
468 }
469
470
471 if (entry->
type != SQL_GUID) {
472 if (strlen(colptr) > entry->
octetlen) {
474 }
475 }
476
478
479
481 for (tmp = colptr; *tmp; tmp++) {
482 if (*tmp == '\'') {
486 } else {
488 }
489 }
491 break;
492 case SQL_TYPE_DATE:
494 continue;
495 } else {
496 int year = 0, month = 0, day = 0;
497 if (sscanf(colptr, "%4d-%2d-%2d", &year, &month, &day) != 3 || year <= 0 ||
498 month <= 0 || month > 12 || day < 0 || day > 31 ||
499 ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) ||
500 (month == 2 && year % 400 == 0 && day > 29) ||
501 (month == 2 && year % 100 == 0 && day > 28) ||
502 (month == 2 && year % 4 == 0 && day > 29) ||
503 (month == 2 && year % 4 != 0 && day > 28)) {
505 continue;
506 }
507
508 if (year > 0 && year < 100) {
509 year += 2000;
510 }
511
513 ast_str_append(&sql2, 0,
"%s{ d '%04d-%02d-%02d' }", separator, year, month, day);
514 }
515 break;
516 case SQL_TYPE_TIME:
518 continue;
519 } else {
520 int hour = 0, minute = 0, second = 0;
521 int count = sscanf(colptr, "%2d:%2d:%2d", &hour, &minute, &second);
522
523 if ((count != 2 && count != 3) || hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) {
525 continue;
526 }
527
529 ast_str_append(&sql2, 0,
"%s{ t '%02d:%02d:%02d' }", separator, hour, minute, second);
530 }
531 break;
532 case SQL_TYPE_TIMESTAMP:
533 case SQL_TIMESTAMP:
534 case SQL_DATETIME:
536 continue;
537 } else {
538 int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;
539 int count = sscanf(colptr, "%4d-%2d-%2d %2d:%2d:%2d", &year, &month, &day, &hour, &minute, &second);
540
541 if ((count != 3 && count != 5 && count != 6) || year <= 0 ||
542 month <= 0 || month > 12 || day < 0 || day > 31 ||
543 ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) ||
544 (month == 2 && year % 400 == 0 && day > 29) ||
545 (month == 2 && year % 100 == 0 && day > 28) ||
546 (month == 2 && year % 4 == 0 && day > 29) ||
547 (month == 2 && year % 4 != 0 && day > 28) ||
548 hour > 23 || minute > 59 || second > 59 || hour < 0 || minute < 0 || second < 0) {
550 continue;
551 }
552
553 if (year > 0 && year < 100) {
554 year += 2000;
555 }
556
558 ast_str_append(&sql2, 0,
"%s{ ts '%04d-%02d-%02d %02d:%02d:%02d' }", separator, year, month, day, hour, minute, second);
559 }
560 break;
561 case SQL_INTEGER:
563 continue;
564 } else {
566 if (sscanf(colptr,
"%30d", &
integer) != 1) {
568 continue;
569 }
570
573 }
574 break;
575 case SQL_BIGINT:
577 continue;
578 } else {
580 if (sscanf(colptr,
"%30lld", &
integer) != 1) {
582 continue;
583 }
584
587 }
588 break;
589 case SQL_SMALLINT:
591 continue;
592 } else {
594 if (sscanf(colptr,
"%30hd", &
integer) != 1) {
596 continue;
597 }
598
601 }
602 break;
603 case SQL_TINYINT:
605 continue;
606 } else {
608 if (sscanf(colptr,
"%30hhd", &
integer) != 1) {
610 continue;
611 }
612
615 }
616 break;
617 case SQL_BIT:
619 continue;
620 } else {
622 if (sscanf(colptr,
"%30hhd", &
integer) != 1) {
624 continue;
625 }
628
631 }
632 break;
633 case SQL_NUMERIC:
634 case SQL_DECIMAL:
636 continue;
637 } else {
639
640 if (!strcasecmp(entry->
cdrname,
"billsec")) {
642 snprintf(colbuf, sizeof(colbuf), "%lf",
644 } else {
646 }
647 }
else if (!strcasecmp(entry->
cdrname,
"duration")) {
648 snprintf(colbuf, sizeof(colbuf), "%lf",
650
652 colptr = colbuf;
653 }
654 }
655
656 if (sscanf(colptr,
"%30lf", &
number) != 1) {
658 continue;
659 }
660
663 }
664 break;
665 case SQL_FLOAT:
666 case SQL_REAL:
667 case SQL_DOUBLE:
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 default:
700 continue;
701 }
702 if (quoted) {
704 } else {
706 }
707 separator = ", ";
711 ast_verb(4,
"CDR column '%s' was not set and does not match filter of"
712 " %s'%s'. Cancelling this CDR.\n",
714 entry->filtervalue);
715 goto early_release;
716 }
717 }
718
719
724
726
727
728
729 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->
con, &stmt);
730 if (!SQL_SUCCEEDED(res)) {
733 goto early_release;
734 }
735
737 if (!SQL_SUCCEEDED(res)) {
739 }
740
741 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
742
743early_release:
745 }
747
748
751 }
754 }
755
758 return 0;
759}
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)
#define LENGTHEN_BUF1(size)
static int answer(void *data)
#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.
SQLRETURN ast_odbc_execute_sql(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Execute a unprepared SQL query.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#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.
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str 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.