~drizzle-trunk/drizzle/development

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
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
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
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
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 *
 *  Copyright (C) 2008 Sun Microsystems
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef DRIZZLED_ITEM_H
#define DRIZZLED_ITEM_H

#include <drizzled/dtcollation.h>
#include <mysys/drizzle_time.h>
#include <drizzled/my_decimal.h>
#include <drizzled/sql_bitmap.h>
#include <drizzled/sql_list.h>
#include <drizzled/sql_alloc.h>

class Protocol;
class TableList;
class Item_field;
class Name_resolution_context;
class st_select_lex;
class Item_equal;
class COND_EQUAL;
class user_var_entry;
class Item_sum;
class Item_in_subselect;
class Send_field;
class Field;

void item_init(void);			/* Init item functions */


void dummy_error_processor(Session *session, void *data);
void view_error_processor(Session *session, void *data);


/*************************************************************************/
/*
  Analyzer function
    SYNOPSIS
      argp   in/out IN:  Analysis parameter
                    OUT: Parameter to be passed to the transformer

     RETURN
      true   Invoke the transformer
      false  Don't do it

*/
typedef bool (Item::*Item_analyzer) (unsigned char **argp);
typedef Item* (Item::*Item_transformer) (unsigned char *arg);
typedef void (*Cond_traverser) (const Item *item, void *arg);
typedef bool (Item::*Item_processor) (unsigned char *arg);


class Item: public Sql_alloc
{
  /* Prevent use of these */
  Item(const Item &);
  void operator=(Item &);

  /* Cache of the result of is_expensive(). */
  int8_t is_expensive_cache;
  virtual bool is_expensive_processor(unsigned char *arg);

public:

  enum Type {FIELD_ITEM= 0, 
    FUNC_ITEM,
    SUM_FUNC_ITEM,
    STRING_ITEM,
    INT_ITEM,
    REAL_ITEM,
    NULL_ITEM,
    VARBIN_ITEM,
    COPY_STR_ITEM,
    FIELD_AVG_ITEM,
    DEFAULT_VALUE_ITEM,
    PROC_ITEM,
    COND_ITEM,
    REF_ITEM,
    FIELD_STD_ITEM,
    FIELD_VARIANCE_ITEM,
    INSERT_VALUE_ITEM,
    SUBSELECT_ITEM,
    ROW_ITEM, CACHE_ITEM,
    TYPE_HOLDER,
    PARAM_ITEM,
    DECIMAL_ITEM
  };

  enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };

  enum traverse_order { POSTFIX, PREFIX };

  /* Reuse size, only used by SP local variable assignment, otherwize 0 */
  uint32_t rsize;

  /*
    str_values's main purpose is to be used to cache the value in
    save_in_field
  */
  String str_value;

  /* Name from select */
  char * name;

  /* Original item name (if it was renamed)*/
  char * orig_name;
  Item *next;
  uint32_t max_length;

  /* Length of name */
  uint32_t name_length;

  int8_t marker;
  uint8_t decimals;
  bool maybe_null;			/* If item may be null */
  bool null_value;			/* if item is null */
  bool unsigned_flag;
  bool with_sum_func;
  bool fixed;                        /* If item fixed with fix_fields */
  bool is_autogenerated_name;        /* indicate was name of this Item
                                           autogenerated or set by user */
  DTCollation collation;
  bool with_subselect;               /* If this item is a subselect or some
                                           of its arguments is or contains a
                                           subselect. Computed by fix_fields. */
  Item_result cmp_context;              /* Comparison context */
  // alloc & destruct is done as start of select using sql_alloc
  Item();
  /*
     Constructor used by Item_field, Item_ref & aggregate (sum) functions.
     Used for duplicating lists in processing queries with temporary
     tables
     Also it used for Item_cond_and/Item_cond_or for creating
     top AND/OR structure of WHERE clause to protect it of
     optimisation changes in prepared statements
  */
  Item(Session *session, Item *item);
  virtual ~Item()
  {
#ifdef EXTRA_DEBUG
    name=0;
#endif
  }
  void set_name(const char *str, uint32_t length,
                const CHARSET_INFO * const cs);
  void rename(char *new_name);
  void init_make_field(Send_field *tmp_field,enum enum_field_types type);
  virtual void cleanup();
  virtual void make_field(Send_field *field);
  Field *make_string_field(Table *table);
  virtual bool fix_fields(Session *, Item **);

  /*
    Fix after some tables has been pulled out. Basically re-calculate all
    attributes that are dependent on the tables.
  */
  virtual void fix_after_pullout(st_select_lex *new_parent, Item **ref);

  /*
    should be used in case where we are sure that we do not need
    complete fix_fields() procedure.  */
  inline void quick_fix_field() { fixed= 1; }

  /*
  Save value in field, but don't give any warnings

  NOTES
   This is used to temporary store and retrieve a value in a column,
   for example in opt_range to adjust the key value to fit the column.
  Return: Function returns 1 on overflow and -1 on fatal errors
  */
  int save_in_field_no_warnings(Field *field, bool no_conversions);

  virtual int save_in_field(Field *field, bool no_conversions);
  virtual void save_org_in_field(Field *field)
  { (void) save_in_field(field, 1); }
  virtual int save_safe_in_field(Field *field)
  { return save_in_field(field, 1); }
  virtual bool send(Protocol *protocol, String *str);
  virtual bool eq(const Item *, bool binary_cmp) const;
  virtual Item_result result_type() const { return REAL_RESULT; }
  virtual Item_result cast_to_int_type() const { return result_type(); }
  virtual enum_field_types string_field_type() const;
  virtual enum_field_types field_type() const;
  virtual enum Type type() const =0;

  /*
    Return information about function monotonicity. See comment for
    enum_monotonicity_info for details. This function can only be called
    after fix_fields() call.
  */
  virtual enum_monotonicity_info get_monotonicity_info() const
  { return NON_MONOTONIC; }

  /*
    Convert:
      "func_arg $CMP$ const" half-interval
    into:
      "FUNC(func_arg) $CMP2$ const2"

    SYNOPSIS
      val_int_endpoint()
        left_endp  false  <=> The interval is "x < const" or "x <= const"
                   true   <=> The interval is "x > const" or "x >= const"

        incl_endp  IN   true <=> the comparison is '<' or '>'
                        false <=> the comparison is '<=' or '>='
                   OUT  The same but for the "F(x) $CMP$ F(const)" comparison

    DESCRIPTION
      This function is defined only for unary monotonic functions. The caller
      supplies the source half-interval

         x $CMP$ const

      The value of const is supplied implicitly as the value this item's
      argument, the form of $CMP$ comparison is specified through the
      function's arguments. The calle returns the result interval

         F(x) $CMP2$ F(const)

      passing back F(const) as the return value, and the form of $CMP2$
      through the out parameter. NULL values are assumed to be comparable and
      be less than any non-NULL values.

    RETURN
      The output range bound, which equal to the value of val_int()
        - If the value of the function is NULL then the bound is the
          smallest possible value of INT64_MIN
  */
  virtual int64_t val_int_endpoint(bool left_endp, bool *incl_endp);


  /* valXXX methods must return NULL or 0 or 0.0 if null_value is set. */
  /*
    Return double precision floating point representation of item.

    SYNOPSIS
      val_real()

    RETURN
      In case of NULL value return 0.0 and set null_value flag to true.
      If value is not null null_value flag will be reset to false.
  */
  virtual double val_real()=0;
  /*
    Return integer representation of item.

    SYNOPSIS
      val_int()

    RETURN
      In case of NULL value return 0 and set null_value flag to true.
      If value is not null null_value flag will be reset to false.
  */
  virtual int64_t val_int()=0;
  /*
    This is just a shortcut to avoid the cast. You should still use
    unsigned_flag to check the sign of the item.
  */
  inline uint64_t val_uint() { return (uint64_t) val_int(); }
  /*
    Return string representation of this item object.

    SYNOPSIS
      val_str()
      str   an allocated buffer this or any nested Item object can use to
            store return value of this method.

    NOTE
      Buffer passed via argument  should only be used if the item itself
      doesn't have an own String buffer. In case when the item maintains
      it's own string buffer, it's preferable to return it instead to
      minimize number of mallocs/memcpys.
      The caller of this method can modify returned string, but only in case
      when it was allocated on heap, (is_alloced() is true).  This allows
      the caller to efficiently use a buffer allocated by a child without
      having to allocate a buffer of it's own. The buffer, given to
      val_str() as argument, belongs to the caller and is later used by the
      caller at it's own choosing.
      A few implications from the above:
      - unless you return a string object which only points to your buffer
        but doesn't manages it you should be ready that it will be
        modified.
      - even for not allocated strings (is_alloced() == false) the caller
        can change charset (see Item_func_{typecast/binary}. XXX: is this
        a bug?
      - still you should try to minimize data copying and return internal
        object whenever possible.

    RETURN
      In case of NULL value return 0 (NULL pointer) and set null_value flag
      to true.
      If value is not null null_value flag will be reset to false.
  */
  virtual String *val_str(String *str)=0;
  /*
    Return decimal representation of item with fixed point.

    SYNOPSIS
      val_decimal()
      decimal_buffer  buffer which can be used by Item for returning value
                      (but can be not)

    NOTE
      Returned value should not be changed if it is not the same which was
      passed via argument.

    RETURN
      Return pointer on my_decimal (it can be other then passed via argument)
        if value is not NULL (null_value flag will be reset to false).
      In case of NULL value it return 0 pointer and set null_value flag
        to true.
  */
  virtual my_decimal *val_decimal(my_decimal *decimal_buffer)= 0;
  /*
    Return boolean value of item.

    RETURN
      false value is false or NULL
      true value is true (not equal to 0)
  */
  virtual bool val_bool();
  virtual String *val_nodeset(String*) { return 0; }
  /* Helper functions, see item_sum.cc */
  String *val_string_from_real(String *str);
  String *val_string_from_int(String *str);
  String *val_string_from_decimal(String *str);
  my_decimal *val_decimal_from_real(my_decimal *decimal_value);
  my_decimal *val_decimal_from_int(my_decimal *decimal_value);
  my_decimal *val_decimal_from_string(my_decimal *decimal_value);
  my_decimal *val_decimal_from_date(my_decimal *decimal_value);
  my_decimal *val_decimal_from_time(my_decimal *decimal_value);
  int64_t val_int_from_decimal();
  double val_real_from_decimal();

  int save_time_in_field(Field *field);
  int save_date_in_field(Field *field);
  int save_str_value_in_field(Field *field, String *result);

  virtual Field *get_tmp_table_field(void) { return 0; }
  /* This is also used to create fields in CREATE ... SELECT: */
  virtual Field *tmp_table_field(Table *t_arg);
  virtual const char *full_name(void) const;

  /*
    *result* family of methods is analog of *val* family (see above) but
    return value of result_field of item if it is present. If Item have not
    result field, it return val(). This methods set null_value flag in same
    way as *val* methods do it.
  */
  virtual double  val_result() { return val_real(); }
  virtual int64_t val_int_result() { return val_int(); }
  virtual String *str_result(String* tmp) { return val_str(tmp); }
  virtual my_decimal *val_decimal_result(my_decimal *val)
  { return val_decimal(val); }
  virtual bool val_bool_result() { return val_bool(); }

  /* bit map of tables used by item */
  virtual table_map used_tables() const { return (table_map) 0L; }
  /*
    Return table map of tables that can't be NULL tables (tables that are
    used in a context where if they would contain a NULL row generated
    by a LEFT or RIGHT join, the item would not be true).
    This expression is used on WHERE item to determinate if a LEFT JOIN can be
    converted to a normal join.
    Generally this function should return used_tables() if the function
    would return null if any of the arguments are null
    As this is only used in the beginning of optimization, the value don't
    have to be updated in update_used_tables()
  */
  virtual table_map not_null_tables() const { return used_tables(); }
  /*
    Returns true if this is a simple constant item like an integer, not
    a constant expression. Used in the optimizer to propagate basic constants.
  */
  virtual bool basic_const_item() const { return 0; }
  /* cloning of constant items (0 if it is not const) */
  virtual Item *clone_item() { return 0; }
  virtual cond_result eq_cmp_result() const { return COND_OK; }
  inline uint32_t float_length(uint32_t decimals_par) const
  { return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
  virtual uint32_t decimal_precision() const;
  int decimal_int_part() const;

  /*
    Returns true if this is constant (during query execution, i.e. its value
    will not change until next fix_fields) and its value is known.
  */
  virtual bool const_item() const { return used_tables() == 0; }
  /*
    Returns true if this is constant but its value may be not known yet.
    (Can be used for parameters of prep. stmts or of stored procedures.)
  */
  virtual bool const_during_execution() const
  { return (used_tables() & ~PARAM_TABLE_BIT) == 0; }

  /**
    This method is used for to:
      - to generate a view definition query (SELECT-statement);
      - to generate a SQL-query for EXPLAIN EXTENDED;
      - to generate a SQL-query to be shown in INFORMATION_SCHEMA;
      - debug.

    For more information about view definition query, INFORMATION_SCHEMA
    query and why they should be generated from the Item-tree, @see
    mysql_register_view().
  */
  virtual void print(String *str, enum_query_type query_type);

  void print_item_w_name(String *, enum_query_type query_type);
  virtual void update_used_tables() {}
  virtual void split_sum_func(Session *session, Item **ref_pointer_array,
                              List<Item> &fields);

  /* Called for items that really have to be split */
  void split_sum_func(Session *session, Item **ref_pointer_array,
                      List<Item> &fields,
                      Item **ref, bool skip_registered);

  virtual bool get_date(DRIZZLE_TIME *ltime,uint32_t fuzzydate);
  virtual bool get_time(DRIZZLE_TIME *ltime);
  virtual bool get_date_result(DRIZZLE_TIME *ltime,uint32_t fuzzydate);

  /*
    The method allows to determine nullness of a complex expression
    without fully evaluating it, instead of calling val/result*() then
    checking null_value. Used in Item_func_isnull/Item_func_isnotnull
    and Item_sum_count/Item_sum_count_distinct.
    Any new item which can be NULL must implement this method.
  */
  virtual bool is_null();

  /*
   Make sure the null_value member has a correct value.
  */
  virtual void update_null_value ();

  /*
    Inform the item that there will be no distinction between its result
    being false or NULL.

    NOTE
      This function will be called for eg. Items that are top-level AND-parts
      of the WHERE clause. Items implementing this function (currently
      Item_cond_and and subquery-related item) enable special optimizations
      when they are "top level".
  */
  virtual void top_level_item(void);
  /*
    set field of temporary table for Item which can be switched on temporary
    table during query processing (grouping and so on)
  */
  virtual void set_result_field(Field *field);
  virtual bool is_result_field(void);
  virtual bool is_bool_func(void);
  virtual void save_in_result_field(bool no_conversions);

  /*
    set value of aggregate function in case of no rows for grouping were found
  */
  virtual void no_rows_in_result(void);
  virtual Item *copy_or_same(Session *session);

  virtual Item *copy_andor_structure(Session *session);

  virtual Item *real_item(void);
  virtual Item *get_tmp_table_item(Session *session);

  static const CHARSET_INFO *default_charset();
  virtual const CHARSET_INFO *compare_collation();

  virtual bool walk(Item_processor processor,
                    bool walk_subquery,
                    unsigned char *arg);

  virtual Item* transform(Item_transformer transformer, unsigned char *arg);

  /*
    This function performs a generic "compilation" of the Item tree.
    The process of compilation is assumed to go as follows:

    compile()
    {
      if (this->*some_analyzer(...))
      {
        compile children if any;
        this->*some_transformer(...);
      }
    }

    i.e. analysis is performed top-down while transformation is done
    bottom-up.
  */
  virtual Item* compile(Item_analyzer analyzer, unsigned char **arg_p,
                        Item_transformer transformer, unsigned char *arg_t);

  virtual void traverse_cond(Cond_traverser traverser,
                             void *arg,
                             traverse_order order);

  virtual bool remove_dependence_processor(unsigned char * arg);
  virtual bool remove_fixed(unsigned char * arg);
  virtual bool cleanup_processor(unsigned char *arg);
  virtual bool collect_item_field_processor(unsigned char * arg);
  virtual bool find_item_in_field_list_processor(unsigned char *arg);
  virtual bool change_context_processor(unsigned char *context);
  virtual bool reset_query_id_processor(unsigned char *query_id_arg);
  virtual bool register_field_in_read_map(unsigned char *arg);

  /*
    The next function differs from the previous one that a bitmap to be updated
    is passed as unsigned char *arg.
  */
  virtual bool register_field_in_bitmap(unsigned char *arg);
  virtual bool subst_argument_checker(unsigned char **arg);

  /*
    Check if an expression/function is allowed for a virtual column
    SYNOPSIS
      check_vcol_func_processor()
      arg is just ignored
    RETURN VALUE
      TRUE                           Function not accepted
      FALSE                          Function accepted
  */
  virtual bool check_vcol_func_processor(unsigned char *arg);
  virtual Item *equal_fields_propagator(unsigned char * arg);
  virtual bool set_no_const_sub(unsigned char *arg);
  virtual Item *replace_equal_field(unsigned char * arg);


  /*
    For SP local variable returns pointer to Item representing its
    current value and pointer to current Item otherwise.
  */
  virtual Item *this_item(void);
  virtual const Item *this_item(void) const;

  /*
    For SP local variable returns address of pointer to Item representing its
    current value and pointer passed via parameter otherwise.
  */
  virtual Item **this_item_addr(Session *session, Item **addr_arg);

  // Row emulation
  virtual uint32_t cols();
  virtual Item* element_index(uint32_t i);
  virtual Item** addr(uint32_t i);
  virtual bool check_cols(uint32_t c);
  // It is not row => null inside is impossible
  virtual bool null_inside();
  // used in row subselects to get value of elements
  virtual void bring_value();

  Field *tmp_table_field_from_field_type(Table *table, bool fixed_length);
  virtual Item_field *filed_for_view_update();

  virtual Item *neg_transformer(Session *session);
  virtual Item *update_value_transformer(unsigned char *select_arg);
  virtual Item *safe_charset_converter(const CHARSET_INFO * const tocs);
  void delete_self();

  /*
    result_as_int64_t() must return true for Items representing DATE/TIME
    functions and DATE/TIME table fields.
    Those Items have result_type()==STRING_RESULT (and not INT_RESULT), but
    their values should be compared as integers (because the integer
    representation is more precise than the string one).
  */
  virtual bool result_as_int64_t();
  bool is_datetime();

  /*
    Test whether an expression is expensive to compute. Used during
    optimization to avoid computing expensive expressions during this
    phase. Also used to force temp tables when sorting on expensive
    functions.
    TODO:
    Normally we should have a method:
      cost Item::execution_cost(),
    where 'cost' is either 'double' or some structure of various cost
    parameters.
  */
  virtual bool is_expensive();

  String *check_well_formed_result(String *str, bool send_error= 0);
  bool eq_by_collation(Item *item, bool binary_cmp,
                       const CHARSET_INFO * const cs);

};


