~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item_func.cc

  • Committer: Brian Aker
  • Date: 2008-11-03 03:49:00 UTC
  • mfrom: (520.4.50 devel)
  • Revision ID: brian@tangent.org-20081103034900-znhvcgtipr3tlel5
Merging in Monty's work

Show diffs side-by-side

added added

removed removed

Lines of Context:
150
150
  return copy_or_same(session);
151
151
}
152
152
 
153
 
/*
154
 
  When a user variable is updated (in a SET command or a query like
155
 
  SELECT @a:= ).
156
 
*/
157
 
 
158
 
bool Item_func_set_user_var::fix_fields(Session *session, Item **ref)
159
 
{
160
 
  assert(fixed == 0);
161
 
  /* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
162
 
  if (Item_func::fix_fields(session, ref) ||
163
 
      !(entry= get_variable(&session->user_vars, name, 1)))
164
 
    return true;
165
 
  /* 
166
 
     Remember the last query which updated it, this way a query can later know
167
 
     if this variable is a constant item in the query (it is if update_query_id
168
 
     is different from query_id).
169
 
  */
170
 
  entry->update_query_id= session->query_id;
171
 
  /*
172
 
    As it is wrong and confusing to associate any 
173
 
    character set with NULL, @a should be latin2
174
 
    after this query sequence:
175
 
 
176
 
      SET @a=_latin2'string';
177
 
      SET @a=NULL;
178
 
 
179
 
    I.e. the second query should not change the charset
180
 
    to the current default value, but should keep the 
181
 
    original value assigned during the first query.
182
 
    In order to do it, we don't copy charset
183
 
    from the argument if the argument is NULL
184
 
    and the variable has previously been initialized.
185
 
  */
186
 
  null_item= (args[0]->type() == NULL_ITEM);
187
 
  if (!entry->collation.collation || !null_item)
188
 
    entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
189
 
  collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
190
 
  cached_result_type= args[0]->result_type();
191
 
  return false;
192
 
}
193
 
 
194
 
 
195
 
void
196
 
Item_func_set_user_var::fix_length_and_dec()
197
 
{
198
 
  maybe_null=args[0]->maybe_null;
199
 
  max_length=args[0]->max_length;
200
 
  decimals=args[0]->decimals;
201
 
  collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
202
 
}
203
 
 
204
 
 
205
 
/*
206
 
  Mark field in read_map
207
 
 
208
 
  NOTES
209
 
    This is used by filesort to register used fields in a a temporary
210
 
    column read set or to register used fields in a view
211
 
*/
212
 
 
213
 
bool Item_func_set_user_var::register_field_in_read_map(unsigned char *arg)
214
 
{
215
 
  if (result_field)
216
 
  {
217
 
    Table *table= (Table *) arg;
218
 
    if (result_field->table == table || !table)
219
 
      bitmap_set_bit(result_field->table->read_set, result_field->field_index);
220
 
    if (result_field->vcol_info && result_field->vcol_info->expr_item)
221
 
      return result_field->vcol_info->
222
 
               expr_item->walk(&Item::register_field_in_read_map, 1, arg);
223
 
  }
224
 
  return 0;
225
 
}
226
 
 
227
 
 
228
 
/*
229
 
  Mark field in bitmap supplied as *arg
230
 
 
231
 
*/
232
 
 
233
 
bool Item_func_set_user_var::register_field_in_bitmap(unsigned char *arg)
234
 
{
235
 
  MY_BITMAP *bitmap = (MY_BITMAP *) arg;
236
 
  assert(bitmap);
237
 
  if (result_field)
238
 
  {
239
 
    bitmap_set_bit(bitmap, result_field->field_index);
240
 
  }
241
 
  return 0;
242
 
}
243
 
 
244
 
 
245
 
/**
246
 
  Set value to user variable.
247
 
 
248
 
  @param entry          pointer to structure representing variable
249
 
  @param set_null       should we set NULL value ?
250
 
  @param ptr            pointer to buffer with new value
251
 
  @param length         length of new value
252
 
  @param type           type of new value
253
 
  @param cs             charset info for new value
254
 
  @param dv             derivation for new value
255
 
  @param unsigned_arg   indiates if a value of type INT_RESULT is unsigned
256
 
 
257
 
  @note Sets error and fatal error if allocation fails.
258
 
 
259
 
  @retval
260
 
    false   success
261
 
  @retval
262
 
    true    failure
263
 
*/
264
 
 
265
 
