/ Check-in [8398f77c]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add an implementation of the REGEXP operator and function. Only defined if compiled with SQLITE_ENABLE_REGEXP.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | regexp
Files: files | file ages | folders
SHA1: 8398f77c5a689c795c5b1e8eea41a3b128dba2fd
User & Date: drh 2012-09-12 18:45:31
Context
2012-09-12
18:45
Add an implementation of the REGEXP operator and function. Only defined if compiled with SQLITE_ENABLE_REGEXP. Closed-Leaf check-in: 8398f77c user: drh tags: regexp
00:11
Update version number to 3.7.15. Delete some obsolete build scripts. check-in: 9402f81f user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/ctime.c.

109
110
111
112
113
114
115



116
117
118
119
120
121
122
  "ENABLE_MEMSYS3",
#endif
#ifdef SQLITE_ENABLE_MEMSYS5
  "ENABLE_MEMSYS5",
#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
  "ENABLE_OVERSIZE_CELL_CHECK",



#endif
#ifdef SQLITE_ENABLE_RTREE
  "ENABLE_RTREE",
#endif
#ifdef SQLITE_ENABLE_STAT3
  "ENABLE_STAT3",
#endif







>
>
>







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  "ENABLE_MEMSYS3",
#endif
#ifdef SQLITE_ENABLE_MEMSYS5
  "ENABLE_MEMSYS5",
#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
  "ENABLE_OVERSIZE_CELL_CHECK",
#endif
#ifdef SQLITE_ENABLE_REGEXP
  "ENABLE_REGEXP",
#endif
#ifdef SQLITE_ENABLE_RTREE
  "ENABLE_RTREE",
#endif
#ifdef SQLITE_ENABLE_STAT3
  "ENABLE_STAT3",
#endif

Changes to src/func.c.

709
710
711
712
713
714
715


























































716
717
718
719
720
721
722
....
1586
1587
1588
1589
1590
1591
1592




1593
1594
1595
1596
1597
1598
1599
    sqlite3_like_count++;
#endif
    
    sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
  }
}



























































/*
** Implementation of the NULLIF(x,y) function.  The result is the first
** argument if the arguments are different.  The result is NULL if the
** arguments are equal to each other.
*/
static void nullifFunc(
  sqlite3_context *context,
................................................................................
  #ifdef SQLITE_CASE_SENSITIVE_LIKE
    LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
    LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
  #else
    LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
    LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
  #endif




  };

  int i;
  FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
  FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc);

  for(i=0; i<ArraySize(aBuiltinFunc); i++){







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>







709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
....
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
    sqlite3_like_count++;
#endif
    
    sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
  }
}

#if defined(SQLITE_ENABLE_REGEXP)
#include <sys/types.h>
#include <regex.h>

/*
** Free a regex_t object obtained from sqlite_malloc().
*/
static void regexpFree(void *pToFree){
  regex_t *pRe = (regex_t*)pToFree;
  regfree(pRe);
  sqlite3_free(pRe);
}

/*
** Implementation of the regexp() SQL function.  This function implements
** the build-in REGEXP operator.  The first argument to the function is the
** pattern and the second argument is the string.  So, the SQL statements:
**
**       A REGEXP B
**
** is implemented as regexp(B,A).
*/
static void regexpFunc(
  sqlite3_context *context, 
  int argc, 
  sqlite3_value **argv
){
  regex_t *pRe;
  int rc;
  char zErr[100];

  pRe = sqlite3_get_auxdata(context, 0);
  if( pRe==0 ){
    pRe = sqlite3_malloc( sizeof(*pRe) );
    if( pRe==0 ){
      sqlite3_result_error_nomem(context);
      return;
    }
    memset(pRe, 0, sizeof(*pRe));
    rc = regcomp(pRe, (const char*)sqlite3_value_text(argv[0]),
                 REG_NOSUB|REG_EXTENDED);
    if( rc ){
      regerror(rc, pRe, zErr, sizeof(zErr));
      sqlite3_result_error(context, zErr, -1);
      regfree(pRe);
    }else{
      sqlite3_set_auxdata(context, 0, pRe, regexpFree);
    }
  }
  rc = regexec(pRe, (const char*)sqlite3_value_text(argv[1]), 0, 0, 0);
  if( rc==0 ){
    sqlite3_result_int(context, 1);
  }else{
    sqlite3_result_int(context, 0);
  }
}
#endif /* defined(SQLITE_ENABLE_REGEXP) */