class Item_basic_constant :public Item
{
public:
  /* to prevent drop fixed flag (no need parent cleanup call) */
  void cleanup()
  {
    /*
      Restore the original field name as it might not have been allocated
      in the statement memory. If the name is auto generated, it must be
      done again between subsequent executions of a prepared statement.
    */
    if (orig_name)
      name= orig_name;
  }
};


class Item_num: public Item_basic_constant
{
public:
  Item_num() {}                               /* Remove gcc warning */
  virtual Item_num *neg()= 0;
  Item *safe_charset_converter(const CHARSET_INFO * const tocs);
};

class Item_ident :public Item
{
protected:
  /* 
    We have to store initial values of db_name, table_name and field_name
    to be able to restore them during cleanup() because they can be 
    updated during fix_fields() to values from Field object and life-time 
    of those is shorter than life-time of Item_field.
  */
  const char *orig_db_name;
  const char *orig_table_name;
  const char *orig_field_name;

public:
  Name_resolution_context *context;
  const char *db_name;
  const char *table_name;
  const char *field_name;
  bool alias_name_used; /* true if item was resolved against alias */
  /* 
    Cached value of index for this field in table->field array, used by prep. 
    stmts for speeding up their re-execution. Holds NO_CACHED_FIELD_INDEX
    if index value is not known.
  */
  uint32_t cached_field_index;
  /*
    Cached pointer to table which contains this field, used for the same reason
    by prep. stmt. too in case then we have not-fully qualified field.
    0 - means no cached value.
  */
  TableList *cached_table;
  st_select_lex *depended_from;
  Item_ident(Name_resolution_context *context_arg,
             const char *db_name_arg, const char *table_name_arg,
             const char *field_name_arg);
  Item_ident(Session *session, Item_ident *item);
  const char *full_name() const;
  void cleanup();
  bool remove_dependence_processor(unsigned char * arg);
  virtual void print(String *str, enum_query_type query_type);
  virtual bool change_context_processor(unsigned char *cntx)
    { context= (Name_resolution_context *)cntx; return false; }
  friend bool insert_fields(Session *session, Name_resolution_context *context,
                            const char *db_name,
                            const char *table_name, List_iterator<Item> *it,
                            bool any_privileges);
};


class Item_ident_for_show :public Item
{
public:
  Field *field;
  const char *db_name;
  const char *table_name;

  Item_ident_for_show(Field *par_field, const char *db_arg,
                      const char *table_name_arg)
    :field(par_field), db_name(db_arg), table_name(table_name_arg)
  {}

  enum Type type() const { return FIELD_ITEM; }
  double val_real();
  int64_t val_int();
  String *val_str(String *str);
  my_decimal *val_decimal(my_decimal *dec);
  void make_field(Send_field *tmp_field);
};


class Item_field :public Item_ident
{
protected:
  void set_field(Field *field);
public:
  Field *field,*result_field;
  Item_equal *item_equal;
  bool no_const_subst;
  /*
    if any_privileges set to true then here real effective privileges will
    be stored
  */
  uint32_t have_privileges;
  /* field need any privileges (for VIEW creation) */
  bool any_privileges;
  Item_field(Name_resolution_context *context_arg,
             const char *db_arg,const char *table_name_arg,
	     const char *field_name_arg);
  /*
    Constructor needed to process subselect with temporary tables (see Item)
  */
  Item_field(Session *session, Item_field *item);
  /*
    Constructor used inside setup_wild(), ensures that field, table,
    and database names will live as long as Item_field (this is important
    in prepared statements).
  */
  Item_field(Session *session, Name_resolution_context *context_arg, Field *field);
  /*
    If this constructor is used, fix_fields() won't work, because
    db_name, table_name and column_name are unknown. It's necessary to call
    reset_field() before fix_fields() for all fields created this way.
  */
  Item_field(Field *field);
  enum Type type() const { return FIELD_ITEM; }
  bool eq(const Item *item, bool binary_cmp) const;
  double val_real();
  int64_t val_int();
  my_decimal *val_decimal(my_decimal *);
  String *val_str(String*);
  double val_result();
  int64_t val_int_result();
  String *str_result(String* tmp);
  my_decimal *val_decimal_result(my_decimal *);
  bool val_bool_result();
  bool send(Protocol *protocol, String *str_arg);
  void reset_field(Field *f);
  bool fix_fields(Session *, Item **);
  void fix_after_pullout(st_select_lex *new_parent, Item **ref);
  void make_field(Send_field *tmp_field);
  int save_in_field(Field *field,bool no_conversions);
  void save_org_in_field(Field *field);
  table_map used_tables() const;
  enum Item_result result_type () const;
  Item_result cast_to_int_type() const;
  enum_field_types field_type() const;
  enum_monotonicity_info get_monotonicity_info() const
  {
    return MONOTONIC_STRICT_INCREASING;
  }
  int64_t val_int_endpoint(bool left_endp, bool *incl_endp);
  Field *get_tmp_table_field() { return result_field; }
  Field *tmp_table_field(Table *t_arg __attribute__((unused))) { return result_field; }
  bool get_date(DRIZZLE_TIME *ltime,uint32_t fuzzydate);
  bool get_date_result(DRIZZLE_TIME *ltime,uint32_t fuzzydate);
  bool get_time(DRIZZLE_TIME *ltime);
  bool is_null();
  void update_null_value();
  Item *get_tmp_table_item(Session *session);
  bool collect_item_field_processor(unsigned char * arg);
  bool find_item_in_field_list_processor(unsigned char *arg);
  bool register_field_in_read_map(unsigned char *arg);
  bool register_field_in_bitmap(unsigned char *arg);
  bool check_vcol_func_processor(unsigned char *arg __attribute__((unused)))
  { return false; }
  void cleanup();
  bool result_as_int64_t();
  Item_equal *find_item_equal(COND_EQUAL *cond_equal);
  bool subst_argument_checker(unsigned char **arg);
  Item *equal_fields_propagator(unsigned char *arg);
  bool set_no_const_sub(unsigned char *arg);
  Item *replace_equal_field(unsigned char *arg);
  uint32_t max_disp_length();
  Item_field *filed_for_view_update() { return this; }
  Item *safe_charset_converter(const CHARSET_INFO * const tocs);
  int fix_outer_field(Session *session, Field **field, Item **reference);
  virtual Item *update_value_transformer(unsigned char *select_arg);
  virtual void print(String *str, enum_query_type query_type);