#define extra_size sizeof(double)
266
 
 
267
 
static bool
268
 
update_hash(user_var_entry *entry, bool set_null, void *ptr, uint32_t length,
269
 
            Item_result type, const CHARSET_INFO * const cs, Derivation dv,
270
 
            bool unsigned_arg)
271
 
{
272
 
  if (set_null)
273
 
  {
274
 
    char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
275
 
    if (entry->value && entry->value != pos)
276
 
      free(entry->value);
277
 
    entry->value= 0;
278
 
    entry->length= 0;
279
 
  }
280
 
  else
281
 
  {
282
 
    if (type == STRING_RESULT)
283
 
      length++;                                 // Store strings with end \0
284
 
    if (length <= extra_size)
285
 
    {
286
 
      /* Save value in value struct */
287
 
      char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
288
 
      if (entry->value != pos)
289
 
      {
290
 
        if (entry->value)
291
 
          free(entry->value);
292
 
        entry->value=pos;
293
 
      }
294
 
    }
295
 
    else
296
 
    {
297
 
      /* Allocate variable */
298
 
      if (entry->length != length)
299
 
      {
300
 
        char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
301
 
        if (entry->value == pos)
302
 
          entry->value=0;
303
 
        entry->value= (char*) my_realloc(entry->value, length,
304
 
                                         MYF(MY_ALLOW_ZERO_PTR | MY_WME |
305
 
                                             ME_FATALERROR));
306
 
        if (!entry->value)
307
 
          return 1;
308
 
      }
309
 
    }
310
 
    if (type == STRING_RESULT)
311
 
    {
312
 
      length--;                                 // Fix length change above
313
 
      entry->value[length]= 0;                  // Store end \0
314
 
    }
315
 
    memcpy(entry->value,ptr,length);
316
 
    if (type == DECIMAL_RESULT)
317
 
      ((my_decimal*)entry->value)->fix_buffer_pointer();
318
 
    entry->length= length;
319
 
    entry->collation.set(cs, dv);
320
 
    entry->unsigned_flag= unsigned_arg;
321
 
  }
322
 
  entry->type=type;
323
 
  return 0;
324
 
}
325
 
 
326
 
 
327
 
bool
328
 
Item_func_set_user_var::update_hash(void *ptr, uint32_t length,
329
 
                                    Item_result res_type,
330
 
                                    const CHARSET_INFO * const cs, Derivation dv,
331
 
                                    bool unsigned_arg)
332
 
{
333
 
  /*
334
 
    If we set a variable explicitely to NULL then keep the old
335
 
    result type of the variable
336
 
  */
337
 
  if ((null_value= args[0]->null_value) && null_item)
338
 
    res_type= entry->type;                      // Don't change type of item
339
 
  if (::update_hash(entry, (null_value= args[0]->null_value),
340
 
                    ptr, length, res_type, cs, dv, unsigned_arg))
341
 
  {
342
 
    null_value= 1;
343
 
    return 1;
344
 
  }
345
 
  return 0;
346
 
}
347
 
 
348
153
 
349
154
/** Get the value of a variable as a double. */
350
155
 
462
267
  }
463
268
  return(val);
464
269
}
465
 
 
466
 
/**
467
 
  This functions is invoked on SET \@variable or
468
 
  \@variable:= expression.
469
 
 
470
 
  Evaluate (and check expression), store results.
471
 
 
472
 
  @note
473
 
    For now it always return OK. All problem with value evaluating
474
 
    will be caught by session->is_error() check in sql_set_variables().
475
 
 
476
 
  @retval
477
 
    false OK.
478
 
*/
479
 
 
480
 
bool
481
 
Item_func_set_user_var::check(bool use_result_field)
482
 
{
483
 
  if (use_result_field && !result_field)
484
 
    use_result_field= false;
485
 
 
486
 
  switch (cached_result_type) {
487
 
  case REAL_RESULT:
488
 
  {
489
 
    save_result.vreal= use_result_field ? result_field->val_real() :
490
 
                        args[0]->val_real();
491
 
    break;
492
 
  }
493
 
  case INT_RESULT:
494
 
  {
495
 
    save_result.vint= use_result_field ? result_field->val_int() :
496
 
                       args[0]->val_int();
497
 
    unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
498
 
                    args[0]->unsigned_flag;
499
 
    break;
500
 
  }
501
 
  case STRING_RESULT:
502
 
  {
503
 
    save_result.vstr= use_result_field ? result_field->val_str(&value) :
504
 
                       args[0]->val_str(&value);
505
 
    break;
506
 
  }
507
 
  case DECIMAL_RESULT:
508
 
  {
509
 
    save_result.vdec= use_result_field ?
510
 
                       result_field->val_decimal(&decimal_buff) :
511
 
                       args[0]->val_decimal(&decimal_buff);
512
 
    break;
513
 
  }
514
 
  case ROW_RESULT:
515
 
  default:
516
 
    // This case should never be chosen
517
 
    assert(0);
518
 
    break;
519
 
  }
520
 
  return(false);
521
 
}
522
 
 
523
 
 
524
 
