enforces unique constraint on given entity returns true if entity confirms with constraint false otherwise
| 65 | // enforces unique constraint on given entity |
| 66 | // returns true if entity confirms with constraint false otherwise |
| 67 | bool EnforceUniqueEntity |
| 68 | ( |
| 69 | const Constraint c, // constraint to enforce |
| 70 | const GraphEntity *e, // enforced entity |
| 71 | char **err_msg // report error message |
| 72 | ) { |
| 73 | // validations |
| 74 | ASSERT(c != NULL); |
| 75 | ASSERT(e != NULL); |
| 76 | |
| 77 | UniqueConstraint _c = (UniqueConstraint)c; |
| 78 | |
| 79 | Index idx = _c->idx; |
| 80 | bool holds = false; // return value none-optimistic |
| 81 | RSIndex *rs_idx = Index_RSIndex(idx); |
| 82 | |
| 83 | //-------------------------------------------------------------------------- |
| 84 | // construct a RediSearch query locating entity |
| 85 | //-------------------------------------------------------------------------- |
| 86 | |
| 87 | // TODO: prefer to have the RediSearch query "template" constructed |
| 88 | // once and reused for each entity |
| 89 | |
| 90 | SIType t; |
| 91 | SIValue *v; |
| 92 | uint8_t i = 0; |
| 93 | RSQNode *node = NULL; // RediSearch query node |
| 94 | RSQNode *root = NULL; // root of RediSearch query tree |
| 95 | RSQNode *nodes[_c->n_attr]; |
| 96 | RSResultsIterator *iter = NULL; |
| 97 | const AttributeSet attributes = GraphEntity_GetAttributes(e); |
| 98 | |
| 99 | //-------------------------------------------------------------------------- |
| 100 | // create a RediSearch query |
| 101 | //-------------------------------------------------------------------------- |
| 102 | |
| 103 | for(i = 0; i < _c->n_attr; i++) { |
| 104 | Attribute_ID attr_id = _c->attrs[i]; |
| 105 | const char *field = _c->attr_names[i]; |
| 106 | |
| 107 | // get current attribute from entity |
| 108 | v = AttributeSet_Get(attributes, attr_id); |
| 109 | if(v == ATTRIBUTE_NOTFOUND) { |
| 110 | // entity satisfies constraint in a vacuous truth manner |
| 111 | holds = true; |
| 112 | goto cleanup; |
| 113 | } |
| 114 | |
| 115 | // create RediSearch query node according to entity attr type |
| 116 | t = SI_TYPE(*v); |
| 117 | |
| 118 | if(!(t & SI_INDEXABLE)) { |
| 119 | // TODO: see RediSearch MULTI-VALUE index. |
| 120 | holds = true; |
| 121 | goto cleanup; |
| 122 | } else if(t == T_STRING) { |
| 123 | node = RediSearch_CreateTagNode(rs_idx, field); |
| 124 | RSQNode *child = RediSearch_CreateTagTokenNode(rs_idx, v->stringval); |
nothing calls this directly
no test coverage detected