  friend class Item_default_value;
  friend class Item_insert_value;
  friend class st_select_lex_unit;
};

class Item_null :public Item_basic_constant
{
public:
  Item_null(char *name_par=0)
  {
    maybe_null= null_value= true;
    max_length= 0;
    name= name_par ? name_par : (char*) "NULL";
    fixed= 1;
    collation.set(&my_charset_bin, DERIVATION_IGNORABLE);
  }
  enum Type type() const { return NULL_ITEM; }
  bool eq(const Item *item, bool binary_cmp) const;
  double val_real();
  int64_t val_int();
  String *val_str(String *str);
  my_decimal *val_decimal(my_decimal *);
  int save_in_field(Field *field, bool no_conversions);
  int save_safe_in_field(Field *field);
  bool send(Protocol *protocol, String *str);
  enum Item_result result_type () const { return STRING_RESULT; }
  enum_field_types field_type() const   { return DRIZZLE_TYPE_NULL; }
  bool basic_const_item() const { return 1; }
  Item *clone_item() { return new Item_null(name); }
  bool is_null() { return 1; }

  virtual inline void print(String *str,
                            enum_query_type query_type __attribute__((unused)))
  {
    str->append(STRING_WITH_LEN("NULL"));
  }

  Item *safe_charset_converter(const CHARSET_INFO * const tocs);
  bool check_vcol_func_processor(unsigned char *arg __attribute__((unused)))
  { return false; }
};

class Item_null_result :public Item_null
{
public:
  Field *result_field;
  Item_null_result() : Item_null(), result_field(0) {}
  bool is_result_field() { return result_field != 0; }
  void save_in_result_field(bool no_conversions)
  {
    save_in_field(result_field, no_conversions);
  }
  bool check_vcol_func_processor(unsigned char *arg __attribute__((unused)))
  { return true; }
};  

/* Item represents one placeholder ('?') of prepared statement */

class Item_param :public Item
{
  char cnvbuf[MAX_FIELD_WIDTH];
  String cnvstr;
  Item *cnvitem;

public:
  enum enum_item_param_state
  {
    NO_VALUE, NULL_VALUE, INT_VALUE, REAL_VALUE,
    STRING_VALUE, TIME_VALUE, LONG_DATA_VALUE,
    DECIMAL_VALUE
  } state;

  /*
    A buffer for string and long data values. Historically all allocated
    values returned from val_str() were treated as eligible to
    modification. I. e. in some cases Item_func_concat can append it's
    second argument to return value of the first one. Because of that we
    can't return the original buffer holding string data from val_str(),
    and have to have one buffer for data and another just pointing to
    the data. This is the latter one and it's returned from val_str().
    Can not be declared inside the union as it's not a POD type.
  */
  String str_value_ptr;
  my_decimal decimal_value;
  union
  {
    int64_t integer;
    double   real;
    /*
      Character sets conversion info for string values.
      Character sets of client and connection defined at bind time are used
      for all conversions, even if one of them is later changed (i.e.
      between subsequent calls to mysql_stmt_execute).
    */
    struct CONVERSION_INFO
    {
      const CHARSET_INFO *character_set_client;
      const CHARSET_INFO *character_set_of_placeholder;
      /*
        This points at character set of connection if conversion
        to it is required (i. e. if placeholder typecode is not BLOB).
        Otherwise it's equal to character_set_client (to simplify
        check in convert_str_value()).
      */
      const CHARSET_INFO *final_character_set_of_str_value;
    } cs_info;
    DRIZZLE_TIME     time;
  } value;

  /* Cached values for virtual methods to save us one switch.  */
  enum Item_result item_result_type;
  enum Type item_type;

  /*
    Used when this item is used in a temporary table.
    This is NOT placeholder metadata sent to client, as this value
    is assigned after sending metadata (in setup_one_conversion_function).
    For example in case of 'SELECT ?' you'll get DRIZZLE_TYPE_STRING both
    in result set and placeholders metadata, no matter what type you will
    supply for this placeholder in mysql_stmt_execute.
  */
  enum enum_field_types param_type;
  /*
    Offset of placeholder inside statement text. Used to create
    no-placeholders version of this statement for the binary log.
  */
  uint32_t pos_in_query;

  Item_param(uint32_t pos_in_query_arg);

  enum Item_result result_type () const { return item_result_type; }
  enum Type type() const { return item_type; }
  enum_field_types field_type() const { return param_type; }

  double val_real();
  int64_t val_int();
  my_decimal *val_decimal(my_decimal*);
  String *val_str(String*);
  bool get_time(DRIZZLE_TIME *tm);
  bool get_date(DRIZZLE_TIME *tm, uint32_t fuzzydate);
  int  save_in_field(Field *field, bool no_conversions);

  void set_null();
  void set_int(int64_t i, uint32_t max_length_arg);
  void set_double(double i);
  void set_decimal(char *str, ulong length);
  bool set_str(const char *str, ulong length);
  bool set_longdata(const char *str, ulong length);
  void set_time(DRIZZLE_TIME *tm, enum enum_drizzle_timestamp_type type,
                uint32_t max_length_arg);
  bool set_from_user_var(Session *session, const user_var_entry *entry);
  void reset();
  /*
    Assign placeholder value from bind data.
    Note, that 'len' has different semantics in embedded library (as we
    don't need to check that packet is not broken there). See
    sql_prepare.cc for details.
  */
  void (*set_param_func)(Item_param *param, unsigned char **pos, ulong len);

  const String *query_val_str(String *str) const;

  bool convert_str_value(Session *session);

  /*
    If value for parameter was not set we treat it as non-const
    so noone will use parameters value in fix_fields still
    parameter is constant during execution.
  */
  virtual table_map used_tables() const
  { return state != NO_VALUE ? (table_map)0 : PARAM_TABLE_BIT; }
  virtual void print(String *str, enum_query_type query_type);
  bool is_null()
  { assert(state != NO_VALUE); return state == NULL_VALUE; }
  bool basic_const_item() const;
  /*
    This method is used to make a copy of a basic constant item when
    propagating constants in the optimizer. The reason to create a new
    item and not use the existing one is not precisely known (2005/04/16).
    Probably we are trying to preserve tree structure of items, in other
    words, avoid pointing at one item from two different nodes of the tree.
    Return a new basic constant item if parameter value is a basic
    constant, assert otherwise. This method is called only if
    basic_const_item returned true.
  */
  Item *safe_charset_converter(const CHARSET_INFO * const tocs);
  Item *clone_item();
  /*
    Implement by-value equality evaluation if parameter value
    is set and is a basic constant (integer, real or string).
    Otherwise return false.
  */
  bool eq(const Item *item, bool binary_cmp) const;
  /** Item is a argument to a limit clause. */
  bool limit_clause_param;
};


