ExtRegExp.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/calculator/ExtRegExp.cpp#2 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2004-2009 SQLstream, Inc.
00006 // Copyright (C) 2009-2009 LucidEra, Inc.
00007 //
00008 // This program is free software; you can redistribute it and/or modify it
00009 // under the terms of the GNU General Public License as published by the Free
00010 // Software Foundation; either version 2 of the License, or (at your option)
00011 // any later version approved by The Eigenbase Project.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License
00019 // along with this program; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 */
00022 
00023 #include "fennel/common/CommonPreamble.h"
00024 #include "fennel/calculator/ExtendedInstructionTable.h"
00025 #include "fennel/calculator/ExtendedInstructionContext.h"
00026 #include "fennel/calculator/SqlRegExp.h"
00027 
00028 FENNEL_BEGIN_NAMESPACE
00029 
00030 
00031 // Context for storing cached and reusable pattern and regexp
00032 class ExtRegExpContext : public ExtendedInstructionContext
00033 {
00034 public:
00035     explicit
00036     ExtRegExpContext(
00037         boost::regex const & re,
00038         string const pat) :
00039         regex(re),
00040         pattern(pat)
00041     {
00042     }
00043     boost::regex regex;
00044     string pattern;
00045 };
00046 
00047 
00048 void
00049 strLikeEscapeA(
00050     boost::scoped_ptr<ExtendedInstructionContext>& context,
00051     RegisterRef<bool>* result,
00052     RegisterRef<char*>* matchValue,
00053     RegisterRef<char*>* pattern,
00054     RegisterRef<char*>* escape) // may be NULL if called by strLikeA
00055 {
00056     assert(StandardTypeDescriptor::isTextArray(matchValue->type()));
00057     assert(StandardTypeDescriptor::isTextArray(pattern->type()));
00058 
00059     // SQL99 Part 2 Section 8.5 General Rule 3.a, cases i & ii
00060     if (matchValue->isNull() ||
00061         pattern->isNull() ||
00062         (escape ? escape->isNull() : false)) {
00063         result->toNull();
00064         result->length(0);
00065     } else {
00066         boost::regex* regexP;
00067         string* patP;
00068         ExtRegExpContext* ctxP;
00069 
00070         ctxP = static_cast<ExtRegExpContext*>(context.get());
00071         if (!ctxP) {
00072             string pat;
00073             SqlLikePrep<1,1>(
00074                 pattern->pointer(),
00075                 pattern->length(),
00076                 (escape ? escape->pointer() : 0),
00077                 (escape ? escape->length() : 0),
00078                 pat);
00079             try {
00080                 boost::regex regex(pat);
00081                 context.reset(new ExtRegExpContext(regex, pat));
00082             } catch (boost::bad_expression badexp) {
00083                 // SQL99 Part 2 Section 8.5 General Rule 3.b.i2 *seems* like
00084                 // best fit here.
00085                 // Data Exception - Invalid Escape Sequence
00086                 throw "22025";
00087             }
00088             // get context anew
00089             ctxP = static_cast<ExtRegExpContext*>(context.get());
00090         }
00091         regexP = &(ctxP->regex);
00092         patP = &(ctxP->pattern);
00093 
00094         result->value(
00095             SqlRegExp<1,1>(
00096                 matchValue->pointer(),
00097                 matchValue->length(),
00098                 pattern->length(),
00099                 *regexP));
00100     }
00101 }
00102 
00103 void
00104 strLikeA(
00105     boost::scoped_ptr<ExtendedInstructionContext>& context,
00106     RegisterRef<bool>* result,
00107     RegisterRef<char*>* matchValue,
00108     RegisterRef<char*>* pattern)
00109 {
00110     strLikeEscapeA(context, result, matchValue, pattern, 0);
00111 }
00112 
00113 
00114 // escape may be NULL if called by strSimilarA
00115 void
00116 strSimilarEscapeA(
00117     boost::scoped_ptr<ExtendedInstructionContext>& context,
00118     RegisterRef<bool>* result,
00119     RegisterRef<char*>* matchValue,
00120     RegisterRef<char*>* pattern,
00121     RegisterRef<char*>* escape)
00122 {
00123     assert(StandardTypeDescriptor::isTextArray(matchValue->type()));
00124     assert(StandardTypeDescriptor::isTextArray(pattern->type()));
00125 
00126     // SQL2003 Part 2 Section 8.5 General Rule 4.a,b
00127     if (matchValue->isNull() ||
00128         pattern->isNull() ||
00129         (escape ? escape->isNull() : false)) {
00130         result->toNull();
00131         result->length(0);
00132     } else {
00133         boost::regex* regexP;
00134         string* patP;
00135         ExtRegExpContext* ctxP;
00136 
00137         ctxP = static_cast<ExtRegExpContext*>(context.get());
00138         if (!ctxP) {
00139             string pat;
00140             SqlSimilarPrep<1,1>(
00141                 pattern->pointer(),
00142                 pattern->length(),
00143                 (escape ? escape->pointer() : 0),
00144                 (escape ? escape->length() : 0),
00145                 pat);
00146             try {
00147                 boost::regex regex(pat);
00148                 context.reset(new ExtRegExpContext(regex, pat));
00149             } catch (boost::bad_expression badexp) {
00150                 // SQL2003 Part 2 Section 8.6 General Rule 2
00151                 // Data Exception - Invalid Regular Expression
00152                 throw "2201B";
00153             }
00154             // get context anew
00155             ctxP = static_cast<ExtRegExpContext*>(context.get());
00156         }
00157         regexP = &(ctxP->regex);
00158         patP = &(ctxP->pattern);
00159 
00160         result->value(
00161             SqlRegExp<1,1>(
00162                 matchValue->pointer(),
00163                 matchValue->length(),
00164                 pattern->length(),
00165                 *regexP));
00166     }
00167 }
00168 
00169 void
00170 strSimilarA(
00171     boost::scoped_ptr<ExtendedInstructionContext>& context,
00172     RegisterRef<bool>* result,
00173     RegisterRef<char*>* matchValue,
00174     RegisterRef<char*>* pattern)
00175 {
00176     strSimilarEscapeA(context, result, matchValue, pattern, 0);
00177 }
00178 
00179 void
00180 ExtRegExpRegister(ExtendedInstructionTable* eit)
00181 {
00182     assert(eit != NULL);
00183 
00184     // JK 2004/5/27: Are all of these combinations really needed?
00185     int i;
00186     for (i = 0; i < 8; i++) {
00187         vector<StandardTypeDescriptorOrdinal> params;
00188 
00189         params.push_back(STANDARD_TYPE_BOOL);
00190 
00191         if (i & 0x01) {
00192             params.push_back(STANDARD_TYPE_CHAR);
00193         } else {
00194             params.push_back(STANDARD_TYPE_VARCHAR);
00195         }
00196         if (i & 0x02) {
00197             params.push_back(STANDARD_TYPE_CHAR);
00198         } else {
00199             params.push_back(STANDARD_TYPE_VARCHAR);
00200         }
00201 
00202         eit->add(
00203             "strLikeA3", params,
00204             (ExtendedInstruction3Context<bool, char*, char*>*) NULL,
00205             &strLikeA);
00206         eit->add(
00207             "strSimilarA3", params,
00208             (ExtendedInstruction3Context<bool, char*, char*>*) NULL,
00209             &strSimilarA);
00210 
00211         // tack on escape parameter
00212         if (i & 0x04) {
00213             params.push_back(STANDARD_TYPE_CHAR);
00214         } else {
00215             params.push_back(STANDARD_TYPE_VARCHAR);
00216         }
00217 
00218         eit->add(
00219             "strLikeA4", params,
00220             (ExtendedInstruction4Context<bool, char*, char*, char*>*) NULL,
00221             &strLikeEscapeA);
00222         eit->add(
00223             "strSimilarA4", params,
00224             (ExtendedInstruction4Context<bool, char*, char*, char*>*) NULL,
00225             &strSimilarEscapeA);
00226     }
00227 }
00228 
00229 
00230 FENNEL_END_NAMESPACE
00231 
00232 // End ExtRegExp.cpp

Generated on Mon Jun 22 04:00:17 2009 for Fennel by  doxygen 1.5.1