Drizzled Public API Documentation

eval0eval.cc
00001 /*****************************************************************************
00002 
00003 Copyright (C) 1997, 2009, Innobase Oy. All Rights Reserved.
00004 
00005 This program is free software; you can redistribute it and/or modify it under
00006 the terms of the GNU General Public License as published by the Free Software
00007 Foundation; version 2 of the License.
00008 
00009 This program is distributed in the hope that it will be useful, but WITHOUT
00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00012 
00013 You should have received a copy of the GNU General Public License along with
00014 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
00015 St, Fifth Floor, Boston, MA 02110-1301 USA
00016 
00017 *****************************************************************************/
00018 
00019 /**************************************************/
00027 #include "eval0eval.h"
00028 
00029 #ifdef UNIV_NONINL
00030 #include "eval0eval.ic"
00031 #endif
00032 
00033 #include "data0data.h"
00034 #include "row0sel.h"
00035 
00037 static ulint  eval_rnd  = 128367121;
00038 
00042 static byte eval_dummy;
00043 
00044 /*****************************************************************/
00051 UNIV_INTERN
00052 byte*
00053 eval_node_alloc_val_buf(
00054 /*====================*/
00055   que_node_t* node, 
00058   ulint   size) 
00059 {
00060   dfield_t* dfield;
00061   byte*   data;
00062 
00063   ut_ad(que_node_get_type(node) == QUE_NODE_SYMBOL
00064         || que_node_get_type(node) == QUE_NODE_FUNC);
00065 
00066   dfield = que_node_get_val(node);
00067 
00068   data = static_cast<unsigned char *>(dfield_get_data(dfield));
00069 
00070   if (data && data != &eval_dummy) {
00071     mem_free(data);
00072   }
00073 
00074   if (size == 0) {
00075     data = &eval_dummy;
00076   } else {
00077     data = static_cast<unsigned char *>(mem_alloc(size));
00078   }
00079 
00080   que_node_set_val_buf_size(node, size);
00081 
00082   dfield_set_data(dfield, data, size);
00083 
00084   return(data);
00085 }
00086 
00087 /*****************************************************************/
00091 UNIV_INTERN
00092 void
00093 eval_node_free_val_buf(
00094 /*===================*/
00095   que_node_t* node) 
00096 {
00097   dfield_t* dfield;
00098   byte*   data;
00099 
00100   ut_ad(que_node_get_type(node) == QUE_NODE_SYMBOL
00101         || que_node_get_type(node) == QUE_NODE_FUNC);
00102 
00103   dfield = que_node_get_val(node);
00104 
00105   data = static_cast<unsigned char *>(dfield_get_data(dfield));
00106 
00107   if (que_node_get_val_buf_size(node) > 0) {
00108     ut_a(data);
00109 
00110     mem_free(data);
00111   }
00112 }
00113 
00114 /*****************************************************************/
00117 UNIV_INTERN
00118 ibool
00119 eval_cmp(
00120 /*=====*/
00121   func_node_t*  cmp_node) 
00122 {
00123   que_node_t* arg1;
00124   que_node_t* arg2;
00125   int   res;
00126   ibool   val;
00127   int   func;
00128 
00129   ut_ad(que_node_get_type(cmp_node) == QUE_NODE_FUNC);
00130 
00131   arg1 = cmp_node->args;
00132   arg2 = que_node_get_next(arg1);
00133 
00134   res = cmp_dfield_dfield(que_node_get_val(arg1),
00135         que_node_get_val(arg2));
00136   val = TRUE;
00137 
00138   func = cmp_node->func;
00139 
00140   if (func == '=') {
00141     if (res != 0) {
00142       val = FALSE;
00143     }
00144   } else if (func == '<') {
00145     if (res != -1) {
00146       val = FALSE;
00147     }
00148   } else if (func == PARS_LE_TOKEN) {
00149     if (res == 1) {
00150       val = FALSE;
00151     }
00152   } else if (func == PARS_NE_TOKEN) {
00153     if (res == 0) {
00154       val = FALSE;
00155     }
00156   } else if (func == PARS_GE_TOKEN) {
00157     if (res == -1) {
00158       val = FALSE;
00159     }
00160   } else {
00161     ut_ad(func == '>');
00162 
00163     if (res != 1) {
00164       val = FALSE;
00165     }
00166   }
00167 
00168   eval_node_set_ibool_val(cmp_node, val);
00169 
00170   return(val);
00171 }
00172 
00173 /*****************************************************************/
00175 UNIV_INLINE
00176 void
00177 eval_logical(
00178 /*=========*/
00179   func_node_t*  logical_node) 
00180 {
00181   que_node_t* arg1;
00182   que_node_t* arg2;
00183   ibool   val1;
00184   ibool   val2 = 0; /* remove warning */
00185   ibool   val = 0;  /* remove warning */
00186   int   func;
00187 
00188   ut_ad(que_node_get_type(logical_node) == QUE_NODE_FUNC);
00189 
00190   arg1 = logical_node->args;
00191   arg2 = que_node_get_next(arg1); /* arg2 is NULL if func is 'NOT' */
00192 
00193   val1 = eval_node_get_ibool_val(arg1);
00194 
00195   if (arg2) {
00196     val2 = eval_node_get_ibool_val(arg2);
00197   }
00198 
00199   func = logical_node->func;
00200 
00201   if (func == PARS_AND_TOKEN) {
00202     val = val1 & val2;
00203   } else if (func == PARS_OR_TOKEN) {
00204     val = val1 | val2;
00205   } else if (func == PARS_NOT_TOKEN) {
00206     val = TRUE - val1;
00207   } else {
00208     ut_error;
00209   }
00210 
00211   eval_node_set_ibool_val(logical_node, val);
00212 }
00213 
00214 /*****************************************************************/
00216 UNIV_INLINE
00217 void
00218 eval_arith(
00219 /*=======*/
00220   func_node_t*  arith_node) 
00221 {
00222   que_node_t* arg1;
00223   que_node_t* arg2;
00224   lint    val1;
00225   lint    val2 = 0; /* remove warning */
00226   lint    val;
00227   int   func;
00228 
00229   ut_ad(que_node_get_type(arith_node) == QUE_NODE_FUNC);
00230 
00231   arg1 = arith_node->args;
00232   arg2 = que_node_get_next(arg1); /* arg2 is NULL if func is unary '-' */
00233 
00234   val1 = eval_node_get_int_val(arg1);
00235 
00236   if (arg2) {
00237     val2 = eval_node_get_int_val(arg2);
00238   }
00239 
00240   func = arith_node->func;
00241 
00242   if (func == '+') {
00243     val = val1 + val2;
00244   } else if ((func == '-') && arg2) {
00245     val = val1 - val2;
00246   } else if (func == '-') {
00247     val = -val1;
00248   } else if (func == '*') {
00249     val = val1 * val2;
00250   } else {
00251     ut_ad(func == '/');
00252     val = val1 / val2;
00253   }
00254 
00255   eval_node_set_int_val(arith_node, val);
00256 }
00257 
00258 /*****************************************************************/
00260 UNIV_INLINE
00261 void
00262 eval_aggregate(
00263 /*===========*/
00264   func_node_t*  node) 
00265 {
00266   que_node_t* arg;
00267   lint    val;
00268   lint    arg_val;
00269   int   func;
00270 
00271   ut_ad(que_node_get_type(node) == QUE_NODE_FUNC);
00272 
00273   val = eval_node_get_int_val(node);
00274 
00275   func = node->func;
00276 
00277   if (func == PARS_COUNT_TOKEN) {
00278 
00279     val = val + 1;
00280   } else {
00281     ut_ad(func == PARS_SUM_TOKEN);
00282 
00283     arg = node->args;
00284     arg_val = eval_node_get_int_val(arg);
00285 
00286     val = val + arg_val;
00287   }
00288 
00289   eval_node_set_int_val(node, val);
00290 }
00291 
00292 /*****************************************************************/
00295 static
00296 void
00297 eval_predefined_2(
00298 /*==============*/
00299   func_node_t*  func_node)  
00300 {
00301   que_node_t* arg;
00302   que_node_t* arg1;
00303   que_node_t* arg2 = 0; /* remove warning (??? bug ???) */
00304   lint    int_val;
00305   byte*   data;
00306   ulint   len1;
00307   ulint   len2;
00308   int   func;
00309   ulint   i;
00310 
00311   ut_ad(que_node_get_type(func_node) == QUE_NODE_FUNC);
00312 
00313   arg1 = func_node->args;
00314 
00315   if (arg1) {
00316     arg2 = que_node_get_next(arg1);
00317   }
00318 
00319   func = func_node->func;
00320 
00321   if (func == PARS_PRINTF_TOKEN) {
00322 
00323     arg = arg1;
00324 
00325     while (arg) {
00326       dfield_print(que_node_get_val(arg));
00327 
00328       arg = que_node_get_next(arg);
00329     }
00330 
00331     putc('\n', stderr);
00332 
00333   } else if (func == PARS_ASSERT_TOKEN) {
00334 
00335     if (!eval_node_get_ibool_val(arg1)) {
00336       fputs("SQL assertion fails in a stored procedure!\n",
00337             stderr);
00338     }
00339 
00340     ut_a(eval_node_get_ibool_val(arg1));
00341 
00342     /* This function, or more precisely, a debug procedure,
00343     returns no value */
00344 
00345   } else if (func == PARS_RND_TOKEN) {
00346 
00347     len1 = (ulint)eval_node_get_int_val(arg1);
00348     len2 = (ulint)eval_node_get_int_val(arg2);
00349 
00350     ut_ad(len2 >= len1);
00351 
00352     if (len2 > len1) {
00353       int_val = (lint) (len1
00354             + (eval_rnd % (len2 - len1 + 1)));
00355     } else {
00356       int_val = (lint) len1;
00357     }
00358 
00359     eval_rnd = ut_rnd_gen_next_ulint(eval_rnd);
00360 
00361     eval_node_set_int_val(func_node, int_val);
00362 
00363   } else if (func == PARS_RND_STR_TOKEN) {
00364 
00365     len1 = (ulint)eval_node_get_int_val(arg1);
00366 
00367     data = eval_node_ensure_val_buf(func_node, len1);
00368 
00369     for (i = 0; i < len1; i++) {
00370       data[i] = (byte)(97 + (eval_rnd % 3));
00371 
00372       eval_rnd = ut_rnd_gen_next_ulint(eval_rnd);
00373     }
00374   } else {
00375     ut_error;
00376   }
00377 }
00378 
00379 /*****************************************************************/
00381 UNIV_INLINE
00382 void
00383 eval_notfound(
00384 /*==========*/
00385   func_node_t*  func_node)  
00386 {
00387   sym_node_t* cursor;
00388   sel_node_t* sel_node;
00389   ibool   ibool_val;
00390 
00391   ut_ad(func_node->func == PARS_NOTFOUND_TOKEN);
00392 
00393   cursor = static_cast<sym_node_t *>(func_node->args);
00394 
00395   ut_ad(que_node_get_type(cursor) == QUE_NODE_SYMBOL);
00396 
00397   if (cursor->token_type == SYM_LIT) {
00398 
00399     ut_ad(ut_memcmp(dfield_get_data(que_node_get_val(cursor)),
00400         "SQL", 3) == 0);
00401 
00402     sel_node = cursor->sym_table->query_graph->last_sel_node;
00403   } else {
00404     sel_node = cursor->alias->cursor_def;
00405   }
00406 
00407   if (sel_node->state == SEL_NODE_NO_MORE_ROWS) {
00408     ibool_val = TRUE;
00409   } else {
00410     ibool_val = FALSE;
00411   }
00412 
00413   eval_node_set_ibool_val(func_node, ibool_val);
00414 }
00415 
00416 /*****************************************************************/
00418 UNIV_INLINE
00419 void
00420 eval_substr(
00421 /*========*/
00422   func_node_t*  func_node)  
00423 {
00424   que_node_t* arg1;
00425   que_node_t* arg2;
00426   que_node_t* arg3;
00427   dfield_t* dfield;
00428   byte*   str1;
00429   ulint   len1;
00430   ulint   len2;
00431 
00432   arg1 = func_node->args;
00433   arg2 = que_node_get_next(arg1);
00434 
00435   ut_ad(func_node->func == PARS_SUBSTR_TOKEN);
00436 
00437   arg3 = que_node_get_next(arg2);
00438 
00439   str1 = static_cast<unsigned char *>(dfield_get_data(que_node_get_val(arg1)));
00440 
00441   len1 = (ulint)eval_node_get_int_val(arg2);
00442   len2 = (ulint)eval_node_get_int_val(arg3);
00443 
00444   dfield = que_node_get_val(func_node);
00445 
00446   dfield_set_data(dfield, str1 + len1, len2);
00447 }
00448 
00449 /*****************************************************************/
00451 static
00452 void
00453 eval_replstr(
00454 /*=========*/
00455   func_node_t*  func_node)  
00456 {
00457   que_node_t* arg1;
00458   que_node_t* arg2;
00459   que_node_t* arg3;
00460   que_node_t* arg4;
00461   byte*   str1;
00462   byte*   str2;
00463   ulint   len1;
00464   ulint   len2;
00465 
00466   arg1 = func_node->args;
00467   arg2 = que_node_get_next(arg1);
00468 
00469   ut_ad(que_node_get_type(arg1) == QUE_NODE_SYMBOL);
00470 
00471   arg3 = que_node_get_next(arg2);
00472   arg4 = que_node_get_next(arg3);
00473 
00474   str1 = static_cast<unsigned char *>(dfield_get_data(que_node_get_val(arg1)));
00475   str2 = static_cast<unsigned char *>(dfield_get_data(que_node_get_val(arg2)));
00476 
00477   len1 = (ulint)eval_node_get_int_val(arg3);
00478   len2 = (ulint)eval_node_get_int_val(arg4);
00479 
00480   if ((dfield_get_len(que_node_get_val(arg1)) < len1 + len2)
00481       || (dfield_get_len(que_node_get_val(arg2)) < len2)) {
00482 
00483     ut_error;
00484   }
00485 
00486   ut_memcpy(str1 + len1, str2, len2);
00487 }
00488 
00489 /*****************************************************************/
00491 static
00492 void
00493 eval_instr(
00494 /*=======*/
00495   func_node_t*  func_node)  
00496 {
00497   que_node_t* arg1;
00498   que_node_t* arg2;
00499   dfield_t* dfield1;
00500   dfield_t* dfield2;
00501   lint    int_val;
00502   byte*   str1;
00503   byte*   str2;
00504   byte    match_char;
00505   ulint   len1;
00506   ulint   len2;
00507   ulint   i;
00508   ulint   j;
00509 
00510   arg1 = func_node->args;
00511   arg2 = que_node_get_next(arg1);
00512 
00513   dfield1 = que_node_get_val(arg1);
00514   dfield2 = que_node_get_val(arg2);
00515 
00516   str1 = static_cast<unsigned char *>(dfield_get_data(dfield1));
00517   str2 = static_cast<unsigned char *>(dfield_get_data(dfield2));
00518 
00519   len1 = dfield_get_len(dfield1);
00520   len2 = dfield_get_len(dfield2);
00521 
00522   if (len2 == 0) {
00523     ut_error;
00524   }
00525 
00526   match_char = str2[0];
00527 
00528   for (i = 0; i < len1; i++) {
00529     /* In this outer loop, the number of matched characters is 0 */
00530 
00531     if (str1[i] == match_char) {
00532 
00533       if (i + len2 > len1) {
00534 
00535         break;
00536       }
00537 
00538       for (j = 1;; j++) {
00539         /* We have already matched j characters */
00540 
00541         if (j == len2) {
00542           int_val = i + 1;
00543 
00544           goto match_found;
00545         }
00546 
00547         if (str1[i + j] != str2[j]) {
00548 
00549           break;
00550         }
00551       }
00552     }
00553   }
00554 
00555   int_val = 0;
00556 
00557 match_found:
00558   eval_node_set_int_val(func_node, int_val);
00559 }
00560 
00561 /*****************************************************************/
00563 UNIV_INLINE
00564 void
00565 eval_binary_to_number(
00566 /*==================*/
00567   func_node_t*  func_node)  
00568 {
00569   que_node_t* arg1;
00570   dfield_t* dfield;
00571   byte*   str1;
00572   byte*   str2;
00573   ulint   len1;
00574   ulint   int_val;
00575 
00576   arg1 = func_node->args;
00577 
00578   dfield = que_node_get_val(arg1);
00579 
00580   str1 = static_cast<unsigned char *>(dfield_get_data(dfield));
00581   len1 = dfield_get_len(dfield);
00582 
00583   if (len1 > 4) {
00584     ut_error;
00585   }
00586 
00587   if (len1 == 4) {
00588     str2 = str1;
00589   } else {
00590     int_val = 0;
00591     str2 = (byte*)&int_val;
00592 
00593     ut_memcpy(str2 + (4 - len1), str1, len1);
00594   }
00595 
00596   eval_node_copy_and_alloc_val(func_node, str2, 4);
00597 }
00598 
00599 /*****************************************************************/
00601 static
00602 void
00603 eval_concat(
00604 /*========*/
00605   func_node_t*  func_node)  
00606 {
00607   que_node_t* arg;
00608   dfield_t* dfield;
00609   byte*   data;
00610   ulint   len;
00611   ulint   len1;
00612 
00613   arg = func_node->args;
00614   len = 0;
00615 
00616   while (arg) {
00617     len1 = dfield_get_len(que_node_get_val(arg));
00618 
00619     len += len1;
00620 
00621     arg = que_node_get_next(arg);
00622   }
00623 
00624   data = eval_node_ensure_val_buf(func_node, len);
00625 
00626   arg = func_node->args;
00627   len = 0;
00628 
00629   while (arg) {
00630     dfield = que_node_get_val(arg);
00631     len1 = dfield_get_len(dfield);
00632 
00633     ut_memcpy(data + len, dfield_get_data(dfield), len1);
00634 
00635     len += len1;
00636 
00637     arg = que_node_get_next(arg);
00638   }
00639 }
00640 
00641 /*****************************************************************/
00647 UNIV_INLINE
00648 void
00649 eval_to_binary(
00650 /*===========*/
00651   func_node_t*  func_node)  
00652 {
00653   que_node_t* arg1;
00654   que_node_t* arg2;
00655   dfield_t* dfield;
00656   byte*   str1;
00657   ulint   len;
00658   ulint   len1;
00659 
00660   arg1 = func_node->args;
00661 
00662   str1 = static_cast<unsigned char *>(dfield_get_data(que_node_get_val(arg1)));
00663 
00664   if (dtype_get_mtype(que_node_get_data_type(arg1)) != DATA_INT) {
00665 
00666     len = dfield_get_len(que_node_get_val(arg1));
00667 
00668     dfield = que_node_get_val(func_node);
00669 
00670     dfield_set_data(dfield, str1, len);
00671 
00672     return;
00673   }
00674 
00675   arg2 = que_node_get_next(arg1);
00676 
00677   len1 = (ulint)eval_node_get_int_val(arg2);
00678 
00679   if (len1 > 4) {
00680 
00681     ut_error;
00682   }
00683 
00684   dfield = que_node_get_val(func_node);
00685 
00686   dfield_set_data(dfield, str1 + (4 - len1), len1);
00687 }
00688 
00689 /*****************************************************************/
00691 UNIV_INLINE
00692 void
00693 eval_predefined(
00694 /*============*/
00695   func_node_t*  func_node)  
00696 {
00697   que_node_t* arg1;
00698   lint    int_val;
00699   byte*   data;
00700   int   func;
00701 
00702   func = func_node->func;
00703 
00704   arg1 = func_node->args;
00705 
00706   if (func == PARS_LENGTH_TOKEN) {
00707 
00708     int_val = (lint)dfield_get_len(que_node_get_val(arg1));
00709 
00710   } else if (func == PARS_TO_CHAR_TOKEN) {
00711 
00712     /* Convert number to character string as a
00713     signed decimal integer. */
00714 
00715     ulint uint_val;
00716     int int_len;
00717 
00718     int_val = eval_node_get_int_val(arg1);
00719 
00720     /* Determine the length of the string. */
00721 
00722     if (int_val == 0) {
00723       int_len = 1; /* the number 0 occupies 1 byte */
00724     } else {
00725       int_len = 0;
00726       if (int_val < 0) {
00727         uint_val = ((ulint) -int_val - 1) + 1;
00728         int_len++; /* reserve space for minus sign */
00729       } else {
00730         uint_val = (ulint) int_val;
00731       }
00732       for (; uint_val > 0; int_len++) {
00733         uint_val /= 10;
00734       }
00735     }
00736 
00737     /* allocate the string */
00738     data = eval_node_ensure_val_buf(func_node, int_len + 1);
00739 
00740     /* add terminating NUL character */
00741     data[int_len] = 0;
00742 
00743     /* convert the number */
00744 
00745     if (int_val == 0) {
00746       data[0] = '0';
00747     } else {
00748       int tmp;
00749       if (int_val < 0) {
00750         data[0] = '-'; /* preceding minus sign */
00751         uint_val = ((ulint) -int_val - 1) + 1;
00752       } else {
00753         uint_val = (ulint) int_val;
00754       }
00755       for (tmp = int_len; uint_val > 0; uint_val /= 10) {
00756         data[--tmp] = (byte)
00757           ('0' + (byte)(uint_val % 10));
00758       }
00759     }
00760 
00761     dfield_set_len(que_node_get_val(func_node), int_len);
00762 
00763     return;
00764 
00765   } else if (func == PARS_TO_NUMBER_TOKEN) {
00766 
00767     int_val = atoi((char*)
00768              dfield_get_data(que_node_get_val(arg1)));
00769 
00770   } else if (func == PARS_SYSDATE_TOKEN) {
00771     int_val = (lint)ut_time();
00772   } else {
00773     eval_predefined_2(func_node);
00774 
00775     return;
00776   }
00777 
00778   eval_node_set_int_val(func_node, int_val);
00779 }
00780 
00781 /*****************************************************************/
00783 UNIV_INTERN
00784 void
00785 eval_func(
00786 /*======*/
00787   func_node_t*  func_node)  
00788 {
00789   que_node_t* arg;
00790   ulint   func_class;
00791   ulint   func;
00792 
00793   ut_ad(que_node_get_type(func_node) == QUE_NODE_FUNC);
00794 
00795   func_class = func_node->func_class;
00796   func = func_node->func;
00797 
00798   arg = func_node->args;
00799 
00800   /* Evaluate first the argument list */
00801   while (arg) {
00802     eval_exp(arg);
00803 
00804     /* The functions are not defined for SQL null argument
00805     values, except for eval_cmp and notfound */
00806 
00807     if (dfield_is_null(que_node_get_val(arg))
00808         && (func_class != PARS_FUNC_CMP)
00809         && (func != PARS_NOTFOUND_TOKEN)
00810         && (func != PARS_PRINTF_TOKEN)) {
00811       ut_error;
00812     }
00813 
00814     arg = que_node_get_next(arg);
00815   }
00816 
00817   if (func_class == PARS_FUNC_CMP) {
00818     eval_cmp(func_node);
00819   } else if (func_class == PARS_FUNC_ARITH) {
00820     eval_arith(func_node);
00821   } else if (func_class == PARS_FUNC_AGGREGATE) {
00822     eval_aggregate(func_node);
00823   } else if (func_class == PARS_FUNC_PREDEFINED) {
00824 
00825     if (func == PARS_NOTFOUND_TOKEN) {
00826       eval_notfound(func_node);
00827     } else if (func == PARS_SUBSTR_TOKEN) {
00828       eval_substr(func_node);
00829     } else if (func == PARS_REPLSTR_TOKEN) {
00830       eval_replstr(func_node);
00831     } else if (func == PARS_INSTR_TOKEN) {
00832       eval_instr(func_node);
00833     } else if (func == PARS_BINARY_TO_NUMBER_TOKEN) {
00834       eval_binary_to_number(func_node);
00835     } else if (func == PARS_CONCAT_TOKEN) {
00836       eval_concat(func_node);
00837     } else if (func == PARS_TO_BINARY_TOKEN) {
00838       eval_to_binary(func_node);
00839     } else {
00840       eval_predefined(func_node);
00841     }
00842   } else {
00843     ut_ad(func_class == PARS_FUNC_LOGICAL);
00844 
00845     eval_logical(func_node);
00846   }
00847 }