class Item_int :public Item_num
{
public:
  int64_t value;
  Item_int(int32_t i,uint32_t length= MY_INT32_NUM_DECIMAL_DIGITS)
    :value((int64_t) i)
    { max_length=length; fixed= 1; }
  Item_int(int64_t i,uint32_t length= MY_INT64_NUM_DECIMAL_DIGITS)
    :value(i)
    { max_length=length; fixed= 1; }
  Item_int(uint64_t i, uint32_t length= MY_INT64_NUM_DECIMAL_DIGITS)
    :value((int64_t)i)
    { max_length=length; fixed= 1; unsigned_flag= 1; }
  Item_int(const char *str_arg,int64_t i,uint32_t length) :value(i)
    { max_length=length; name=(char*) str_arg; fixed= 1; }
  Item_int(const char *str_arg, uint32_t length=64);
  enum Type type() const { return INT_ITEM; }
  enum Item_result result_type () const { return INT_RESULT; }
  enum_field_types field_type() const { return DRIZZLE_TYPE_LONGLONG; }
  int64_t val_int() { assert(fixed == 1); return value; }
  double val_real() { assert(fixed == 1); return (double) value; }
  my_decimal *val_decimal(my_decimal *);
  String *val_str(String*);
  int save_in_field(Field *field, bool no_conversions);
  bool basic_const_item() const { return 1; }
  Item *clone_item() { return new Item_int(name,value,max_length); }
  virtual void print(String *str, enum_query_type query_type);
  Item_num *neg() { value= -value; return this; }
  uint32_t decimal_precision() const
  { return (uint)(max_length - test(value < 0)); }
  bool eq(const Item *, bool binary_cmp) const;
  bool check_vcol_func_processor(unsigned char *arg __attribute__((unused)))
  { return false; }
};


class Item_uint :public Item_int
{
public:
  Item_uint(const char *str_arg, uint32_t length);
  Item_uint(uint64_t i) :Item_int((uint64_t) i, 10) {}
  Item_uint(const char *str_arg, int64_t i, uint32_t length);
  double val_real()
    { assert(fixed == 1); return uint64_t2double((uint64_t)value); }
  String *val_str(String*);
  Item *clone_item() { return new Item_uint(name, value, max_length); }
  int save_in_field(Field *field, bool no_conversions);
  virtual void print(String *str, enum_query_type query_type);
  Item_num *neg ();
  uint32_t decimal_precision() const { return max_length; }
  bool check_vcol_func_processor(unsigned char *arg __attribute__((unused)))
  { return false; }
};


/* decimal (fixed point) constant */
class Item_decimal :public Item_num
{
protected:
  my_decimal decimal_value;
public:
  Item_decimal(const char *str_arg, uint32_t length, const CHARSET_INFO * const charset);
  Item_decimal(const char *str, const my_decimal *val_arg,
               uint32_t decimal_par, uint32_t length);
  Item_decimal(my_decimal *value_par);
  Item_decimal(int64_t val, bool unsig);
  Item_decimal(double val, int precision, int scale);
  Item_decimal(const unsigned char *bin, int precision, int scale);

  enum Type type() const { return DECIMAL_ITEM; }
  enum Item_result result_type () const { return DECIMAL_RESULT; }
  enum_field_types field_type() const { return DRIZZLE_TYPE_NEWDECIMAL; }
  int64_t val_int();
  double val_real();
  String *val_str(String*);
  my_decimal *val_decimal(my_decimal *val __attribute__((unused)))
  { return &decimal_value; }
  int save_in_field(Field *field, bool no_conversions);
  bool basic_const_item() const { return 1; }
  Item *clone_item()
  {
    return new Item_decimal(name, &decimal_value, decimals, max_length);
  }
  virtual void print(String *str, enum_query_type query_type);
  Item_num *neg()
  {
    my_decimal_neg(&decimal_value);
    unsigned_flag= !decimal_value.sign();
    return this;
  }
  uint32_t decimal_precision() const { return decimal_value.precision(); }
  bool eq(const Item *, bool binary_cmp) const;
  void set_decimal_value(my_decimal *value_par);
  bool check_vcol_func_processor(unsigned char *arg __attribute__((unused)))
  { return false; }
};


class Item_float :public Item_num
{
  char *presentation;
public:
  double value;
  // Item_real() :value(0) {}
  Item_float(const char *str_arg, uint32_t length);
  Item_float(const char *str,double val_arg,uint32_t decimal_par,uint32_t length)
    :value(val_arg)
  {
    presentation= name=(char*) str;
    decimals=(uint8_t) decimal_par;
    max_length=length;
    fixed= 1;
  }
  Item_float(double value_par, uint32_t decimal_par) :presentation(0), value(value_par)
  {
    decimals= (uint8_t) decimal_par;
    fixed= 1;
  }
  int save_in_field(Field *field, bool no_conversions);
  enum Type type() const { return REAL_ITEM; }
  enum_field_types field_type() const { return DRIZZLE_TYPE_DOUBLE; }
  double val_real() { assert(fixed == 1); return value; }
  int64_t val_int();
  String *val_str(String*);
  my_decimal *val_decimal(my_decimal *);
  bool basic_const_item() const { return 1; }
  Item *clone_item()
  { return new Item_float(name, value, decimals, max_length); }
  Item_num *neg() { value= -value; return this; }
  virtual void print(String *str, enum_query_type query_type);
  bool eq(const Item *, bool binary_cmp) const;
};


class Item_static_float_func :public Item_float
{
  const char *func_name;
public:
  Item_static_float_func(const char *str, double val_arg, uint32_t decimal_par,
                        uint32_t length)
    :Item_float(NULL, val_arg, decimal_par, length), func_name(str)
  {}

  virtual inline void print(String *str,
                            enum_query_type query_type __attribute__((unused)))
  {
    str->append(func_name);
  }

  Item *safe_charset_converter(const CHARSET_INFO * const tocs);
  bool check_vcol_func_processor(unsigned char *arg __attribute__((unused)))
  { return false; }
};


class Item_string :public Item_basic_constant
{
public:
  Item_string(const char *str,uint32_t length,
              const CHARSET_INFO * const cs, Derivation dv= DERIVATION_COERCIBLE,
              uint32_t repertoire= MY_REPERTOIRE_UNICODE30)
    : m_cs_specified(false)
  {
    str_value.set_or_copy_aligned(str, length, cs);
    collation.set(cs, dv, repertoire);
    /*
      We have to have a different max_length than 'length' here to
      ensure that we get the right length if we do use the item
      to create a new table. In this case max_length must be the maximum
      number of chars for a string of this type because we in Create_field::
      divide the max_length with mbmaxlen).
    */
    max_length= str_value.numchars()*cs->mbmaxlen;
    set_name(str, length, cs);
    decimals=NOT_FIXED_DEC;
    // it is constant => can be used without fix_fields (and frequently used)
    fixed= 1;
  }
  /* Just create an item and do not fill string representation */
  Item_string(const CHARSET_INFO * const cs, Derivation dv= DERIVATION_COERCIBLE)
    : m_cs_specified(false)
  {
    collation.set(cs, dv);
    max_length= 0;
    set_name(NULL, 0, cs);
    decimals= NOT_FIXED_DEC;
    fixed= 1;
  }
  Item_string(const char *name_par, const char *str, uint32_t length,
              const CHARSET_INFO * const cs, Derivation dv= DERIVATION_COERCIBLE,
              uint32_t repertoire= MY_REPERTOIRE_UNICODE30)
    : m_cs_specified(false)
  {
    str_value.set_or_copy_aligned(str, length, cs);
    collation.set(cs, dv, repertoire);
    max_length= str_value.numchars()*cs->mbmaxlen;
    set_name(name_par, 0, cs);
    decimals=NOT_FIXED_DEC;
    // it is constant => can be used without fix_fields (and frequently used)
    fixed= 1;
  }
  void set_repertoire_from_value()
  {
    collation.repertoire= my_string_repertoire(str_value.charset(),
                                               str_value.ptr(),
                                               str_value.length());
  }
  enum Type type() const { return STRING_ITEM; }
  double val_real();
  int64_t val_int();
  String *val_str(String*)
  {
    assert(fixed == 1);
    return (String*) &str_value;
  }
  my_decimal *val_decimal(my_decimal *);
  int save_in_field(Field *field, bool no_conversions);
  enum Item_result result_type () const { return STRING_RESULT; }
  enum_field_types field_type() const { return DRIZZLE_TYPE_VARCHAR; }
  bool basic_const_item() const { return 1; }
  bool eq(const Item *item, bool binary_cmp) const;
  Item *clone_item() 
  {
    return new Item_string(name, str_value.ptr(), 
    			   str_value.length(), collation.collation);
  }
  Item *safe_charset_converter(const CHARSET_INFO * const tocs);
  inline void append(char *str, uint32_t length)
  {
    str_value.append(str, length);
    max_length= str_value.numchars() * collation.collation->mbmaxlen;
  }
  virtual void print(String *str, enum_query_type query_type);

