Index: addons/cdr_mysql.c
===================================================================
--- addons/cdr_mysql.c	(revision 238312)
+++ addons/cdr_mysql.c	(working copy)
@@ -288,6 +288,17 @@
 					ast_str_append(&sql2, 0, ",");
 				}
 
+				if (!strcmp(cdrname, "billsec") && 
+					(strstr(entry->type, "float") ||
+					strstr(entry->type, "double") ||
+					strstr(entry->type, "real"))) {
+					snprintf(workspace, sizeof(workspace), "%lf", 
+						(double) ((cdr->end.tv_sec - cdr->answer.tv_sec) 
+						+ ((cdr->end.tv_usec - cdr->answer.tv_usec) / 1000000.0)));
+					if (!ast_strlen_zero(workspace))
+						value = workspace;
+				}
+					
 				ast_str_make_space(&escape, (valsz = strlen(value)) * 2 + 1);
 				mysql_real_escape_string(&mysql, ast_str_buffer(escape), value, valsz);
 
Index: funcs/func_cdr.c
===================================================================
--- funcs/func_cdr.c	(revision 238312)
+++ funcs/func_cdr.c	(working copy)
@@ -106,6 +106,9 @@
 			</parameter>
 			<parameter name="options" required="false">
 				<optionlist>
+					<option name="f">
+						<para>Returns billsec/duration as floating point values.</para>
+					</option>
 					<option name="l">
 						<para>Uses the most recent CDR on a channel with multiple records</para>
 					</option>
@@ -174,9 +177,11 @@
 	OPT_UNPARSED = (1 << 1),
 	OPT_LAST = (1 << 2),
 	OPT_SKIPLOCKED = (1 << 3),
+	OPT_FLOAT = (1 << 4),
 };
 
 AST_APP_OPTIONS(cdr_func_options, {
+	AST_APP_OPTION('f', OPT_FLOAT),
 	AST_APP_OPTION('l', OPT_LAST),
 	AST_APP_OPTION('r', OPT_RECURSIVE),
 	AST_APP_OPTION('s', OPT_SKIPLOCKED),
@@ -213,9 +218,17 @@
 		while (ast_test_flag(cdr, AST_CDR_FLAG_LOCKED) && cdr->next)
 			cdr = cdr->next;
 
+	if (!strcmp("billsec",args.variable) && ast_test_flag(&flags, OPT_FLOAT)) {
+		snprintf(buf, len, "%lf", (double)(cdr->end.tv_sec - cdr->answer.tv_sec 
+			+ (cdr->end.tv_usec - cdr->answer.tv_usec)/1000000.0));
+		if (!ast_strlen_zero(buf))
+			ret = buf;
+	} else {
 	ast_cdr_getvar(cdr, args.variable, &ret, buf, len,
 		       ast_test_flag(&flags, OPT_RECURSIVE),
 			   ast_test_flag(&flags, OPT_UNPARSED));
+	}
+	
 
 	return ret ? 0 : -1;
 }
Index: configs/cdr_odbc.conf.sample
===================================================================
--- configs/cdr_odbc.conf.sample	(revision 238312)
+++ configs/cdr_odbc.conf.sample	(working copy)
@@ -10,3 +10,4 @@
 ;dispositionstring=yes
 ;table=cdr		;"cdr" is default table name
 ;usegmtime=no             ; set to "yes" to log in GMT
+;hrbillsec=yes
Index: cdr/cdr_odbc.c
===================================================================
--- cdr/cdr_odbc.c	(revision 238312)
+++ cdr/cdr_odbc.c	(working copy)
@@ -55,6 +55,7 @@
 	CONFIG_LOGUNIQUEID =       1 << 0,
 	CONFIG_USEGMTIME =         1 << 1,
 	CONFIG_DISPOSITIONSTRING = 1 << 2,
+	CONFIG_HRBILLSEC =         1 << 3,
 };
 
 static struct ast_flags config = { 0 };
@@ -99,7 +100,14 @@
 	SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastapp), 0, cdr->lastapp, 0, NULL);
 	SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->lastdata), 0, cdr->lastdata, 0, NULL);
 	SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->duration, 0, NULL);
-	SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL);
+
+	if (ast_test_flag(&config, CONFIG_HRBILLSEC)) {
+		double hrbill = 0.0;
+		hrbill = (cdr->answer.tv_sec - cdr->end.tv_sec) + ((cdr->end.tv_usec - cdr->answer.tv_usec) / 1000000.0);
+		SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_FLOAT, 0, 0, &hrbill, 0, NULL);
+	} else
+		SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->billsec, 0, NULL);
+
 	if (ast_test_flag(&config, CONFIG_DISPOSITIONSTRING))
 		SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(ast_cdr_disp2str(cdr->disposition)) + 1, 0, ast_cdr_disp2str(cdr->disposition), 0, NULL);
 	else
@@ -205,6 +213,14 @@
 			ast_debug(1, "cdr_odbc: Logging in local time\n");
 		}
 
+		if (((tmp = ast_variable_retrieve(cfg, "global", "hrbillsec"))) && ast_true(tmp)) {
+			ast_set_flag(&config, CONFIG_HRBILLSEC);
+			ast_debug(1, "cdr_odbc: Logging billsec in float\n");
+		} else {
+			ast_clear_flag(&config, CONFIG_HRBILLSEC);
+			ast_debug(1, "cdr_odbc: Logging billsec in integer\n");
+		}
+
 		if ((tmp = ast_variable_retrieve(cfg, "global", "table")) == NULL) {
 			ast_log(LOG_WARNING, "cdr_odbc: table not specified.  Assuming cdr\n");
 			tmp = "cdr";
Index: cdr/cdr_tds.c
===================================================================
--- cdr/cdr_tds.c	(revision 238312)
+++ cdr/cdr_tds.c	(working copy)
@@ -150,6 +150,7 @@
 		}
 	}
 
+	/* No type check of database field, milli-billsec fail*/
 	if (settings->has_userfield) {
 		erc = dbfcmd(settings->dbproc,
 					 "INSERT INTO %s "
Index: cdr/cdr_sqlite3_custom.c
===================================================================
--- cdr/cdr_sqlite3_custom.c	(revision 238312)
+++ cdr/cdr_sqlite3_custom.c	(working copy)
@@ -255,6 +255,7 @@
 			ast_str_append(&value_string, 0, "%s'%s'", ast_str_strlen(value_string) ? "," : "", escaped);
 			sqlite3_free(escaped);
 		}
+		/* No changes req */
 		sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, ast_str_buffer(value_string));
 		ast_debug(1, "About to log: %s\n", sql);
 		ast_channel_release(dummy);
Index: cdr/cdr_adaptive_odbc.c
===================================================================
--- cdr/cdr_adaptive_odbc.c	(revision 238312)
+++ cdr/cdr_adaptive_odbc.c	(working copy)
@@ -628,6 +628,14 @@
 						continue;
 					} else {
 						double number = 0.0;
+
+						if (!strcmp(entry->cdrname,"billsec")) {
+							snprintf(colbuf, sizeof(colbuf), "%lf", (double)((cdr->end.tv_sec - cdr->answer.tv_sec) 
+								+ (cdr->end.tv_usec - cdr->answer.tv_usec) / 1000000.0));
+							if (!ast_strlen_zero(buf))
+								*colptr = colbuf;
+						}
+							
 						if (sscanf(colptr, "%30lf", &number) != 1) {
 							ast_log(LOG_WARNING, "CDR variable %s is not an numeric type.\n", entry->name);
 							continue;