/*
** Implementation of the NULLIF(x,y) function.  The result is the first
** argument if the arguments are different.  The result is NULL if the
** arguments are equal to each other.
*/
static void nullifFunc(
  sqlite3_context *context,
................................................................................
  #ifdef SQLITE_CASE_SENSITIVE_LIKE
    LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
    LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
  #else
    LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
    LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
  #endif

#if defined(SQLITE_ENABLE_REGEXP)
    FUNCTION(regexp,             2, 0, 0, regexpFunc       ),
#endif
  };

  int i;
  FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
  FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc);

  for(i=0; i<ArraySize(aBuiltinFunc); i++){

Changes to test/e_expr.test.

1059
1060
1061
1062
1063
1064
1065

1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078

1079
1080
1081
1082
1083
1084
1085
do_execsql_test e_expr-17.3.1 { SELECT 'abc' GLOB 'def' } 1
do_test         e_expr-17.3.2 { set globargs } {def abc}
set ::globargs [list]
do_execsql_test e_expr-17.3.3 { SELECT 'X' NOT GLOB 'Y' } 0
do_test         e_expr-17.3.4 { set globargs } {Y X}
sqlite3 db test.db


# EVIDENCE-OF: R-41650-20872 No regexp() user function is defined by
# default and so use of the REGEXP operator will normally result in an
# error message.
#
#   There is a regexp function if ICU is enabled though.
#
ifcapable !icu {
  do_catchsql_test e_expr-18.1.1 { 
    SELECT regexp('abc', 'def') 
  } {1 {no such function: regexp}}
  do_catchsql_test e_expr-18.1.2 { 
    SELECT 'abc' REGEXP 'def'
  } {1 {no such function: REGEXP}}

}

# EVIDENCE-OF: R-33693-50180 The REGEXP operator is a special syntax for
# the regexp() user function.
#
# EVIDENCE-OF: R-57289-13578 If a application-defined SQL function named
# "regexp" is added at run-time, that function will be called in order







>
|












>







1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
do_execsql_test e_expr-17.3.1 { SELECT 'abc' GLOB 'def' } 1
do_test         e_expr-17.3.2 { set globargs } {def abc}
set ::globargs [list]
do_execsql_test e_expr-17.3.3 { SELECT 'X' NOT GLOB 'Y' } 0
do_test         e_expr-17.3.4 { set globargs } {Y X}
sqlite3 db test.db

if 0 {
# xxxxEVIDENCE-OF: R-41650-20872 No regexp() user function is defined by
# default and so use of the REGEXP operator will normally result in an
# error message.
#
#   There is a regexp function if ICU is enabled though.
#
ifcapable !icu {
  do_catchsql_test e_expr-18.1.1 { 
    SELECT regexp('abc', 'def') 
  } {1 {no such function: regexp}}
  do_catchsql_test e_expr-18.1.2 { 
    SELECT 'abc' REGEXP 'def'
  } {1 {no such function: REGEXP}}
}
}

# EVIDENCE-OF: R-33693-50180 The REGEXP operator is a special syntax for
# the regexp() user function.
#
# EVIDENCE-OF: R-57289-13578 If a application-defined SQL function named
# "regexp" is added at run-time, that function will be called in order

Changes to test/like.test.

110
111
112
113
114
115
116
117

118
119
120
121



122
123
124
125
126
127
128
    PRAGMA case_sensitive_like;  -- No argument, does not change setting.
    SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
  }
} {ABC abc}

# Tests of the REGEXP operator
#
do_test like-2.1 {

  proc test_regexp {a b} {
    return [regexp $a $b]
  }
  db function regexp -argcount 2 test_regexp



  execsql {
    SELECT x FROM t1 WHERE x REGEXP 'abc' ORDER BY 1;
  }
} {{ABC abc xyz} abc abcd}
do_test like-2.2 {
  execsql {
    SELECT x FROM t1 WHERE x REGEXP '^abc' ORDER BY 1;







|
>




>
>
>







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
    PRAGMA case_sensitive_like;  -- No argument, does not change setting.
    SELECT x FROM t1 WHERE x LIKE 'abc' ORDER BY 1;
  }
} {ABC abc}

# Tests of the REGEXP operator
#
db eval {SELECT sqlite_compileoption_used('ENABLE_REGEXP') AS has_regexp} break;
if {$has_regexp==0} {
  proc test_regexp {a b} {
    return [regexp $a $b]
  }
  db function regexp -argcount 2 test_regexp
  puts "# installing substitute REGEXP function"
}
do_test like-2.1 {
  execsql {
    SELECT x FROM t1 WHERE x REGEXP 'abc' ORDER BY 1;
  }
} {{ABC abc xyz} abc abcd}
do_test like-2.2 {
  execsql {
    SELECT x FROM t1 WHERE x REGEXP '^abc' ORDER BY 1;