  /**
    Return true if character-set-introducer was explicitly specified in the
    original query for this item (text literal).

    This operation is to be called from Item_string::print(). The idea is
    that when a query is generated (re-constructed) from the Item-tree,
    character-set-introducers should appear only for those literals, where
    they were explicitly specified by the user. Otherwise, that may lead to
    loss collation information (character set introducers implies default
    collation for the literal).

    Basically, that makes sense only for views and hopefully will be gone
    one day when we start using original query as a view definition.

    @return This operation returns the value of m_cs_specified attribute.
      @retval true if character set introducer was explicitly specified in
      the original query.
      @retval false otherwise.
  */
  inline bool is_cs_specified() const
  {
    return m_cs_specified;
  }

  /**
    Set the value of m_cs_specified attribute.

    m_cs_specified attribute shows whether character-set-introducer was
    explicitly specified in the original query for this text literal or
    not. The attribute makes sense (is used) only for views.

    This operation is to be called from the parser during parsing an input
    query.
  */
  inline void set_cs_specified(bool cs_specified)
  {
    m_cs_specified= cs_specified;
  }
  bool check_vcol_func_processor(unsigned char *arg __attribute__((unused)))
  { return false; }

private:
  bool m_cs_specified;
};


class Item_static_string_func :public Item_string
{
  const char *func_name;
public:
  Item_static_string_func(const char *name_par, const char *str, uint32_t length,
                          const CHARSET_INFO * const cs,
                          Derivation dv= DERIVATION_COERCIBLE)
    :Item_string(NULL, str, length, cs, dv), func_name(name_par)
  {}
  Item *safe_charset_converter(const CHARSET_INFO * const tocs);

  virtual inline void print(String *str,
                            enum_query_type query_type __attribute__((unused)))
  {
    str->append(func_name);
  }
  bool check_vcol_func_processor(unsigned char *arg __attribute__((unused)))
  { return true; }
};


/* for show tables */
class Item_return_date_time :public Item_string
{
  enum_field_types date_time_field_type;
public:
  Item_return_date_time(const char *name_arg, enum_field_types field_type_arg)
    :Item_string(name_arg, 0, &my_charset_bin),
     date_time_field_type(field_type_arg)
  { }
  enum_field_types field_type() const { return date_time_field_type; }
};


class Item_blob :public Item_string
{
public:
  Item_blob(const char *name, uint32_t length) :
    Item_string(name, length, &my_charset_bin)
  { max_length= length; }
  enum Type type() const { return TYPE_HOLDER; }
  enum_field_types field_type() const { return DRIZZLE_TYPE_BLOB; }
};


/**
  Item_empty_string -- is a utility class to put an item into List<Item>
  which is then used in protocol.send_fields() when sending SHOW output to
  the client.
*/

class Item_empty_string :public Item_string
{
public:
  Item_empty_string(const char *header,uint32_t length, const CHARSET_INFO * cs= NULL) :
    Item_string("",0, cs ? cs : &my_charset_utf8_general_ci)
    { name=(char*) header; max_length= cs ? length * cs->mbmaxlen : length; }
  void make_field(Send_field *field);
};


class Item_return_int :public Item_int
{
  enum_field_types int_field_type;
public:
  Item_return_int(const char *name_arg, uint32_t length,
		  enum_field_types field_type_arg, int64_t value= 0)
    :Item_int(name_arg, value, length), int_field_type(field_type_arg)
  {
    unsigned_flag=1;
  }
  enum_field_types field_type() const { return int_field_type; }
};


class Item_hex_string: public Item_basic_constant
{
public:
  Item_hex_string() {}
  Item_hex_string(const char *str,uint32_t str_length);
  enum Type type() const { return VARBIN_ITEM; }
  double val_real()
  { 
    assert(fixed == 1); 
    return (double) (uint64_t) Item_hex_string::val_int();
  }
  int64_t val_int();
  bool basic_const_item() const { return 1; }
  String *val_str(String*) { assert(fixed == 1); return &str_value; }
  my_decimal *val_decimal(my_decimal *);
  int save_in_field(Field *field, bool no_conversions);
  enum Item_result result_type () const { return STRING_RESULT; }
  enum Item_result cast_to_int_type() const { return INT_RESULT; }
  enum_field_types field_type() const { return DRIZZLE_TYPE_VARCHAR; }
  virtual void print(String *str, enum_query_type query_type);
  bool eq(const Item *item, bool binary_cmp) const;
  virtual Item *safe_charset_converter(const CHARSET_INFO * const tocs);
  bool check_vcol_func_processor(unsigned char *arg __attribute__((unused)))
  { return false; }
};


class Item_bin_string: public Item_hex_string
{
public:
  Item_bin_string(const char *str,uint32_t str_length);
};

class Item_result_field :public Item	/* Item with result field */
{
public:
  Field *result_field;				/* Save result here */
  Item_result_field() :result_field(0) {}
  // Constructor used for Item_sum/Item_cond_and/or (see Item comment)
  Item_result_field(Session *session, Item_result_field *item):
    Item(session, item), result_field(item->result_field)
  {}
  ~Item_result_field() {}			/* Required with gcc 2.95 */
  Field *get_tmp_table_field() { return result_field; }
  Field *tmp_table_field(Table *t_arg __attribute__((unused)))
  { return result_field; }
  table_map used_tables() const { return 1; }
  virtual void fix_length_and_dec()=0;
  void set_result_field(Field *field) { result_field= field; }
  bool is_result_field() { return 1; }
  void save_in_result_field(bool no_conversions)
  {
    save_in_field(result_field, no_conversions);
  }
  void cleanup();
  bool check_vcol_func_processor(unsigned char *arg __attribute__((unused)))
  { return false; }
};