/**
525
 
  This functions is invoked on
526
 
  SET \@variable or \@variable:= expression.
527
 
 
528
 
  @note
529
 
    We have to store the expression as such in the variable, independent of
530
 
    the value method used by the user
531
 
 
532
 
  @retval
533
 
    0   OK
534
 
  @retval
535
 
    1   EOM Error
536
 
 
537
 
*/
538
 
 
539
 
bool
540
 
Item_func_set_user_var::update()
541
 
{
542
 
  bool res= false;
543
 
 
544
 
  switch (cached_result_type) {
545
 
  case REAL_RESULT:
546
 
  {
547
 
    res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
548
 
                     REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
549
 
    break;
550
 
  }
551
 
  case INT_RESULT:
552
 
  {
553
 
    res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
554
 
                     INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT,
555
 
                     unsigned_flag);
556
 
    break;
557
 
  }
558
 
  case STRING_RESULT:
559
 
  {
560
 
    if (!save_result.vstr)                                      // Null value
561
 
      res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
562
 
                       DERIVATION_IMPLICIT, 0);
563
 
    else
564
 
      res= update_hash((void*) save_result.vstr->ptr(),
565
 
                       save_result.vstr->length(), STRING_RESULT,
566
 
                       save_result.vstr->charset(),
567
 
                       DERIVATION_IMPLICIT, 0);
568
 
    break;
569
 
  }
570
 
  case DECIMAL_RESULT:
571
 
  {
572
 
    if (!save_result.vdec)                                      // Null value
573
 
      res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
574
 
                       DERIVATION_IMPLICIT, 0);
575
 
    else
576
 
      res= update_hash((void*) save_result.vdec,
577
 
                       sizeof(my_decimal), DECIMAL_RESULT,
578
 
                       &my_charset_bin, DERIVATION_IMPLICIT, 0);
579
 
    break;
580
 
  }
581
 
  case ROW_RESULT:
582
 
  default:
583
 
    // This case should never be chosen
584
 
    assert(0);
585
 
    break;
586
 
  }
587
 
  return(res);
588
 
}
589
 
 
590
 
 
591
 
double Item_func_set_user_var::val_real()
592
 
{
593
 
  assert(fixed == 1);
594
 
  check(0);
595
 
  update();                                     // Store expression
596
 
  return entry->val_real(&null_value);
597
 
}
598
 
 
599
 
int64_t Item_func_set_user_var::val_int()
600
 
{
601
 
  assert(fixed == 1);
602
 
  check(0);
603
 
  update();                                     // Store expression
604
 
  return entry->val_int(&null_value);
605
 
}
606
 
 
607
 
String *Item_func_set_user_var::val_str(String *str)
608
 
{
609
 
  assert(fixed == 1);
610
 
  check(0);
611
 
  update();                                     // Store expression
612
 
  return entry->val_str(&null_value, str, decimals);
613
 
}
614
 
 
615
 
 
616
 
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
617
 
{
618
 
  assert(fixed == 1);
619
 
  check(0);
620
 
  update();                                     // Store expression
621
 
  return entry->val_decimal(&null_value, val);
622
 
}
623
 
 
624
 
 
625
 
double Item_func_set_user_var::val_result()
626
 
{
627
 
  assert(fixed == 1);
628
 
  check(true);
629
 
  update();                                     // Store expression
630
 
  return entry->val_real(&null_value);
631
 
}
632
 
 
633
 
int64_t Item_func_set_user_var::val_int_result()
634
 
{
635
 
  assert(fixed == 1);
636
 
  check(true);
637
 
  update();                                     // Store expression
638
 
  return entry->val_int(&null_value);
639
 
}
640
 
 
641
 
String *Item_func_set_user_var::str_result(String *str)
642
 
{
643
 
  assert(fixed == 1);
644
 
  check(true);
645
 
  update();                                     // Store expression
646
 
  return entry->val_str(&null_value, str, decimals);
647
 
}
648
 
 
649
 
 
650
 
