File: sql_data_change.cc

package info (click to toggle)
mysql-8.0 8.0.43-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 1,273,924 kB
  • sloc: cpp: 4,684,605; ansic: 412,450; pascal: 108,398; java: 83,641; perl: 30,221; cs: 27,067; sql: 26,594; sh: 24,181; python: 21,816; yacc: 17,169; php: 11,522; xml: 7,388; javascript: 7,076; makefile: 2,194; lex: 1,075; awk: 670; asm: 520; objc: 183; ruby: 97; lisp: 86
file content (177 lines) | stat: -rw-r--r-- 6,403 bytes parent folder | download
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
/* Copyright (c) 2000, 2025, Oracle and/or its affiliates.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License, version 2.0,
   as published by the Free Software Foundation.

   This program is designed to work with certain software (including
   but not limited to OpenSSL) that is licensed under separate terms,
   as designated in a particular file or component or in included license
   documentation.  The authors of MySQL hereby grant you an additional
   permission to link the program and your derivative works with the
   separately licensed software that they have either included with
   the program or referenced in the documentation.

   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, version 2.0, 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 */

/**
  @file sql_data_change.cc

  Contains classes representing SQL-data change statements. Currently
  the only data change functionality implemented here is function
  defaults.
*/

#include "sql/sql_data_change.h"

#include "my_dbug.h"
#include "my_inttypes.h"
#include "my_sys.h"
#include "sql/current_thd.h"
#include "sql/field.h"
#include "sql/item.h"
#include "sql/sql_class.h"  // THD
#include "sql/sql_list.h"
#include "sql/table.h"  // TABLE

/**
   Allocates and initializes a MY_BITMAP bitmap, containing one bit per column
   in the table. The table THD's MEM_ROOT is used to allocate memory.

   @param      table   The table whose columns should be used as a template
                       for the bitmap.
   @param[out] bitmap  A pointer to the allocated bitmap.

   @retval false Success.
   @retval true Memory allocation error.
*/
static bool allocate_column_bitmap(TABLE *table, MY_BITMAP **bitmap) {
  DBUG_TRACE;
  const uint number_bits = table->s->fields;
  MY_BITMAP *the_struct;
  my_bitmap_map *the_bits;

  if (multi_alloc_root(current_thd->mem_root, &the_struct, sizeof(MY_BITMAP),
                       &the_bits, bitmap_buffer_size(number_bits),
                       NULL) == nullptr)
    return true;

  if (bitmap_init(the_struct, the_bits, number_bits) != 0) return true;

  *bitmap = the_struct;

  return false;
}

bool COPY_INFO::get_function_default_columns(TABLE *table) {
  DBUG_TRACE;

  if (m_function_default_columns != nullptr) return false;

  if (allocate_column_bitmap(table, &m_function_default_columns)) return true;

  if (!m_manage_defaults) return false;  // leave bitmap full of zeroes

  /*
    Find columns with function default on insert or update, mark them in
    bitmap.
  */
  for (uint i = 0; i < table->s->fields; ++i) {
    Field *f = table->field[i];
    if ((m_optype == INSERT_OPERATION &&
         f->has_insert_default_datetime_value_expression()) ||
        (m_optype == UPDATE_OPERATION &&
         f->has_update_default_datetime_value_expression()))
      bitmap_set_bit(m_function_default_columns, f->field_index());
    // if it's a default expression also mark the columns it reads
    if (m_optype == INSERT_OPERATION &&
        f->has_insert_default_general_value_expression()) {
      bitmap_set_bit(m_function_default_columns, f->field_index());
      for (uint j = 0; j < table->s->fields; j++) {
        if (bitmap_is_set(&f->m_default_val_expr->base_columns_map, j)) {
          bitmap_set_bit(table->read_set, j);
        }
      }
    }
  }

  if (bitmap_is_clear_all(m_function_default_columns))
    return false;  // no bit set, next step unneeded

  /*
    Remove explicitly assigned columns from the bitmap. The assignment
    target (lvalue) may not always be a column (Item_field), e.g. we could
    be inserting into a view, whose column is actually a base table's column
    converted with COLLATE: the lvalue would then be an
    Item_func_set_collation.
    If the lvalue is an expression tree, we clear all columns in it from the
    bitmap.
  */
  mem_root_deque<Item *> *all_changed_columns[2] = {m_changed_columns,
                                                    m_changed_columns2};
  for (uint i = 0; i < 2; i++) {
    if (all_changed_columns[i] != nullptr) {
      for (Item *lvalue_item : *all_changed_columns[i]) {
        lvalue_item->walk(
            &Item::remove_column_from_bitmap, enum_walk::SUBQUERY_POSTFIX,
            reinterpret_cast<uchar *>(m_function_default_columns));
      }
    }
  }

  return false;
}

bool COPY_INFO::set_function_defaults(TABLE *table) {
  DBUG_TRACE;

  assert(m_function_default_columns != nullptr);

  /* Quick reject test for checking the case when no defaults are invoked. */
  if (bitmap_is_clear_all(m_function_default_columns)) return false;

  for (uint i = 0; i < table->s->fields; ++i)
    if (bitmap_is_set(m_function_default_columns, i)) {
      assert(bitmap_is_set(table->write_set, i));
      switch (m_optype) {
        case INSERT_OPERATION:
          table->field[i]->evaluate_insert_default_function();
          break;
        case UPDATE_OPERATION:
          table->field[i]->evaluate_update_default_function();
          break;
      }
      // If there was an error while executing the default expression
      if (current_thd->is_error()) return true;
    }

  /**
    @todo combine this call to update_generated_write_fields() with the
    one in fill_record() to avoid updating virtual generated fields twice.
    blobs_need_not_keep_old_value() is called to unset the m_keep_old_value
    flag. Allowing this flag to remain might interfere with the way the old
    BLOB value is handled. When update_generated_write_fields() is removed,
    blobs_need_not_keep_old_value() can also be removed.
  */
  bool res = false;
  if (table->has_gcol()) {
    table->blobs_need_not_keep_old_value();
    res = update_generated_write_fields(table->write_set, table);
  }

  return res;
}

bool COPY_INFO::ignore_last_columns(TABLE *table, uint count) {
  if (get_function_default_columns(table)) return true;
  for (uint i = 0; i < count; i++)
    bitmap_clear_bit(m_function_default_columns, table->s->fields - 1 - i);
  return false;
}