class Item_ref :public Item_ident
{
protected:
  void set_properties();
public:
  enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF };
  Field *result_field;			 /* Save result here */
  Item **ref;
  Item_ref(Name_resolution_context *context_arg,
           const char *db_arg, const char *table_name_arg,
           const char *field_name_arg)
    :Item_ident(context_arg, db_arg, table_name_arg, field_name_arg),
     result_field(0), ref(0) {}
  /*
    This constructor is used in two scenarios:
    A) *item = NULL
      No initialization is performed, fix_fields() call will be necessary.
      
    B) *item points to an Item this Item_ref will refer to. This is 
      used for GROUP BY. fix_fields() will not be called in this case,
      so we call set_properties to make this item "fixed". set_properties
      performs a subset of action Item_ref::fix_fields does, and this subset
      is enough for Item_ref's used in GROUP BY.
    
    TODO we probably fix a superset of problems like in BUG#6658. Check this 
         with Bar, and if we have a more broader set of problems like this.
  */
  Item_ref(Name_resolution_context *context_arg, Item **item,
           const char *table_name_arg, const char *field_name_arg,
           bool alias_name_used_arg= false);

  /* Constructor need to process subselect with temporary tables (see Item) */
  Item_ref(Session *session, Item_ref *item)
    :Item_ident(session, item), result_field(item->result_field), ref(item->ref) {}
  enum Type type() const		{ return REF_ITEM; }
  bool eq(const Item *item, bool binary_cmp) const
  { 
    Item *it= ((Item *) item)->real_item();
    return ref && (*ref)->eq(it, binary_cmp);
  }
  double val_real();
  int64_t val_int();
  my_decimal *val_decimal(my_decimal *);
  bool val_bool();
  String *val_str(String* tmp);
  bool is_null();
  bool get_date(DRIZZLE_TIME *ltime,uint32_t fuzzydate);
  double val_result();
  int64_t val_int_result();
  String *str_result(String* tmp);
  my_decimal *val_decimal_result(my_decimal *);
  bool val_bool_result();
  bool send(Protocol *prot, String *tmp);
  void make_field(Send_field *field);
  bool fix_fields(Session *, Item **);
  void fix_after_pullout(st_select_lex *new_parent, Item **ref);
  int save_in_field(Field *field, bool no_conversions);
  void save_org_in_field(Field *field);
  enum Item_result result_type () const { return (*ref)->result_type(); }
  enum_field_types field_type() const   { return (*ref)->field_type(); }
  Field *get_tmp_table_field()
  { return result_field ? result_field : (*ref)->get_tmp_table_field(); }
  Item *get_tmp_table_item(Session *session);
  table_map used_tables() const		
  {
    return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables(); 
  }
  void update_used_tables() 
  { 
    if (!depended_from) 
      (*ref)->update_used_tables(); 
  }
  table_map not_null_tables() const { return (*ref)->not_null_tables(); }
  void set_result_field(Field *field)	{ result_field= field; }
  bool is_result_field() { return 1; }
  void save_in_result_field(bool no_conversions)
  {
    (*ref)->save_in_field(result_field, no_conversions);
  }
  Item *real_item()
  {
    return ref ? (*ref)->real_item() : this;
  }
  bool walk(Item_processor processor, bool walk_subquery, unsigned char *arg)
  { return (*ref)->walk(processor, walk_subquery, arg); }
  virtual void print(String *str, enum_query_type query_type);
  bool result_as_int64_t()
  {
    return (*ref)->result_as_int64_t();
  }
  void cleanup();
  Item_field *filed_for_view_update()
    { return (*ref)->filed_for_view_update(); }
  virtual Ref_Type ref_type() { return REF; }

  // Row emulation: forwarding of ROW-related calls to ref
  uint32_t cols()
  {
    return ref && result_type() == ROW_RESULT ? (*ref)->cols() : 1;
  }
  Item* element_index(uint32_t i)
  {
    return ref && result_type() == ROW_RESULT ? (*ref)->element_index(i) : this;
  }
  Item** addr(uint32_t i)
  {
    return ref && result_type() == ROW_RESULT ? (*ref)->addr(i) : 0;
  }
  bool check_cols(uint32_t c)
  {
    return ref && result_type() == ROW_RESULT ? (*ref)->check_cols(c) 
                                              : Item::check_cols(c);
  }
  bool null_inside()
  {
    return ref && result_type() == ROW_RESULT ? (*ref)->null_inside() : 0;
  }
  void bring_value()
  { 
    if (ref && result_type() == ROW_RESULT)
      (*ref)->bring_value();
  }

};


/*
  The same as Item_ref, but get value from val_* family of method to get
  value of item on which it referred instead of result* family.
*/
class Item_direct_ref :public Item_ref
{
public:
  Item_direct_ref(Name_resolution_context *context_arg, Item **item,
                  const char *table_name_arg,
                  const char *field_name_arg,
                  bool alias_name_used_arg= false)
    :Item_ref(context_arg, item, table_name_arg,
              field_name_arg, alias_name_used_arg)
  {}
  /* Constructor need to process subselect with temporary tables (see Item) */
  Item_direct_ref(Session *session, Item_direct_ref *item) : Item_ref(session, item) {}

  double val_real();
  int64_t val_int();
  String *val_str(String* tmp);
  my_decimal *val_decimal(my_decimal *);
  bool val_bool();
  bool is_null();
  bool get_date(DRIZZLE_TIME *ltime,uint32_t fuzzydate);
  virtual Ref_Type ref_type() { return DIRECT_REF; }
};

/*
  Class for outer fields.
  An object of this class is created when the select where the outer field was
  resolved is a grouping one. After it has been fixed the ref field will point
  to either an Item_ref or an Item_direct_ref object which will be used to
  access the field.
  See also comments for the fix_inner_refs() and the
  Item_field::fix_outer_field() functions.
*/

class Item_outer_ref :public Item_direct_ref
{
public:
  Item *outer_ref;
  /* The aggregate function under which this outer ref is used, if any. */
  Item_sum *in_sum_func;
  /*
    true <=> that the outer_ref is already present in the select list
    of the outer select.
  */
  bool found_in_select_list;
  Item_outer_ref(Name_resolution_context *context_arg,
                 Item_field *outer_field_arg)
    :Item_direct_ref(context_arg, 0, outer_field_arg->table_name,
                     outer_field_arg->field_name),
    outer_ref(outer_field_arg), in_sum_func(0),
    found_in_select_list(0)
  {
    ref= &outer_ref;
    set_properties();
    fixed= 0;
  }
  Item_outer_ref(Name_resolution_context *context_arg, Item **item,
                 const char *table_name_arg, const char *field_name_arg,
                 bool alias_name_used_arg)
    :Item_direct_ref(context_arg, item, table_name_arg, field_name_arg,
                     alias_name_used_arg),
    outer_ref(0), in_sum_func(0), found_in_select_list(1)
  {}
  void save_in_result_field(bool no_conversions __attribute__((unused)))
  {
    outer_ref->save_org_in_field(result_field);
  }
  bool fix_fields(Session *, Item **);
  void fix_after_pullout(st_select_lex *new_parent, Item **ref);
  table_map used_tables() const
  {
    return (*ref)->const_item() ? 0 : OUTER_REF_TABLE_BIT;
  }
  virtual Ref_Type ref_type() { return OUTER_REF; }
};



/*
  An object of this class:
   - Converts val_XXX() calls to ref->val_XXX_result() calls, like Item_ref.
   - Sets owner->was_null=true if it has returned a NULL value from any
     val_XXX() function. This allows to inject an Item_ref_null_helper
     object into subquery and then check if the subquery has produced a row
     with NULL value.
*/

class Item_ref_null_helper: public Item_ref
{
protected:
  Item_in_subselect* owner;
public:
  Item_ref_null_helper(Name_resolution_context *context_arg,
                       Item_in_subselect* master, Item **item,
		       const char *table_name_arg, const char *field_name_arg)
    :Item_ref(context_arg, item, table_name_arg, field_name_arg),
     owner(master) {}
  double val_real();
  int64_t val_int();
  String* val_str(String* s);
  my_decimal *val_decimal(my_decimal *);
  bool val_bool();
  bool get_date(DRIZZLE_TIME *ltime, uint32_t fuzzydate);
  virtual void print(String *str, enum_query_type query_type);
  /*
    we add RAND_TABLE_BIT to prevent moving this item from HAVING to WHERE
  */
  table_map used_tables() const
  {
    return (depended_from ?
            OUTER_REF_TABLE_BIT :
            (*ref)->used_tables() | RAND_TABLE_BIT);
  }
};

/*
  The following class is used to optimize comparing of date and bigint columns
  We need to save the original item ('ref') to be able to call
  ref->save_in_field(). This is used to create index search keys.
  
  An instance of Item_int_with_ref may have signed or unsigned integer value.
  
*/

class Item_int_with_ref :public Item_int
{
  Item *ref;
public:
  Item_int_with_ref(int64_t i, Item *ref_arg, bool unsigned_arg) :
    Item_int(i), ref(ref_arg)
  {
    unsigned_flag= unsigned_arg;
  }
  int save_in_field(Field *field, bool no_conversions)
  {
    return ref->save_in_field(field, no_conversions);
  }
  Item *clone_item();
  virtual Item *real_item() { return ref; }
};


