Skip to content

Commit

Permalink
sql_cacher: properly support integer caching keys
Browse files Browse the repository at this point in the history
Add a new parameter "key_type" to the caching entries configuration
that specifies an integer or string data type for the caching key.

Fixes #2335

(cherry picked from commit 600cd1c)
  • Loading branch information
rvlad-patrascu committed Dec 15, 2020
1 parent ae5ac48 commit 9b0ae63
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 5 deletions.
12 changes: 12 additions & 0 deletions modules/sql_cacher/doc/sql_cacher_admin.xml
Expand Up @@ -87,6 +87,18 @@
<emphasis>key</emphasis> : SQL database column name of the <quote>key</quote> column
</para></listitem>
<listitem><para>
<emphasis>key_type</emphasis> : data type for the SQL "key" column:
<itemizedlist>
<listitem><para>
string
</para></listitem>
<listitem><para>
int
</para></listitem>
</itemizedlist>
<para>If not present, default value is <quote>string</quote></para>
</para></listitem>
<listitem><para>
<emphasis>columns</emphasis> : names of the columns to be cached from the
SQL database, separated by a delimiter configured by
<xref linkend="param_columns_delimiter"/>.
Expand Down
62 changes: 57 additions & 5 deletions modules/sql_cacher/sql_cacher.c
Expand Up @@ -136,6 +136,7 @@ static int parse_cache_entry(unsigned int type, void *val)
int col_idx;
int rc = -1;
int i;
int len;
str parse_str_copy, parse_str;

if(!entry_list){
Expand All @@ -161,6 +162,7 @@ static int parse_cache_entry(unsigned int type, void *val)
}
new_entry->id.s = NULL;
new_entry->columns = NULL;
new_entry->key_type = DB_STR;
new_entry->nr_columns = 0;
new_entry->on_demand = 0;
new_entry->expire = DEFAULT_ON_DEMAND_EXPIRE;
Expand Down Expand Up @@ -255,13 +257,54 @@ static int parse_cache_entry(unsigned int type, void *val)
goto parse_err;
}

/* parse the required column names if present */
/* parse the key type if present */
p1 = tmp + 1;
p2 = memchr(p1, '=', parse_str.len - (p1 - parse_str.s));
if (!p2) {
LM_ERR("expected: '='\n");
goto parse_err;
}
if (!memcmp(p1, KEY_TYPE_STR, KEY_TYPE_STR_LEN)) {
if (*(p1+KEY_TYPE_STR_LEN) != '=') { \
LM_ERR("expected: '=' after: %.*s\n", KEY_TYPE_STR_LEN, KEY_TYPE_STR);
goto parse_err;
}


tmp = memchr(p2 + 1, spec_delimiter.s[0],
parse_str.len - (p2 - parse_str.s));
if (!tmp)
len = parse_str.len - (p2 - parse_str.s + 1);
else
len = tmp - p2 - 1;

if (len <= 0) {
LM_ERR("expected value of: %.*s\n", KEY_TYPE_STR_LEN, KEY_TYPE_STR);
goto parse_err;
}

if (len == TYPE_STR_LEN && !memcmp(p2+1, TYPE_STR_STR, len))
new_entry->key_type = DB_STR;
else if (len == TYPE_INT_LEN && !memcmp(p2+1, TYPE_INT_STR, len))
new_entry->key_type = DB_INT;
else {
LM_ERR("Unsupported key type: %.*s\n", len, p2+1);
goto parse_err;
}

if (!tmp) /* delimiter not found, reached the end of the string to parse */
goto end_parsing;
else {
p1 = tmp + 1;
p2 = memchr(p1, '=', parse_str.len - (p1 - parse_str.s));
if (!p2) {
LM_ERR("expected: '='\n");
goto parse_err;
}
}
}