my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
651
 
{
652
 
  assert(fixed == 1);
653
 
  check(true);
654
 
  update();                                     // Store expression
655
 
  return entry->val_decimal(&null_value, val);
656
 
}
657
 
 
658
 
 
659
 
void Item_func_set_user_var::print(String *str, enum_query_type query_type)
660
 
{
661
 
  str->append(STRING_WITH_LEN("(@"));
662
 
  str->append(name.str, name.length);
663
 
  str->append(STRING_WITH_LEN(":="));
664
 
  args[0]->print(str, query_type);
665
 
  str->append(')');
666
 
}
667
 
 
668
 
 
669
 
void Item_func_set_user_var::print_as_stmt(String *str,
670
 
                                           enum_query_type query_type)
671
 
{
672
 
  str->append(STRING_WITH_LEN("set @"));
673
 
  str->append(name.str, name.length);
674
 
  str->append(STRING_WITH_LEN(":="));
675
 
  args[0]->print(str, query_type);
676
 
  str->append(')');
677
 
}
678
 
 
679
 
bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
680
 
{
681
 
  if (result_field)
682
 
  {
683
 
    check(1);
684
 
    update();
685
 
    return protocol->store(result_field);
686
 
  }
687
 
  return Item::send(protocol, str_arg);
688
 
}
689
 
 
690
 
void Item_func_set_user_var::make_field(Send_field *tmp_field)
691
 
{
692
 
  if (result_field)
693
 
  {
694
 
    result_field->make_field(tmp_field);
695
 
    assert(tmp_field->table_name != 0);
696
 
    if (Item::name)
697
 
      tmp_field->col_name=Item::name;               // Use user supplied name
698
 
  }
699
 
  else
700
 
    Item::make_field(tmp_field);
701
 
}
702
 
 
703
 
 
704
 
/*
705
 
  Save the value of a user variable into a field
706
 
 
707
 
  SYNOPSIS
708
 
    save_in_field()
709
 
      field           target field to save the value to
710
 
      no_conversion   flag indicating whether conversions are allowed
711
 
 
712
 
  DESCRIPTION
713
 
    Save the function value into a field and update the user variable
714
 
    accordingly. If a result field is defined and the target field doesn't
715
 
    coincide with it then the value from the result field will be used as
716
 
    the new value of the user variable.
717
 
 
718
 
    The reason to have this method rather than simply using the result
719
 
    field in the val_xxx() methods is that the value from the result field
720
 
    not always can be used when the result field is defined.
721
 
    Let's consider the following cases:
722
 
    1) when filling a tmp table the result field is defined but the value of it
723
 
    is undefined because it has to be produced yet. Thus we can't use it.
724
 
    2) on execution of an INSERT ... SELECT statement the save_in_field()
725
 
    function will be called to fill the data in the new record. If the SELECT
726
 
    part uses a tmp table then the result field is defined and should be
727
 
    used in order to get the correct result.
728
 
 
729
 
    The difference between the SET_USER_VAR function and regular functions
730
 
    like CONCAT is that the Item_func objects for the regular functions are
731
 
    replaced by Item_field objects after the values of these functions have
732
 
    been stored in a tmp table. Yet an object of the Item_field class cannot
733
 
    be used to update a user variable.
734
 
    Due to this we have to handle the result field in a special way here and
735
 
    in the Item_func_set_user_var::send() function.
736
 
 
737
 
  RETURN VALUES
738
 
    false       Ok
739
 
    true        Error
740
 
*/
741
 
 
742
 
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
743
 
                                          bool can_use_result_field)
744
 
