diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h
index 37c72d6c91e3f6bb36292a3048a29560824c2f7d..aebf7abbc0cc38039f98a18dc246dc48b7833414 100755
--- a/include/asterisk/pbx.h
+++ b/include/asterisk/pbx.h
@@ -356,7 +356,7 @@ int ast_matchmore_extension(struct ast_channel *c, const char *context, const ch
  * Returns 1 on match, 0 on failure
  */
 int ast_extension_match(const char *pattern, const char *extension);
-
+int ast_extension_close(const char *pattern, const char *data, int needmore);
 //! Launch a new extension (i.e. new stack)
 /*!
  * \param c not important
diff --git a/pbx.c b/pbx.c
index 5ae63735e9f4adb43be14ed03241886c3d28fb4e..737611af5ad755a9e134ad97aff54568e659a470 100755
--- a/pbx.c
+++ b/pbx.c
@@ -649,7 +649,7 @@ int ast_extension_match(const char *pattern, const char *data)
 	return match;
 }
 
-static int extension_close(const char *pattern, const char *data, int needmore)
+int ast_extension_close(const char *pattern, const char *data, int needmore)
 {
 	int match;
 	/* If "data" is longer, it can'be a subset of pattern unless
@@ -749,8 +749,8 @@ static struct ast_exten *pbx_find_extension(struct ast_channel *chan, struct ast
 			while(eroot) {
 				/* Match extension */
 				if ((((action != HELPER_MATCHMORE) && ast_extension_match(eroot->exten, exten)) ||
-						((action == HELPER_CANMATCH) && (extension_close(eroot->exten, exten, 0))) ||
-						((action == HELPER_MATCHMORE) && (extension_close(eroot->exten, exten, 1)))) &&
+						((action == HELPER_CANMATCH) && (ast_extension_close(eroot->exten, exten, 0))) ||
+						((action == HELPER_MATCHMORE) && (ast_extension_close(eroot->exten, exten, 1)))) &&
 						(!eroot->matchcid || matchcid(eroot->cidmatch, callerid))) {
 						e = eroot;
 						if (*status < STATUS_NO_PRIORITY)
diff --git a/pbx/pbx_realtime.c b/pbx/pbx_realtime.c
index 5a828f44a65ab6eb9e06acd6850497b1a4851583..52de08ba8eb0b2e1659b07d19844b0852b6f9e9e 100755
--- a/pbx/pbx_realtime.c
+++ b/pbx/pbx_realtime.c
@@ -13,6 +13,7 @@
 #include <asterisk/logger.h>
 #include <asterisk/channel.h>
 #include <asterisk/config.h>
+#include <asterisk/config_pvt.h>
 #include <asterisk/options.h>
 #include <asterisk/pbx.h>
 #include <asterisk/module.h>
@@ -34,9 +35,9 @@
 #include <string.h>
 #include <errno.h>
 
-#define MODE_MATCH 0
-#define MODE_MATCHMORE 1
-#define MODE_CANMATCH 2
+#define MODE_MATCH 		0
+#define MODE_MATCHMORE 	1
+#define MODE_CANMATCH 	2
 
 static char *tdesc = "Realtime Switch";
 
@@ -49,7 +50,7 @@ static char *tdesc = "Realtime Switch";
 
 	The realtime table should have entries for context,exten,priority,app,args
 	
-	The realtime table currently does not support patterns or callerid fields.
+	The realtime table currently does not support callerid fields.
 
 */
 
@@ -86,9 +87,12 @@ static char *tdesc = "Realtime Switch";
 static struct ast_variable *realtime_switch_common(const char *table, const char *context, const char *exten, int priority, int mode)
 {
 	struct ast_variable *var;
+	struct ast_config *cfg;
+	struct ast_category *cat;
 	char pri[20];
 	char *ematch;
 	char rexten[AST_MAX_EXTENSION + 20]="";
+	int match;
 	snprintf(pri, sizeof(pri), "%d", priority);
 	switch(mode) {
 	case MODE_MATCHMORE:
@@ -104,7 +108,33 @@ static struct ast_variable *realtime_switch_common(const char *table, const char
 		ematch = "exten";
 		strncpy(rexten, exten, sizeof(rexten) - 1);
 	}
-	var = ast_load_realtime(table, "context", context, ematch, rexten, "priority", pri, NULL);
+	var = ast_load_realtime(table, ematch, rexten, "context", context, "priority", pri, NULL);
+	if (!var) {
+		cfg = ast_load_realtime_multientry(table, "exten RLIKE", "_.*", "context", context, "priority", pri, NULL);	
+		if (cfg) {
+			cat = cfg->root;
+			while(cat) {
+				switch(mode) {
+				case MODE_MATCHMORE:
+					match = ast_extension_close(cat->name, exten, 1);
+					break;
+				case MODE_CANMATCH:
+					match = ast_extension_close(cat->name, exten, 0);
+					break;
+				case MODE_MATCH:
+				default:
+					match = ast_extension_match(cat->name, exten);
+				}
+				if (match) {
+					var = cat->root;
+					cat->root = NULL;
+					break;
+				}
+				cat = cat->next;
+			}
+			ast_destroy(cfg);
+		}
+	}
 	return var;
 }
 
diff --git a/res/res_config_odbc.c b/res/res_config_odbc.c
index 786e14bca108eebc16ec2ea946d88de0af34959b..96d5aacd3ad5647404544fec577aa7cfde86f9c9 100755
--- a/res/res_config_odbc.c
+++ b/res/res_config_odbc.c
@@ -174,6 +174,8 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char *
 	char sql[1024];
 	char coltitle[256];
 	char rowdata[2048];
+	char *title=NULL;
+	const char *initfield=NULL;
 	char *op;
 	const char *newparam, *newval;
 	char *stringp;
@@ -213,6 +215,9 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char *
 		SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 		return NULL;
 	}
+	initfield = ast_strdupa(newparam);
+	if (initfield && (op = strchr(initfield, ' '))) 
+		*op = '\0';
 	newval = va_arg(aq, const char *);
 	if (!strchr(newparam, ' ')) op = " ="; else op = "";
 	snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?", table, newparam, op);
@@ -221,6 +226,8 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char *
 		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?", newparam, op);
 		newval = va_arg(aq, const char *);
 	}