/* parse the required column names if present */
if (!memcmp(p1, COLUMNS_STR, COLUMNS_STR_LEN)) {
if (*(p1+COLUMNS_STR_LEN) != '=') { \
LM_ERR("expected: '=' after: %.*s\n", COLUMNS_STR_LEN, COLUMNS_STR);
Expand Down Expand Up @@ -712,8 +755,11 @@ static db_handlers_t *db_init_test_conn(cache_entry_t *c_entry)
}

VAL_NULL(&query_key_val) = 0;
VAL_TYPE(&query_key_val) = DB_STR;
VAL_STR(&query_key_val) = test_query_key_str;
VAL_TYPE(&query_key_val) = c_entry->key_type;
if (c_entry->key_type == DB_STR)
VAL_STR(&query_key_val) = test_query_key_str;
else
VAL_INT(&query_key_val) = TEST_QUERY_INT;

query_key_col = &c_entry->key;

Expand Down Expand Up @@ -902,9 +948,15 @@ static int load_key(cache_entry_t *c_entry, db_handlers_t *db_hdls, str key,
memcpy(src_key.s + c_entry->id.len, key.s, key.len);

key_col = &(c_entry->key);

VAL_NULL(&key_val) = 0;
VAL_TYPE(&key_val) = DB_STR;
VAL_STR(&key_val) = key;
VAL_TYPE(&key_val) = c_entry->key_type;
if (c_entry->key_type == DB_STR)
VAL_STR(&key_val) = key;
else if (str2sint(&key, &VAL_INT(&key_val)) < 0) {
LM_ERR("Failed to convert key value to integer\n");
goto out_error;
}

if (db_hdls->db_funcs.use_table(db_hdls->db_con, &c_entry->table) < 0) {
LM_ERR("Invalid table name: %.*s\n", c_entry->table.len, c_entry->table.s);
Expand Down
9 changes: 9 additions & 0 deletions modules/sql_cacher/sql_cacher.h
Expand Up @@ -43,18 +43,26 @@
#define TABLE_STR_LEN ((int)(sizeof(TABLE_STR) - 1))
#define KEY_STR "key"
#define KEY_STR_LEN ((int)(sizeof(KEY_STR) - 1))
#define KEY_TYPE_STR "key_type"
#define KEY_TYPE_STR_LEN ((int)(sizeof(KEY_TYPE_STR) - 1))
#define COLUMNS_STR "columns"
#define COLUMNS_STR_LEN ((int)(sizeof(COLUMNS_STR) - 1))
#define ONDEMAND_STR "on_demand"
#define ONDEMAND_STR_LEN ((int)(sizeof(ONDEMAND_STR) - 1))
#define EXPIRE_STR "expire"
#define EXPIRE_STR_LEN ((int)(sizeof(EXPIRE_STR) - 1))

#define TYPE_STR_STR "string"
#define TYPE_STR_LEN ((int)(sizeof(TYPE_STR_STR) - 1))
#define TYPE_INT_STR "int"
#define TYPE_INT_LEN ((int)(sizeof(TYPE_INT_STR) - 1))

#define DEFAULT_ON_DEMAND_EXPIRE 3600
#define DEFAULT_FULL_CACHING_EXPIRE 86400 /* 24h */
#define DEFAULT_RELOAD_INTERVAL 60
#define DEFAULT_FETCH_NR_ROWS 100
#define TEST_QUERY_STR "sql_cacher_test_query_key"
#define TEST_QUERY_INT 555666555
#define CDB_TEST_KEY_STR "sql_cacher_cdb_test_key"
#define CDB_TEST_VAL_STR "sql_cacher_cdb_test_val"
#define INT_B64_ENC_LEN 8
Expand All @@ -71,6 +79,7 @@ typedef struct _cache_entry {
str table;
str key;
str **columns;
db_type_t key_type;
unsigned int nr_columns;
unsigned int on_demand;
unsigned int expire;
Expand Down

0 comments on commit 9b0ae63

Please sign in to comment.