1 /* Copyright (C) 2014 InfiniDB, Inc.
2 
3    This program is free software; you can redistribute it and/or
4    modify it under the terms of the GNU General Public License
5    as published by the Free Software Foundation; version 2 of
6    the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16    MA 02110-1301, USA. */
17 
18 /****************************************************************************
19 * $Id: func_find_in_set.cpp 2675 2011-06-22 04:58:07Z chao $
20 *
21 *
22 ****************************************************************************/
23 
24 #include <cstdlib>
25 #include <string>
26 #include <sstream>
27 using namespace std;
28 
29 #include <boost/tokenizer.hpp>
30 using namespace boost;
31 
32 #include "functor_int.h"
33 #include "functioncolumn.h"
34 #include "rowgroup.h"
35 #include "calpontsystemcatalog.h"
36 using namespace execplan;
37 
38 #include "dataconvert.h"
39 
40 #include "errorcodes.h"
41 #include "idberrorinfo.h"
42 #include "errorids.h"
43 using namespace logging;
44 
45 #include "collation.h"
46 
47 namespace funcexp
48 {
49 
operationType(FunctionParm & fp,CalpontSystemCatalog::ColType & resultType)50 CalpontSystemCatalog::ColType Func_find_in_set::operationType( FunctionParm& fp, CalpontSystemCatalog::ColType& resultType )
51 {
52     return resultType;
53 }
54 
getIntVal(rowgroup::Row & row,FunctionParm & parm,bool & isNull,CalpontSystemCatalog::ColType & op_ct)55 int64_t Func_find_in_set::getIntVal(rowgroup::Row& row,
56                                     FunctionParm& parm,
57                                     bool& isNull,
58                                     CalpontSystemCatalog::ColType& op_ct)
59 {
60     const string& searchStr = parm[0]->data()->getStrVal(row, isNull);
61     if (isNull)
62         return 0;
63 
64     const string& setString = parm[1]->data()->getStrVal(row, isNull);
65     if (isNull)
66         return 0;
67 
68     if (searchStr.find(",") != string::npos)
69         return 0;
70 
71     if (setString.length() < searchStr.length())
72         return 0;
73 
74     CHARSET_INFO *cs= op_ct.getCharset();
75 
76     my_wc_t wc= 0;
77     const char *str_begin = setString.c_str();
78     const char *str_end = setString.c_str();
79     const char *real_end = str_end + setString.length();
80     const char *find_str = searchStr.c_str();
81     size_t find_str_len = searchStr.length();
82     int position = 0;
83     static const char separator=',';
84     while (1)
85     {
86         int symbol_len;
87         if ((symbol_len= cs->mb_wc(&wc, (uchar*) str_end,
88                                  (uchar*) real_end)) > 0)
89         {
90             const char *substr_end = str_end + symbol_len;
91             bool is_last_item= (substr_end == real_end);
92             bool is_separator = (wc == (my_wc_t) separator);
93             if (is_separator || is_last_item)
94             {
95                 position++;
96                 if (is_last_item && !is_separator)
97                     str_end = substr_end;
98                 if (!cs->strnncoll(str_begin, (size_t) (str_end - str_begin),
99                                  find_str, find_str_len))
100                     return (int64_t) position;
101                 else
102                     str_begin = substr_end;
103             }
104             str_end = substr_end;
105         }
106         else if (str_end - str_begin == 0 &&
107                find_str_len == 0 &&
108                wc == (my_wc_t) separator)
109             return (longlong) ++position;
110         else
111             return 0;
112     }
113     return 0;
114 }
115 
getDoubleVal(rowgroup::Row & row,FunctionParm & parm,bool & isNull,execplan::CalpontSystemCatalog::ColType & ct)116 double Func_find_in_set::getDoubleVal(rowgroup::Row& row,
117                                       FunctionParm& parm,
118                                       bool& isNull,
119                                       execplan::CalpontSystemCatalog::ColType& ct)
120 {
121     return (double)getIntVal(row, parm, isNull, ct);
122 }
123 
124 
getStrVal(rowgroup::Row & row,FunctionParm & parm,bool & isNull,CalpontSystemCatalog::ColType & ct)125 string Func_find_in_set::getStrVal(rowgroup::Row& row,
126                                    FunctionParm& parm,
127                                    bool& isNull,
128                                    CalpontSystemCatalog::ColType& ct)
129 {
130     return intToString(getIntVal(row, parm, isNull, ct));
131 }
132 
getDecimalVal(rowgroup::Row & row,FunctionParm & fp,bool & isNull,execplan::CalpontSystemCatalog::ColType & op_ct)133 execplan::IDB_Decimal Func_find_in_set::getDecimalVal(rowgroup::Row& row,
134         FunctionParm& fp,
135         bool& isNull,
136         execplan::CalpontSystemCatalog::ColType& op_ct)
137 {
138     IDB_Decimal decimal;
139     decimal.value = getIntVal(row, fp, isNull, op_ct);
140     decimal.scale = op_ct.scale;
141     return decimal;
142 }
143 
144 } // namespace funcexp
145 // vim:ts=4 sw=4:
146