~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/function/get_user_var.cc

  • Committer: Brian Aker
  • Date: 2009-01-28 01:12:41 UTC
  • Revision ID: brian@tangent.org-20090128011241-w309ibv1yeza84cp
Dead variable array removal for statement based. (Thank god I got something
done today)

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
  return (var_entry->val_int(&null_value));
61
61
}
62
62
 
63
 
/**
64
 
  Get variable by name and, if necessary, put the record of variable
65
 
  use into the binary log.
66
 
 
67
 
  When a user variable is invoked from an update query (INSERT, UPDATE etc),
68
 
  stores this variable and its value in session->user_var_events, so that it can be
69
 
  written to the binlog (will be written just before the query is written, see
70
 
  log.cc).
71
 
 
72
 
  @param      session        Current thread
73
 
  @param      name       Variable name
74
 
  @param[out] out_entry  variable structure or NULL. The pointer is set
75
 
                         regardless of whether function succeeded or not.
76
 
 
77
 
  @retval
78
 
    0  OK
79
 
  @retval
80
 
    1  Failed to put appropriate record into binary log
81
 
 
82
 
*/
83
 
 
84
 
static int get_var_with_binlog(Session *session, enum_sql_command sql_command,
85
 
                               LEX_STRING &name, user_var_entry **out_entry)
86
 
{
87
 
  BINLOG_USER_VAR_EVENT *user_var_event;
88
 
  user_var_entry *var_entry;
89
 
  var_entry= get_variable(&session->user_vars, name, 0);
90
 
 
91
 
  /*
92
 
    Any reference to user-defined variable which is done from stored
93
 
    function or trigger affects their execution and the execution of the
94
 
    calling statement. We must log all such variables even if they are
95
 
    not involved in table-updating statements.
96
 
  */
97
 
  if (!(opt_bin_log && is_update_query(sql_command)))
98
 
  {
99
 
    *out_entry= var_entry;
100
 
    return 0;
101
 
  }
102
 
 
103
 
  if (!var_entry)
104
 
  {
105
 
    /*
106
 
      If the variable does not exist, it's NULL, but we want to create it so
107
 
      that it gets into the binlog (if it didn't, the slave could be
108
 
      influenced by a variable of the same name previously set by another
109
 
      thread).
110
 
      We create it like if it had been explicitly set with SET before.
111
 
      The 'new' mimics what sql_yacc.yy does when 'SET @a=10;'.
112
 
      sql_set_variables() is what is called from 'case SQLCOM_SET_OPTION'
113
 
      in dispatch_command()). Instead of building a one-element list to pass to
114
 
      sql_set_variables(), we could instead manually call check() and update();
115
 
      this would save memory and time; but calling sql_set_variables() makes
116
 
      one unique place to maintain (sql_set_variables()).
117
 
 
118
 
      Manipulation with lex is necessary since free_underlaid_joins
119
 
      is going to release memory belonging to the main query.
120
 
    */
121
 
 
122
 
    List<set_var_base> tmp_var_list;
123
 
    LEX *sav_lex= session->lex, lex_tmp;
124
 
    session->lex= &lex_tmp;
125
 
    lex_start(session);
126
 
    tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
127
 
                                                                       new Item_null())));
128
 
    /* Create the variable */
129
 
    if (sql_set_variables(session, &tmp_var_list))
130
 
    {
131
 
      session->lex= sav_lex;
132
 
      goto err;
133
 
    }
134
 
    session->lex= sav_lex;
135
 
    if (!(var_entry= get_variable(&session->user_vars, name, 0)))
136
 
      goto err;
137
 
  }
138
 
  else if (var_entry->used_query_id == session->query_id)
139
 
  {
140
 
    /*
141
 
       If this variable was already stored in user_var_events by this query
142
 
       (because it's used in more than one place in the query), don't store
143
 
       it.
144
 
    */
145
 
    *out_entry= var_entry;
146
 
    return 0;
147
 
  }
148
 
 
149
 
  uint32_t size;
150
 
  /*
151
 
    First we need to store value of var_entry, when the next situation
152
 
    appears:
153
 
    > set @a:=1;
154
 
    > insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
155
 
    We have to write to binlog value @a= 1.
156
 
 
157
 
    We allocate the user_var_event on user_var_events_alloc pool, not on
158
 
    the this-statement-execution pool because in SPs user_var_event objects
159
 
    may need to be valid after current [SP] statement execution pool is
160
 
    destroyed.
161
 
  */
162
 
  size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
163
 
  if (!(user_var_event= (BINLOG_USER_VAR_EVENT *)
164
 
        alloc_root(session->user_var_events_alloc, size)))
165
 
    goto err;
166
 
 
167
 
  user_var_event->value= (char*) user_var_event +
168
 
    ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
169
 
  user_var_event->user_var_event= var_entry;
170
 
  user_var_event->type= var_entry->type;
171
 
  user_var_event->charset_number= var_entry->collation.collation->number;
172
 
  if (!var_entry->value)
173
 
  {
174
 
    /* NULL value*/
175
 
    user_var_event->length= 0;
176
 
    user_var_event->value= 0;
177
 
  }
178
 
  else
179
 
  {
180
 
    user_var_event->length= var_entry->length;
181
 
    memcpy(user_var_event->value, var_entry->value,
182
 
           var_entry->length);
183
 
  }
184
 
  /* Mark that this variable has been used by this query */
185
 
  var_entry->used_query_id= session->query_id;
186
 
  if (insert_dynamic(&session->user_var_events, (unsigned char*) &user_var_event))
187
 
    goto err;
188
 
 
189
 
  *out_entry= var_entry;
190
 
  return 0;
191
 
 
192
 
err:
193
 
  *out_entry= var_entry;
194
 
  return 1;
195
 
}
196
 
 
197
63
void Item_func_get_user_var::fix_length_and_dec()
198
64
{
199
65
  Session *session=current_session;
200
 
  int error;
201
66
  maybe_null=1;
202
67
  decimals=NOT_FIXED_DEC;
203
68
  max_length=MAX_BLOB_WIDTH;
204
69
 
205
 
  error= get_var_with_binlog(session, session->lex->sql_command, name, &var_entry);
 
70
  var_entry= get_variable(&session->user_vars, name, 0);
206
71
 
207
72
  /*
208
73
    If the variable didn't exist it has been created as a STRING-type.