+	if (initfield)
+		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
 	va_end(aq);
 	res = SQLPrepare(stmt, sql, SQL_NTS);
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
@@ -259,7 +266,7 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char *
 		return NULL;
 	}
 
-	while (rowcount) {
+	while (rowcount--) {
 		var = NULL;
 		prev = NULL;
 		res = SQLFetch(stmt);
@@ -289,6 +296,8 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char *
 			while(stringp) {
 				chunk = strsep(&stringp, ";");
 				if (chunk && !ast_strlen_zero(ast_strip(chunk))) {
+					if (initfield && !strcmp(initfield, coltitle) && !title)
+						title = ast_strdupa(chunk);
 					if (prev) {
 						prev->next = ast_new_variable(coltitle, chunk);
 						if (prev->next)
@@ -298,20 +307,20 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char *
 					
 				}
 			}
-			if (var) {
-				cat = ast_new_category("");
-				if (cat) {
-					cat->root = var;
-					if (!cfg) 
-						cfg = ast_new_config();
-					if (cfg)
-						ast_category_append(cfg, cat);
-					else 
-						ast_category_destroy(cat);
-				} else {
-					ast_log(LOG_WARNING, "Out of memory!\n");
-					ast_destroy_realtime(var);
-				}
+		}
+		if (var) {
+			cat = ast_new_category(title ? title : "");
+			if (cat) {
+				cat->root = var;
+				if (!cfg) 
+					cfg = ast_new_config();
+				if (cfg)
+					ast_category_append(cfg, cat);
+				else 
+					ast_category_destroy(cat);
+			} else {
+				ast_log(LOG_WARNING, "Out of memory!\n");
+				ast_destroy_realtime(var);
 			}
 		}
 	}