allow multiple where condition joining by "and"

This commit is contained in:
Kenneth Cheng 2020-05-01 12:33:19 +08:00
parent ff90e37965
commit 3056d81fcc
2 changed files with 85 additions and 68 deletions

View File

@ -120,17 +120,20 @@ The above is nearly like REDIS keys command
Each record is exactly a hash, you could use raw REDIS commands ``hget, hmget or hgetall`` to retrieve the same content
#### Where in Select Statement
This module supports =, >, <, >=, <=, <>, != and like conditions. Only single condition is allowed.
#### Where Clause in Select Statement
Your could specify =, >, <, >=, <=, <>, != or like conditions in where clause. Now the module only support "and" to join multiple conditions.
```bash
127.0.0.1:6379> dbx.select tel from phonebook where name like Son
1) 1) tel
2) "1-888-3333-1412"
2) 1) tel
2) "1-456-1246-3421"
127.0.0.1:6379> dbx.select tel from phonebook where name like Son and pos = 4
1) 1) tel
2) "1-888-3333-1412"
```
#### Order in Select Statement
#### Order Clause in Select Statement
Ordering can be ascending or descending. All sortings are alpha-sort.
```bash
127.0.0.1:6379> dbx.select * from phonebook order by pos asc
@ -140,7 +143,7 @@ Ordering can be ascending or descending. All sortings are alpha-sort.
```
#### Delete Statement
You may also use Insert and Delete statement to operate the hash
You may also use Insert and Delete statement to operate the hash. If you does not provide the where clause, it will delete all the records of the specified key prefix. (i.e. phonebook)
```bash
127.0.0.1:6379> dbx.delete from phonebook where gender = F
(integer) 2
@ -149,6 +152,7 @@ You may also use Insert and Delete statement to operate the hash
```
#### Insert Statement
The module provide simple Insert statement which same as the function of the REDIS command hmset. It will append a random string to your provided key (i.e. phonebook). If operation is successful, it will return the key name.
```bash
127.0.0.1:6379> dbx.insert into phonebook (name,tel,birth,pos,gender) values ('Peter Nelson' ,1-456-1246-3421, 2019-10-01, 3, M)
"phonebook:1588298418-551514504"
@ -159,7 +163,7 @@ You may also use Insert and Delete statement to operate the hash
127.0.0.1:6379> dbx.insert into phonebook (name,tel,birth,pos,gender) values ('Mattias Swensson' ,1-888-3333-1412, 2017-06-30, 4, M)
"phonebook:1588299202-1052597574"
```
Please be noted that Redis requires at least one space after the single and double quoted arguments.
Note that Redis requires at least one space after the single and double quoted arguments.
Or you may quote the whole SQL statement as below:
```bash
127.0.0.1:6379> dbx.insert "into phonebook (name,tel,birth,pos,gender) values ('Peter Nelson','1-456-1246-3421','2019-10-01',3, 'M')"
@ -204,4 +208,4 @@ REDIS v4.0
MIT
## Status
Now the Select statement only supports single where condition and single order sequence. I will add more useful features in the future. Simple Insert, Update and Delete statement will be included finally. This project is in an early stage of development. Any contribution is welcome :D
This project is in an early stage of development. Any contribution is welcome :D

View File

@ -41,17 +41,22 @@ int whereRecord(RedisModuleCtx *ctx, RedisModuleString *key, Vector *vWhere) {
int match = 1;
// If where statement is defined, get the specified hash content and do comparison
if (Vector_Size(vWhere) == 3) {
Vector_Get(vWhere, 0, &field);
Vector_Get(vWhere, 1, &condition);
Vector_Get(vWhere, 2, &w);
size_t n = Vector_Size(vWhere);
if (n == 0) return 1;
if (n % 3 != 0) return 0;
for (size_t i = 0; i < n; i += 3) {
Vector_Get(vWhere, i, &field);
Vector_Get(vWhere, i+1, &condition);
Vector_Get(vWhere, i+2, &w);
if (condition == 7)
toLower(w);
if (strlen(w) == 0)
match = 0;
else {
if (strlen(w) == 0) return 0;
RedisModuleCallReply *tags = RedisModule_Call(ctx, "HGET", "sc", key, field);
if (RedisModule_CallReplyLength(tags) > 0) {
if (RedisModule_CallReplyLength(tags) == 0) {
RedisModule_FreeCallReply(tags);
return 0;
}
RedisModuleString *rms = RedisModule_CreateStringFromCallReply(tags);
size_t l;
const char *s = RedisModule_StringPtrLen(rms, &l);
@ -81,10 +86,7 @@ int whereRecord(RedisModuleCtx *ctx, RedisModuleString *key, Vector *vWhere) {
}
RedisModule_FreeString(ctx, rms);
RedisModule_FreeCallReply(tags);
}
else
match = 0;
}
if (match == 0) return 0;
}
return match;
}
@ -154,21 +156,25 @@ Vector* splitStringByChar(char *s, char* d) {
Vector* splitWhereString(char *s) {
Vector *v = NewVector(void *, 16);
char *token = strtok(s, "&&");
while (token != NULL) {
static char chk[8][3] = {">=", "<=", "!=", "<>", ">", "<", "=", "~"};
char *p = s;
char *p = token;
while(*p++) {
for(int i=0; i<8; i++) {
char *c = chk[i];
if (strncmp(c, p, strlen(c)) == 0) {
*p = 0;
p += strlen(c);
Vector_Push(v, s);
Vector_Push(v, token);
Vector_Push(v, i);
Vector_Push(v, p);
break;
}
}
}
token = strtok(NULL, "&&");
}
return v;
}
@ -283,7 +289,7 @@ int SelectCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
}
break;
case -1:
// parse from statement
// parse from clause
fromKeys = RMUtil_CreateFormattedString(ctx, token);
step = 2;
break;
@ -299,9 +305,11 @@ int SelectCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
break;
case -3:
case 4:
// parse where statement
// parse where clause
if (strcmp("order", token) == 0)
step = -5;
else if (strcmp("and", token) == 0)
strcat(stmWhere, "&&");
else {
if (strlen(stmWhere) + strlen(token) > 512) {
RedisModule_ReplyWithError(ctx, "where arguments are too long");
@ -323,7 +331,7 @@ int SelectCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
break;
case -6:
case 7:
// parse order statement
// parse order clause
if (strlen(stmOrder) + strlen(token) > 512) {
RedisModule_ReplyWithError(ctx, "order arguments are too long");
return REDISMODULE_ERR;
@ -471,7 +479,7 @@ int InsertCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
}
break;
case -1:
// parse into key, assume time+rand always is new key
// parse into clause, assume time+rand always is new key
intoKey = RMUtil_CreateFormattedString(ctx, "%s:%u-%i", token, (unsigned)time(NULL), rand());
step = -2;
break;
@ -615,7 +623,7 @@ int DeleteCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
}
break;
case -1:
// parse from statement
// parse from clause
fromKeys = RMUtil_CreateFormattedString(ctx, token);
step = 2;
break;
@ -629,14 +637,19 @@ int DeleteCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
break;
case -3:
case 4:
// parse where clause
if (strlen(stmWhere) + strlen(token) > 512) {
RedisModule_ReplyWithError(ctx, "where arguments are too long");
return REDISMODULE_ERR;
}
if (strcmp("and", token) == 0)
strcat(stmWhere, "&&");
else {
char *p = token;
while (*p++) *p = *p == 7? 32: *p;
strcat(stmWhere, token);
step = 4;
}
break;
}
token = strtok(NULL, " ");