{
745
 
  bool use_result_field= (!can_use_result_field ? 0 :
746
 
                          (result_field && result_field != field));
747
 
  int error;
748
 
 
749
 
  /* Update the value of the user variable */
750
 
  check(use_result_field);
751
 
  update();
752
 
 
753
 
  if (result_type() == STRING_RESULT ||
754
 
      (result_type() == REAL_RESULT && field->result_type() == STRING_RESULT))
755
 
  {
756
 
    String *result;
757
 
    const CHARSET_INFO * const cs= collation.collation;
758
 
    char buff[MAX_FIELD_WIDTH];         // Alloc buffer for small columns
759
 
    str_value.set_quick(buff, sizeof(buff), cs);
760
 
    result= entry->val_str(&null_value, &str_value, decimals);
761
 
 
762
 
    if (null_value)
763
 
    {
764
 
      str_value.set_quick(0, 0, cs);
765
 
      return set_field_to_null_with_conversions(field, no_conversions);
766
 
    }
767
 
 
768
 
    /* NOTE: If null_value == false, "result" must be not NULL.  */
769
 
 
770
 
    field->set_notnull();
771
 
    error=field->store(result->ptr(),result->length(),cs);
772
 
    str_value.set_quick(0, 0, cs);
773
 
  }
774
 
  else if (result_type() == REAL_RESULT)
775
 
  {
776
 
    double nr= entry->val_real(&null_value);
777
 
    if (null_value)
778
 
      return set_field_to_null(field);
779
 
    field->set_notnull();
780
 
    error=field->store(nr);
781
 
  }
782
 
  else if (result_type() == DECIMAL_RESULT)
783
 
  {
784
 
    my_decimal decimal_value;
785
 
    my_decimal *val= entry->val_decimal(&null_value, &decimal_value);
786
 
    if (null_value)
787
 
      return set_field_to_null(field);
788
 
    field->set_notnull();
789
 
    error=field->store_decimal(val);
790
 
  }
791
 
  else
792
 
  {
793
 
    int64_t nr= entry->val_int(&null_value);
794
 
    if (null_value)
795
 
      return set_field_to_null_with_conversions(field, no_conversions);
796
 
    field->set_notnull();
797
 
    error=field->store(nr, unsigned_flag);
798
 
  }
799
 
  return error;
800
 
}
801
 
 
802
 
 
803
 
bool Item_user_var_as_out_param::fix_fields(Session *session, Item **ref)
804
 
{
805
 
  assert(fixed == 0);
806
 
  if (Item::fix_fields(session, ref) ||
807
 
      !(entry= get_variable(&session->user_vars, name, 1)))
808
 
    return true;
809
 
  entry->type= STRING_RESULT;
810
 
  /*
811
 
    Let us set the same collation which is used for loading
812
 
    of fields in LOAD DATA INFILE.
813
 
    (Since Item_user_var_as_out_param is used only there).
814
 
  */
815
 
  entry->collation.set(session->variables.collation_database);
816
 
  entry->update_query_id= session->query_id;
817
 
  return false;
818
 
}
819
 
 
820
 
 
821
 
void Item_user_var_as_out_param::set_null_value(const CHARSET_INFO * const cs)
822
 
{
823
 
  ::update_hash(entry, true, 0, 0, STRING_RESULT, cs,
824
 
                DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
825
 
}
826
 
 
827
 
 
828
 
void Item_user_var_as_out_param::set_value(const char *str, uint32_t length,
829
 
                                           const CHARSET_INFO * const cs)
830
 
{
831
 
  ::update_hash(entry, false, (void*)str, length, STRING_RESULT, cs,
832
 
                DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
833
 
}
834
 
 
835
 
 
836
 
double Item_user_var_as_out_param::val_real()
837
 
{
838
 
  assert(0);
839
 
  return 0.0;
840
 
}
841
 
 
842
 
 
843
 
int64_t Item_user_var_as_out_param::val_int()
844
 
{
845
 
  assert(0);
846
 
  return 0;
847
 
}
848
 
 
849
 
 
850
 
String* Item_user_var_as_out_param::val_str(String *str __attribute__((unused)))
851
 
{
852
 
  assert(0);
853
 
  return 0;
854
 
}
855
 
 
856
 
 
857
 
my_decimal* Item_user_var_as_out_param::val_decimal(my_decimal *decimal_buffer __attribute__((unused)))
858
 
{
859
 
  assert(0);
860
 
  return 0;
861
 
}
862
 
 
863
 
 
864
 
void Item_user_var_as_out_param::print(String *str,
865
 
                                       enum_query_type query_type __attribute__((unused)))
866
 
{
867
 
  str->append('@');
868
 
  str->append(name.str,name.length);
869
 
}
870
 
 
871
 
/***************************************************************************
872
 
  System variables
873
 
****************************************************************************/
874
 
 
875
 
/**
876
 
  Return value of an system variable base[.name] as a constant item.
877
 
 
878
 
  @param session                        Thread handler
879
 
  @param var_type               global / session
880
 
  @param name                   Name of base or system variable
881
 
  @param component              Component.
882
 
 
883
 
  @note
884
 
    If component.str = 0 then the variable name is in 'name'
885
 
 
886
 
  @return
887
 
    - 0  : error
888
 
    - #  : constant item
889
 
*/