1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
#include <drizzled/server_includes.h>
22
#include <drizzled/functions/get_user_var.h>
25
Item_func_get_user_var::val_str(String *str)
29
return((String*) 0); // No such variable
30
return(var_entry->val_str(&null_value, str, decimals));
34
double Item_func_get_user_var::val_real()
38
return 0.0; // No such variable
39
return (var_entry->val_real(&null_value));
43
my_decimal *Item_func_get_user_var::val_decimal(my_decimal *dec)
48
return var_entry->val_decimal(&null_value, dec);
51
int64_t Item_func_get_user_var::val_int()
55
return 0L; // No such variable
56
return (var_entry->val_int(&null_value));
60
Get variable by name and, if necessary, put the record of variable
61
use into the binary log.
63
When a user variable is invoked from an update query (INSERT, UPDATE etc),
64
stores this variable and its value in session->user_var_events, so that it can be
65
written to the binlog (will be written just before the query is written, see
68
@param session Current thread
69
@param name Variable name
70
@param[out] out_entry variable structure or NULL. The pointer is set
71
regardless of whether function succeeded or not.
76
1 Failed to put appropriate record into binary log
80
int get_var_with_binlog(Session *session, enum_sql_command sql_command,
81
LEX_STRING &name, user_var_entry **out_entry)
83
BINLOG_USER_VAR_EVENT *user_var_event;
84
user_var_entry *var_entry;
85
var_entry= get_variable(&session->user_vars, name, 0);
88
Any reference to user-defined variable which is done from stored
89
function or trigger affects their execution and the execution of the
90
calling statement. We must log all such variables even if they are
91
not involved in table-updating statements.
93
if (!(opt_bin_log && is_update_query(sql_command)))
95
*out_entry= var_entry;
102
If the variable does not exist, it's NULL, but we want to create it so
103
that it gets into the binlog (if it didn't, the slave could be
104
influenced by a variable of the same name previously set by another
106
We create it like if it had been explicitly set with SET before.
107
The 'new' mimics what sql_yacc.yy does when 'SET @a=10;'.
108
sql_set_variables() is what is called from 'case SQLCOM_SET_OPTION'
109
in dispatch_command()). Instead of building a one-element list to pass to
110
sql_set_variables(), we could instead manually call check() and update();
111
this would save memory and time; but calling sql_set_variables() makes
112
one unique place to maintain (sql_set_variables()).
114
Manipulation with lex is necessary since free_underlaid_joins
115
is going to release memory belonging to the main query.
118
List<set_var_base> tmp_var_list;
119
LEX *sav_lex= session->lex, lex_tmp;
120
session->lex= &lex_tmp;
122
tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
124
/* Create the variable */
125
if (sql_set_variables(session, &tmp_var_list))
127
session->lex= sav_lex;
130
session->lex= sav_lex;
131
if (!(var_entry= get_variable(&session->user_vars, name, 0)))
134
else if (var_entry->used_query_id == session->query_id ||
135
mysql_bin_log.is_query_in_union(session, var_entry->used_query_id))
138
If this variable was already stored in user_var_events by this query
139
(because it's used in more than one place in the query), don't store
142
*out_entry= var_entry;
148
First we need to store value of var_entry, when the next situation
151
> insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
152
We have to write to binlog value @a= 1.
154
We allocate the user_var_event on user_var_events_alloc pool, not on
155
the this-statement-execution pool because in SPs user_var_event objects
156
may need to be valid after current [SP] statement execution pool is
159
size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
160
if (!(user_var_event= (BINLOG_USER_VAR_EVENT *)
161
alloc_root(session->user_var_events_alloc, size)))
164
user_var_event->value= (char*) user_var_event +
165
ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
166
user_var_event->user_var_event= var_entry;
167
user_var_event->type= var_entry->type;
168
user_var_event->charset_number= var_entry->collation.collation->number;
169
if (!var_entry->value)
172
user_var_event->length= 0;
173
user_var_event->value= 0;
177
user_var_event->length= var_entry->length;
178
memcpy(user_var_event->value, var_entry->value,
181
/* Mark that this variable has been used by this query */
182
var_entry->used_query_id= session->query_id;
183
if (insert_dynamic(&session->user_var_events, (unsigned char*) &user_var_event))
186
*out_entry= var_entry;
190
*out_entry= var_entry;
194
void Item_func_get_user_var::fix_length_and_dec()
196
Session *session=current_session;
199
decimals=NOT_FIXED_DEC;
200
max_length=MAX_BLOB_WIDTH;
202
error= get_var_with_binlog(session, session->lex->sql_command, name, &var_entry);
205
If the variable didn't exist it has been created as a STRING-type.
206
'var_entry' is NULL only if there occured an error during the call to
211
m_cached_result_type= var_entry->type;
212
unsigned_flag= var_entry->unsigned_flag;
213
max_length= var_entry->length;
215
collation.set(var_entry->collation);
216
switch(m_cached_result_type) {
218
max_length= DBL_DIG + 8;
221
max_length= MAX_BIGINT_WIDTH;
225
max_length= MAX_BLOB_WIDTH;
228
max_length= DECIMAL_MAX_STR_LENGTH;
229
decimals= DECIMAL_MAX_SCALE;
231
case ROW_RESULT: // Keep compiler happy
239
collation.set(&my_charset_bin, DERIVATION_IMPLICIT);
241
m_cached_result_type= STRING_RESULT;
242
max_length= MAX_BLOB_WIDTH;
247
bool Item_func_get_user_var::const_item() const
249
return (!var_entry || current_session->query_id != var_entry->update_query_id);
253
enum Item_result Item_func_get_user_var::result_type() const
255
return m_cached_result_type;
259
void Item_func_get_user_var::print(String *str,
260
enum_query_type query_type __attribute__((unused)))
262
str->append(STRING_WITH_LEN("(@"));
263
str->append(name.str,name.length);
268
bool Item_func_get_user_var::eq(const Item *item,
269
bool binary_cmp __attribute__((unused))) const
271
/* Assume we don't have rtti */
273
return 1; // Same item is same.
274
/* Check if other type is also a get_user_var() object */
275
if (item->type() != FUNC_ITEM ||
276
((Item_func*) item)->functype() != functype())
278
Item_func_get_user_var *other=(Item_func_get_user_var*) item;
279
return (name.length == other->name.length &&
280
!memcmp(name.str, other->name.str, name.length));