Changeset: 82eb036255ec for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=82eb036255ec
Modified Files:
        monetdb5/modules/mal/pcre.c
Branch: Jun2020
Log Message:

Cleanning PCRElike4 call (I know it's just for a single string, but makes the 
implementation pair with the bulk implmentation in BATPCRElike3)


diffs (293 lines):

diff --git a/monetdb5/modules/mal/pcre.c b/monetdb5/modules/mal/pcre.c
--- a/monetdb5/modules/mal/pcre.c
+++ b/monetdb5/modules/mal/pcre.c
@@ -382,6 +382,24 @@ re_simple(const char *pat, unsigned char
        return true;
 }
 
+static bool
+re_is_pattern_properly_escaped(const char *pat, unsigned char esc)
+{
+       bool escaped = false;
+
+       if (pat == 0)
+               return true;
+       while (*pat) {
+               if (escaped) {
+                       escaped = false;
+               } else if ((unsigned char) *pat == esc) {
+                       escaped = true;
+               }
+               pat++;
+       }
+       return escaped ? false : true;
+}
+
 static inline bool
 is_strcmpable(const char *pat, const char *esc)
 {
@@ -895,7 +913,7 @@ re_like_proj(BAT **bnp, BAT *b, const ch
 
        assert(ATOMstorage(b->ttype) == TYPE_str);
 
-       bn = COLnew(0, TYPE_bit, BATcount(b), TRANSIENT);
+       bn = COLnew(0, TYPE_bit, q, TRANSIENT);
        if (bn == NULL) {
                msg = createException(MAL, "pcre.likeselect", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
                goto bailout;
@@ -946,7 +964,7 @@ bailout:
                if (msg) {
                        BBPreclaim(bn);
                } else {
-                       BATsetcount(bn, BATcount(b));
+                       BATsetcount(bn, q);
                        bn->tsorted = false;
                        bn->trevsorted = false;
                        *bnp = bn;
@@ -1719,35 +1737,88 @@ PCREsql2pcre(str *ret, const str *pat, c
 }
 
 static str
-PCRElike4(bit *ret, const str *s, const str *pat, const str *esc, const bit 
*isens)
+choose_like_path(char **ppat, bool *use_re, bool *use_strcmp, bool *empty, 
const str *pat, const str *esc, const bit *caseignore)
 {
-       char *ppat = NULL;
-       str r = sql2pcre(&ppat, *pat, *esc);
+       str res = MAL_SUCCEED;
+       *use_re = false;
+       *use_strcmp = false;
+       *empty = false;
 
-       if (!r) {
-               assert(ppat);
-               if (strNil(*pat) || strNil(*s) || strNil(*esc)) {
-                       *ret = bit_nil;
-               } else if (strNil(ppat)) {
-                       *ret = FALSE;
-                       if (*isens) {
-                               if (mystrcasecmp(*s, *pat) == 0)
-                                       *ret = TRUE;
-                       } else {
-                               if (strcmp(*s, *pat) == 0)
-                                       *ret = TRUE;
-                       }
+       if (strNil(*pat) || strNil(*esc)) {
+               *empty = true;
+       } else {
+               if (!re_is_pattern_properly_escaped(*pat, (unsigned char) 
**esc))
+                       throw(MAL, "pcre.sql2pcre", SQLSTATE(22019) 
ILLEGAL_ARGUMENT ": (I)LIKE pattern must not end with escape character");
+               if (is_strcmpable(*pat, *esc)) {
+                       *use_re = true;
+                       *use_strcmp = true;
+               } else if (re_simple(*pat, (unsigned char) **esc)) {
+                       *use_re = true;
                } else {
-                       if (*isens) {
-                               r = PCREimatch(ret, s, &ppat);
-                       } else {
-                               r = PCREmatch(ret, s, &ppat);
+                       if ((res = sql2pcre(ppat, *pat, *esc)) != MAL_SUCCEED)
+                               return res;
+                       if (strNil(*ppat)) {
+                               GDKfree(*ppat);
+                               *ppat = NULL;
+                               if (*caseignore) {
+                                       if (!(*ppat = GDKmalloc(strlen(*pat) + 
3)))
+                                               throw(MAL, 
"algebra.likeselect", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+                                       stpcpy(stpcpy(stpcpy(*ppat, "^"), 
*pat), "$");
+                               }
                        }
                }
        }
-       if (ppat)
-               GDKfree(ppat);
-       return r;
+       return res;
+}
+
+static str
+PCRElike4(bit *ret, const str *s, const str *pat, const str *esc, const bit 
*isens)
+{
+       str res = MAL_SUCCEED;
+       char *ppat = NULL;
+       bool use_re = false, use_strcmp = false, isnull = false;
+       uint32_t *wpat = NULL;
+       struct RE *re = NULL;
+
+       if ((res = choose_like_path(&ppat, &use_re, &use_strcmp, &isnull, pat, 
esc, isens)) != MAL_SUCCEED)
+               return res;
+
+       if (strNil(*s)) {
+               *ret = bit_nil;
+       } else if (use_re) {
+               if (use_strcmp) {
+                       if (*isens) {
+                               if (!(wpat = utf8stoucs(*pat))) {
+                                       res = createException(MAL, 
"pcre.like4", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+                                       goto bailout;
+                               }
+                               *ret = mywstrcasecmp(*s, wpat) == 0;
+                       } else {
+                               *ret = strcmp(*s, *pat) == 0;
+                       }
+               } else {
+                       if (!(re = re_create(*pat, *isens, (unsigned char) 
**esc))) {
+                               res = createException(MAL, "pcre.like4", 
SQLSTATE(HY013) MAL_MALLOC_FAIL);
+                               goto bailout;
+                       }
+                       *ret = *isens ? re_match_ignore(*s, re) : 
re_match_no_ignore(*s, re);
+               }
+       } else if (ppat == NULL) {
+               /* no pattern and no special characters: can use normal strcmp 
*/
+               if (isnull)
+                       *ret = bit_nil;
+               else
+                       *ret = *isens ? mystrcasecmp(*s, *pat) == 0 : 
strcmp(*s, *pat) == 0;
+       } else {
+               res = *isens ? PCREimatch(ret, s, &ppat) : PCREmatch(ret, s, 
&ppat);
+       }
+
+bailout:
+       if (re)
+               re_destroy(re);
+       GDKfree(wpat);
+       GDKfree(ppat);
+       return res;
 }
 
 str
@@ -1826,38 +1897,6 @@ PCREnotilike2(bit *ret, const str *s, co
        return MAL_SUCCEED;
 }
 
-/* try if a simple list of keywords works */
-static str
-choose_like_path(char **ppat, bool *use_re, bool *use_strcmp, bool *empty, 
const str *pat, const str *esc, const bit *caseignore)
-{
-       *use_re = false;
-       *use_strcmp = false;
-       *empty = false;
-
-       if (strNil(*pat) || strNil(*esc)) {
-               *empty = true;
-       } else if (is_strcmpable(*pat, *esc)) {
-               *use_re = true;
-               *use_strcmp = true;
-       } else if (re_simple(*pat, (unsigned char) **esc)) {
-               *use_re = true;
-       } else {
-               str res = sql2pcre(ppat, *pat, *esc);
-               if (res != MAL_SUCCEED)
-                       return res;
-               if (strNil(*ppat)) {
-                       GDKfree(*ppat);
-                       *ppat = NULL;
-                       if (*caseignore) {
-                               if (!(*ppat = GDKmalloc(strlen(*pat) + 3)))
-                                       throw(MAL, "algebra.likeselect", 
SQLSTATE(HY013) MAL_MALLOC_FAIL);
-                               stpcpy(stpcpy(stpcpy(*ppat, "^"), *pat), "$");
-                       }
-               }
-       }
-       return MAL_SUCCEED;
-}
-
 #define PCRE_LIKE_BODY(LOOP_BODY, RES1, RES2) \
        do { \
                if (b->tnonil) { \
@@ -1981,32 +2020,11 @@ bailout:
        return msg;
 }
 
-#define do_pcre_simple_scanloop(FUNC) \
-       do { \
-               if (b->tnonil) { \
-                       for (BUN p = 0; p < q; p++) {   \
-                               const char *restrict s = BUNtail(bi, p); \
-                               br[p] = FUNC; \
-                       }       \
-               } else { \
-                       for (BUN p = 0; p < q; p++) { \
-                               const char *restrict s = BUNtail(bi, p); \
-                               if (*s == '\200') { \
-                                       br[p] = bit_nil; \
-                                       r->tnonil = false; \
-                                       r->tnil = true; \
-                               } else { \
-                                       br[p] = FUNC; \
-                               } \
-                       } \
-               } \
-       } while (0)
-
 static str
 BATPCRElike3(bat *ret, const bat *bid, const str *pat, const str *esc, const 
bit *isens, const bit *not)
 {
        str res = MAL_SUCCEED;
-       BAT *b = NULL, *r = NULL;
+       BAT *b = NULL, *bn = NULL;
        char *ppat = NULL;
        bool use_re = false, use_strcmp = false, allnulls = false;
 
@@ -2019,44 +2037,44 @@ BATPCRElike3(bat *ret, const bat *bid, c
        }
 
        if (use_re) {
-               res = re_like_proj(&r, b, *pat, (bool) *isens, (bool) *not, 
use_strcmp, (unsigned char) **esc);
+               res = re_like_proj(&bn, b, *pat, (bool) *isens, (bool) *not, 
use_strcmp, (unsigned char) **esc);
        } else if (ppat == NULL) {
                /* no pattern and no special characters: can use normal strcmp 
loop */
-               r = COLnew(b->hseqbase, TYPE_bit, BATcount(b), TRANSIENT);
-               if (r == NULL) {
+               BUN q = BATcount(b);
+               bn = COLnew(b->hseqbase, TYPE_bit, q, TRANSIENT);
+               if (bn == NULL) {
                        res = createException(MAL, "pcre.like3", 
SQLSTATE(HY013) MAL_MALLOC_FAIL);
                } else {
-                       BUN q = BATcount(b);
-                       bit *restrict br = (bit*)Tloc(r, 0);
+                       bit *restrict res = (bit*)Tloc(bn, 0);
 
                        if (allnulls) {
                                for (BUN p = 0; p < q; p++)
-                                       br[p] = bit_nil;
-                               r->tnonil = false;
-                               r->tnil = true;
-                               r->tsorted = true;
-                               r->trevsorted = true;
+                                       res[p] = bit_nil;
+                               bn->tnonil = false;
+                               bn->tnil = true;
+                               bn->tsorted = true;
+                               bn->trevsorted = true;
                        } else {
                                BATiter bi = bat_iterator(b);
-                               const char *dpat = *pat;
+                               const char *dpat = *pat, *restrict v;
 
                                if (*not)
-                                       do_pcre_simple_scanloop(strcmp(s, dpat) 
!= 0);
+                                       proj_scanloop(strcmp(v, dpat) != 0);
                                else
-                                       do_pcre_simple_scanloop(strcmp(s, dpat) 
== 0);
+                                       proj_scanloop(strcmp(v, dpat) == 0);
                        }
-                       BATsetcount(r, BATcount(b));
+                       BATsetcount(bn, q);
                }
        } else {
-               res = pcre_like(&r, b, ppat, (bool) *isens, (bool) *not);
+               res = pcre_like(&bn, b, ppat, (bool) *isens, (bool) *not);
        }
 
        GDKfree(ppat);
        BBPunfix(b->batCacheid);
        if (res != MAL_SUCCEED)
                return res;
-       assert(r);
-       BBPkeepref(*ret = r->batCacheid);
+       assert(bn);
+       BBPkeepref(*ret = bn->batCacheid);
        return MAL_SUCCEED;
 }
 
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to