class Item_copy_string :public Item
{
  enum enum_field_types cached_field_type;
public:
  Item *item;
  Item_copy_string(Item *i) :item(i)
  {
    null_value= maybe_null= item->maybe_null;
    decimals=item->decimals;
    max_length=item->max_length;
    name=item->name;
    cached_field_type= item->field_type();
  }
  enum Type type() const { return COPY_STR_ITEM; }
  enum Item_result result_type () const { return STRING_RESULT; }
  enum_field_types field_type() const { return cached_field_type; }
  double val_real()
  {
    int err_not_used;
    char *end_not_used;
    return (null_value ? 0.0 :
            my_strntod(str_value.charset(), (char*) str_value.ptr(),
                       str_value.length(), &end_not_used, &err_not_used));
  }
  int64_t val_int()
  {
    int err;
    return null_value ? 0 : my_strntoll(str_value.charset(),str_value.ptr(),
                                        str_value.length(),10, (char**) 0,
                                        &err);
  }
  String *val_str(String*);
  my_decimal *val_decimal(my_decimal *);
  void make_field(Send_field *field) { item->make_field(field); }
  void copy();
  int save_in_field(Field *field,
                    bool no_conversions __attribute__((unused)))
  {
    return save_str_value_in_field(field, &str_value);
  }
  table_map used_tables() const { return (table_map) 1L; }
  bool const_item() const { return 0; }
  bool is_null() { return null_value; }
};
class Item_default_value : public Item_field
{
public:
  Item *arg;
  Item_default_value(Name_resolution_context *context_arg)
    :Item_field(context_arg, (const char *)NULL, (const char *)NULL,
               (const char *)NULL),
     arg(NULL) {}
  Item_default_value(Name_resolution_context *context_arg, Item *a)
    :Item_field(context_arg, (const char *)NULL, (const char *)NULL,
                (const char *)NULL),
     arg(a) {}
  enum Type type() const { return DEFAULT_VALUE_ITEM; }
  bool eq(const Item *item, bool binary_cmp) const;
  bool fix_fields(Session *, Item **);
  virtual void print(String *str, enum_query_type query_type);
  int save_in_field(Field *field_arg, bool no_conversions);
  table_map used_tables() const { return (table_map)0L; }

  bool walk(Item_processor processor, bool walk_subquery, unsigned char *args)
  {
    return arg->walk(processor, walk_subquery, args) ||
      (this->*processor)(args);
  }

  Item *transform(Item_transformer transformer, unsigned char *args);
};

/*
  Item_insert_value -- an implementation of VALUES() function.
  You can use the VALUES(col_name) function in the UPDATE clause
  to refer to column values from the INSERT portion of the INSERT
  ... UPDATE statement. In other words, VALUES(col_name) in the
  UPDATE clause refers to the value of col_name that would be
  inserted, had no duplicate-key conflict occurred.
  In all other places this function returns NULL.
*/

class Item_insert_value : public Item_field
{
public:
  Item *arg;
  Item_insert_value(Name_resolution_context *context_arg, Item *a)
    :Item_field(context_arg, (const char *)NULL, (const char *)NULL,
               (const char *)NULL),
     arg(a) {}
  bool eq(const Item *item, bool binary_cmp) const;
  bool fix_fields(Session *, Item **);
  virtual void print(String *str, enum_query_type query_type);
  int save_in_field(Field *field_arg, bool no_conversions)
  {
    return Item_field::save_in_field(field_arg, no_conversions);
  }
  /* 
   We use RAND_TABLE_BIT to prevent Item_insert_value from
   being treated as a constant and precalculated before execution
  */
  table_map used_tables() const { return RAND_TABLE_BIT; }

  bool walk(Item_processor processor, bool walk_subquery, unsigned char *args)
  {
    return arg->walk(processor, walk_subquery, args) ||
	    (this->*processor)(args);
  }
  bool check_vcol_func_processor(unsigned char *arg __attribute__((unused)))
  { return true; }
};


class Item_cache: public Item_basic_constant
{
protected:
  Item *example;
  table_map used_table_map;
  /*
    Field that this object will get value from. This is set/used by 
    index-based subquery engines to detect and remove the equality injected 
    by IN->EXISTS transformation.
    For all other uses of Item_cache, cached_field doesn't matter.
  */  
  Field *cached_field;
  enum enum_field_types cached_field_type;
public:
  Item_cache(): 
    example(0), used_table_map(0), cached_field(0), cached_field_type(DRIZZLE_TYPE_VARCHAR) 
  {
    fixed= 1; 
    null_value= 1;
  }
  Item_cache(enum_field_types field_type_arg):
    example(0), used_table_map(0), cached_field(0), cached_field_type(field_type_arg)
  {
    fixed= 1;
    null_value= 1;
  }

  void set_used_tables(table_map map) { used_table_map= map; }

  virtual bool allocate(uint32_t i __attribute__((unused)))
  { return 0; }
  virtual bool setup(Item *item)
  {
    example= item;
    max_length= item->max_length;
    decimals= item->decimals;
    collation.set(item->collation);
    unsigned_flag= item->unsigned_flag;
    if (item->type() == FIELD_ITEM)
      cached_field= ((Item_field *)item)->field;
    return 0;
  };
  virtual void store(Item *)= 0;
  enum Type type() const { return CACHE_ITEM; }
  enum_field_types field_type() const { return cached_field_type; }
  static Item_cache* get_cache(const Item *item);
  table_map used_tables() const { return used_table_map; }
  virtual void keep_array() {}
  virtual void print(String *str, enum_query_type query_type);
  bool eq_def(Field *field);
  bool eq(const Item *item,
          bool binary_cmp __attribute__((unused))) const
  {
    return this == item;
  }
};


class Item_cache_int: public Item_cache
{
protected:
  int64_t value;
public:
  Item_cache_int(): Item_cache(), value(0) {}
  Item_cache_int(enum_field_types field_type_arg):
    Item_cache(field_type_arg), value(0) {}

  void store(Item *item);
  void store(Item *item, int64_t val_arg);
  double val_real() { assert(fixed == 1); return (double) value; }
  int64_t val_int() { assert(fixed == 1); return value; }
  String* val_str(String *str);
  my_decimal *val_decimal(my_decimal *);
  enum Item_result result_type() const { return INT_RESULT; }
  bool result_as_int64_t() { return true; }
};


class Item_cache_real: public Item_cache
{
  double value;
public:
  Item_cache_real(): Item_cache(), value(0) {}

  void store(Item *item);
  double val_real() { assert(fixed == 1); return value; }
  int64_t val_int();
  String* val_str(String *str);
  my_decimal *val_decimal(my_decimal *);
  enum Item_result result_type() const { return REAL_RESULT; }
};


class Item_cache_decimal: public Item_cache
{
protected:
  my_decimal decimal_value;
public:
  Item_cache_decimal(): Item_cache() {}

  void store(Item *item);
  double val_real();
  int64_t val_int();
  String* val_str(String *str);
  my_decimal *val_decimal(my_decimal *);
  enum Item_result result_type() const { return DECIMAL_RESULT; }
};


class Item_cache_str: public Item_cache
{
  char buffer[STRING_BUFFER_USUAL_SIZE];
  String *value, value_buff;
  bool is_varbinary;

public:
  Item_cache_str(const Item *item);
  void store(Item *item);
  double val_real();
  int64_t val_int();
  String* val_str(String *) { assert(fixed == 1); return value; }
  my_decimal *val_decimal(my_decimal *);
  enum Item_result result_type() const { return STRING_RESULT; }
  const CHARSET_INFO *charset() const { return value->charset(); };
  int save_in_field(Field *field, bool no_conversions);
};



void mark_select_range_as_dependent(Session *session,
                                    st_select_lex *last_select,
                                    st_select_lex *current_sel,
                                    Field *found_field, Item *found_item,
                                    Item_ident *resolved_item);

extern void resolve_const_item(Session *session, Item **ref, Item *cmp_item);
extern bool field_is_equal_to_item(Field *field,Item *item);

/**
  Create field for temporary table.

  @param session		Thread handler
  @param table		Temporary table
  @param item		Item to create a field for
  @param type		Type of item (normally item->type)
  @param copy_func	If set and item is a function, store copy of item
                       in this array
  @param from_field    if field will be created using other field as example,
                       pointer example field will be written here
  @param default_field	If field has a default value field, store it here
  @param group		1 if we are going to do a relative group by on result
  @param modify_item	1 if item->result_field should point to new item.
                       This is relevent for how fill_record() is going to
                       work:
                       If modify_item is 1 then fill_record() will update
                       the record in the original table.
                       If modify_item is 0 then fill_record() will update
                       the temporary table
  @param convert_blob_length If >0 create a varstring(convert_blob_length)
                             field instead of blob.

  @retval
    0			on error
  @retval
    new_created field
*/

/* TODO: This is here for now because it needs the Item::Type. It should live
   in Field or Table once item.h is clean enough to actually include */
Field *create_tmp_field(Session *session, Table *table, Item *item,
                        Item::Type type,
                        Item ***copy_func, Field **from_field,
                        Field **def_field,
                        bool group, bool modify_item,
                        bool table_cant_handle_bit_fields,
                        bool make_copy_field,
                        uint32_t convert_blob_length);

#endif /* DRIZZLED_ITEM_H */