~harrison-fisk/drizzle/import-google-innodb-smp-patch

« back to all changes in this revision

Viewing changes to drizzled/item_func.cc

  • Committer: Brian Aker
  • Date: 2008-10-29 13:44:52 UTC
  • mfrom: (520.4.24 devel)
  • Revision ID: brian@tangent.org-20081029134452-1nm5k9jw9mao0r1k
Merge from Monty

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
*/
23
23
 
24
24
#include <drizzled/server_includes.h>
25
 
#include "rpl_mi.h"
26
25
#include <mysys/my_bit.h>
27
26
#include <drizzled/error.h>
28
27
 
150
149
  return copy_or_same(session);
151
150
}
152
151
 
153
 
// Shift-functions, same as << and >> in C/C++
154
 
 
155
 
int64_t Item_func_shift_left::val_int()
156
 
{
157
 
  assert(fixed == 1);
158
 
  uint32_t shift;
159
 
  uint64_t res= ((uint64_t) args[0]->val_int() <<
160
 
                  (shift=(uint) args[1]->val_int()));
161
 
  if (args[0]->null_value || args[1]->null_value)
162
 
  {
163
 
    null_value=1;
164
 
    return 0;
165
 
  }
166
 
  null_value=0;
167
 
  return (shift < sizeof(int64_t)*8 ? (int64_t) res : 0L);
168
 
}
169
 
 
170
 
int64_t Item_func_shift_right::val_int()
171
 
{
172
 
  assert(fixed == 1);
173
 
  uint32_t shift;
174
 
  uint64_t res= (uint64_t) args[0]->val_int() >>
175
 
    (shift=(uint) args[1]->val_int());
176
 
  if (args[0]->null_value || args[1]->null_value)
177
 
  {
178
 
    null_value=1;
179
 
    return 0;
180
 
  }
181
 
  null_value=0;
182
 
  return (shift < sizeof(int64_t)*8 ? (int64_t) res : 0);
183
 
}
184
 
 
185
 
// Conversion functions
186
 
 
187
 
void Item_func_integer::fix_length_and_dec()
188
 
{
189
 
  max_length=args[0]->max_length - args[0]->decimals+1;
190
 
  uint32_t tmp=float_length(decimals);
191
 
  set_if_smaller(max_length,tmp);
192
 
  decimals=0;
193
 
}
194
 
 
195
 
int64_t Item_func_field::val_int()
196
 
{
197
 
  assert(fixed == 1);
198
 
 
199
 
  if (cmp_type == STRING_RESULT)
200
 
  {
201
 
    String *field;
202
 
    if (!(field= args[0]->val_str(&value)))
203
 
      return 0;
204
 
    for (uint32_t i=1 ; i < arg_count ; i++)
205
 
    {
206
 
      String *tmp_value=args[i]->val_str(&tmp);
207
 
      if (tmp_value && !sortcmp(field,tmp_value,cmp_collation.collation))
208
 
        return (int64_t) (i);
209
 
    }
210
 
  }
211
 
  else if (cmp_type == INT_RESULT)
212
 
  {
213
 
    int64_t val= args[0]->val_int();
214
 
    if (args[0]->null_value)
215
 
      return 0;
216
 
    for (uint32_t i=1; i < arg_count ; i++)
217
 
    {
218
 
      if (val == args[i]->val_int() && !args[i]->null_value)
219
 
        return (int64_t) (i);
220
 
    }
221
 
  }
222
 
  else if (cmp_type == DECIMAL_RESULT)
223
 
  {
224
 
    my_decimal dec_arg_buf, *dec_arg,
225
 
               dec_buf, *dec= args[0]->val_decimal(&dec_buf);
226
 
    if (args[0]->null_value)
227
 
      return 0;
228
 
    for (uint32_t i=1; i < arg_count; i++)
229
 
    {
230
 
      dec_arg= args[i]->val_decimal(&dec_arg_buf);
231
 
      if (!args[i]->null_value && !my_decimal_cmp(dec_arg, dec))
232
 
        return (int64_t) (i);
233
 
    }
234
 
  }
235
 
  else
236
 
  {
237
 
    double val= args[0]->val_real();
238
 
    if (args[0]->null_value)
239
 
      return 0;
240
 
    for (uint32_t i=1; i < arg_count ; i++)
241
 
    {
242
 
      if (val == args[i]->val_real() && !args[i]->null_value)
243
 
        return (int64_t) (i);
244
 
    }
245
 
  }
246
 
  return 0;
247
 
}
248
 
 
249
 
 
250
 
void Item_func_field::fix_length_and_dec()
251
 
{
252
 
  maybe_null=0; max_length=3;
253
 
  cmp_type= args[0]->result_type();
254
 
  for (uint32_t i=1; i < arg_count ; i++)
255
 
    cmp_type= item_cmp_type(cmp_type, args[i]->result_type());
256
 
  if (cmp_type == STRING_RESULT)
257
 
    agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1);
258
 
}
259
 
 
260
 
 
261
 
int64_t Item_func_ord::val_int()
262
 
{
263
 
  assert(fixed == 1);
264
 
  String *res=args[0]->val_str(&value);
265
 
  if (!res)
266
 
  {
267
 
    null_value=1;
268
 
    return 0;
269
 
  }
270
 
  null_value=0;
271
 
  if (!res->length()) return 0;
272
 
#ifdef USE_MB
273
 
  if (use_mb(res->charset()))
274
 
  {
275
 
    register const char *str=res->ptr();
276
 
    register uint32_t n=0, l=my_ismbchar(res->charset(),str,str+res->length());
277
 
    if (!l)
278
 
      return (int64_t)((unsigned char) *str);
279
 
    while (l--)
280
 
      n=(n<<8)|(uint32_t)((unsigned char) *str++);
281
 
    return (int64_t) n;
282
 
  }
283
 
#endif
284
 
  return (int64_t) ((unsigned char) (*res)[0]);
285
 
}
286
 
 
287
 
/*
288
 
** User level locks
289
 
*/
290
 
 
291
 
pthread_mutex_t LOCK_user_locks;
292
 
static HASH hash_user_locks;
293
 
 
294
 
class User_level_lock
295
 
{
296
 
  unsigned char *key;
297
 
  size_t key_length;
298
 
 
299
 
public:
300
 
  int count;
301
 
  bool locked;
302
 
  pthread_cond_t cond;
303
 
  my_thread_id thread_id;
304
 
  void set_thread(Session *session) { thread_id= session->thread_id; }
305
 
 
306
 
  User_level_lock(const unsigned char *key_arg,uint32_t length, ulong id) 
307
 
    :key_length(length),count(1),locked(1), thread_id(id)
308
 
  {
309
 
    key= (unsigned char*) my_memdup(key_arg,length,MYF(0));
310
 
    pthread_cond_init(&cond,NULL);
311
 
    if (key)
312
 
    {
313
 
      if (my_hash_insert(&hash_user_locks,(unsigned char*) this))
314
 
      {
315
 
        free(key);
316
 
        key=0;
317
 
      }
318
 
    }
319
 
  }
320
 
  ~User_level_lock()
321
 
  {
322
 
    if (key)
323
 
    {
324
 
      hash_delete(&hash_user_locks,(unsigned char*) this);
325
 
      free(key);
326
 
    }
327
 
    pthread_cond_destroy(&cond);
328
 
  }
329
 
  inline bool initialized() { return key != 0; }
330
 
  friend void item_user_lock_release(User_level_lock *ull);
331
 
  friend unsigned char *ull_get_key(const User_level_lock *ull, size_t *length,
332
 
                            bool not_used);
333
 
};
334
 
 
335
 
unsigned char *ull_get_key(const User_level_lock *ull, size_t *length,
336
 
                   bool not_used __attribute__((unused)))
337
 
{
338
 
  *length= ull->key_length;
339
 
  return ull->key;
340
 
}
341
 
 
342
 
 
343
 
static bool item_user_lock_inited= 0;
344
 
 
345
 
void item_user_lock_init(void)
346
 
{
347
 
  pthread_mutex_init(&LOCK_user_locks,MY_MUTEX_INIT_SLOW);
348
 
  hash_init(&hash_user_locks, system_charset_info,
349
 
            16,0,0,(hash_get_key) ull_get_key,NULL,0);
350
 
  item_user_lock_inited= 1;
351
 
}
352
 
 
353
 
void item_user_lock_free(void)
354
 
{
355
 
  if (item_user_lock_inited)
356
 
  {
357
 
    item_user_lock_inited= 0;
358
 
    hash_free(&hash_user_locks);
359
 
    pthread_mutex_destroy(&LOCK_user_locks);
360
 
  }
361
 
}
362
 
 
363
 
void item_user_lock_release(User_level_lock *ull)
364
 
{
365
 
  ull->locked=0;
366
 
  ull->thread_id= 0;
367
 
  if (--ull->count)
368
 
    pthread_cond_signal(&ull->cond);
369
 
  else
370
 
    delete ull;
371
 
}
372
 
 
373
 
/**
374
 
  Wait until we are at or past the given position in the master binlog
375
 
  on the slave.
376
 
*/
377
 
 
378
 
int64_t Item_master_pos_wait::val_int()
379
 
{
380
 
  assert(fixed == 1);
381
 
  Session* session = current_session;
382
 
  String *log_name = args[0]->val_str(&value);
383
 
  int event_count= 0;
384
 
 
385
 
  null_value=0;
386
 
  if (session->slave_thread || !log_name || !log_name->length())
387
 
  {
388
 
    null_value = 1;
389
 
    return 0;
390
 
  }
391
 
  int64_t pos = (ulong)args[1]->val_int();
392
 
  int64_t timeout = (arg_count==3) ? args[2]->val_int() : 0 ;
393
 
  if ((event_count = active_mi->rli.wait_for_pos(session, log_name, pos, timeout)) == -2)
394
 
  {
395
 
    null_value = 1;
396
 
    event_count=0;
397
 
  }
398
 
  return event_count;
399
 
}
400
 
 
401
 
#ifdef EXTRA_DEBUG
402
 
void debug_sync_point(const char* lock_name, uint32_t lock_timeout)
403
 
{
404
 
}
405
 
 
406
 
#endif
407
 
 
408
 
#define extra_size sizeof(double)
409
 
 
410
 
static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
411
 
                                    bool create_if_not_exists)
412
 
{
413
 
  user_var_entry *entry;
414
 
 
415
 
  if (!(entry = (user_var_entry*) hash_search(hash, (unsigned char*) name.str,
416
 
                                              name.length)) &&
417
 
      create_if_not_exists)
418
 
  {
419
 
    uint32_t size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
420
 
    if (!hash_inited(hash))
421
 
      return 0;
422
 
    if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME | ME_FATALERROR))))
423
 
      return 0;
424
 
    entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
425
 
      extra_size;
426
 
    entry->name.length=name.length;
427
 
    entry->value=0;
428
 
    entry->length=0;
429
 
    entry->update_query_id=0;
430
 
    entry->collation.set(NULL, DERIVATION_IMPLICIT, 0);
431
 
    entry->unsigned_flag= 0;
432
 
    /*
433
 
      If we are here, we were called from a SET or a query which sets a
434
 
      variable. Imagine it is this:
435
 
      INSERT INTO t SELECT @a:=10, @a:=@a+1.
436
 
      Then when we have a Item_func_get_user_var (because of the @a+1) so we
437
 
      think we have to write the value of @a to the binlog. But before that,
438
 
      we have a Item_func_set_user_var to create @a (@a:=10), in this we mark
439
 
      the variable as "already logged" (line below) so that it won't be logged
440
 
      by Item_func_get_user_var (because that's not necessary).
441
 
    */
442
 
    entry->used_query_id=current_session->query_id;
443
 
    entry->type=STRING_RESULT;
444
 
    memcpy(entry->name.str, name.str, name.length+1);
445
 
    if (my_hash_insert(hash,(unsigned char*) entry))
446
 
    {
447
 
      free((char*) entry);
448
 
      return 0;
449
 
    }
450
 
  }
451
 
  return entry;
452
 
}
453
 
 
454
152
/*
455
153
  When a user variable is updated (in a SET command or a query like
456
154
  SELECT @a:= ).
563
261
    true    failure
564
262
*/
565
263
 
 
264
#define extra_size sizeof(double)
 
265
 
566
266
static bool
567
267
update_hash(user_var_entry *entry, bool set_null, void *ptr, uint32_t length,
568
268
            Item_result type, const CHARSET_INFO * const cs, Derivation dv,
1099
799
}
1100
800
 
1101
801
 
1102
 
String *
1103
 
Item_func_get_user_var::val_str(String *str)
1104
 
{
1105
 
  assert(fixed == 1);
1106
 
  if (!var_entry)
1107
 
    return((String*) 0);                        // No such variable
1108
 
  return(var_entry->val_str(&null_value, str, decimals));
1109
 
}
1110
 
 
1111
 
 
1112
 
double Item_func_get_user_var::val_real()
1113
 
{
1114
 
  assert(fixed == 1);
1115
 
  if (!var_entry)
1116
 
    return 0.0;                                 // No such variable
1117
 
  return (var_entry->val_real(&null_value));
1118
 
}
1119
 
 
1120
 
 
1121
 
my_decimal *Item_func_get_user_var::val_decimal(my_decimal *dec)
1122
 
{
1123
 
  assert(fixed == 1);
1124
 
  if (!var_entry)
1125
 
    return 0;
1126
 
  return var_entry->val_decimal(&null_value, dec);
1127
 
}
1128
 
 
1129
 
 
1130
 
int64_t Item_func_get_user_var::val_int()
1131
 
{
1132
 
  assert(fixed == 1);
1133
 
  if (!var_entry)
1134
 
    return 0L;                          // No such variable
1135
 
  return (var_entry->val_int(&null_value));
1136
 
}
1137
 
 
1138
 
 
1139
 
/**
1140
 
  Get variable by name and, if necessary, put the record of variable 
1141
 
  use into the binary log.
1142
 
 
1143
 
  When a user variable is invoked from an update query (INSERT, UPDATE etc),
1144
 
  stores this variable and its value in session->user_var_events, so that it can be
1145
 
  written to the binlog (will be written just before the query is written, see
1146
 
  log.cc).
1147
 
 
1148
 
  @param      session        Current thread
1149
 
  @param      name       Variable name
1150
 
  @param[out] out_entry  variable structure or NULL. The pointer is set
1151
 
                         regardless of whether function succeeded or not.
1152
 
 
1153
 
  @retval
1154
 
    0  OK
1155
 
  @retval
1156
 
    1  Failed to put appropriate record into binary log
1157
 
 
1158
 
*/
1159
 
 
1160
 
int get_var_with_binlog(Session *session, enum_sql_command sql_command,
1161
 
                        LEX_STRING &name, user_var_entry **out_entry)
1162
 
{
1163
 
  BINLOG_USER_VAR_EVENT *user_var_event;
1164
 
  user_var_entry *var_entry;
1165
 
  var_entry= get_variable(&session->user_vars, name, 0);
1166
 
 
1167
 
  /*
1168
 
    Any reference to user-defined variable which is done from stored
1169
 
    function or trigger affects their execution and the execution of the
1170
 
    calling statement. We must log all such variables even if they are 
1171
 
    not involved in table-updating statements.
1172
 
  */
1173
 
  if (!(opt_bin_log && is_update_query(sql_command)))
1174
 
  {
1175
 
    *out_entry= var_entry;
1176
 
    return 0;
1177
 
  }
1178
 
 
1179
 
  if (!var_entry)
1180
 
  {
1181
 
    /*
1182
 
      If the variable does not exist, it's NULL, but we want to create it so
1183
 
      that it gets into the binlog (if it didn't, the slave could be
1184
 
      influenced by a variable of the same name previously set by another
1185
 
      thread).
1186
 
      We create it like if it had been explicitly set with SET before.
1187
 
      The 'new' mimics what sql_yacc.yy does when 'SET @a=10;'.
1188
 
      sql_set_variables() is what is called from 'case SQLCOM_SET_OPTION'
1189
 
      in dispatch_command()). Instead of building a one-element list to pass to
1190
 
      sql_set_variables(), we could instead manually call check() and update();
1191
 
      this would save memory and time; but calling sql_set_variables() makes
1192
 
      one unique place to maintain (sql_set_variables()). 
1193
 
 
1194
 
      Manipulation with lex is necessary since free_underlaid_joins
1195
 
      is going to release memory belonging to the main query.
1196
 
    */
1197
 
 
1198
 
    List<set_var_base> tmp_var_list;
1199
 
    LEX *sav_lex= session->lex, lex_tmp;
1200
 
    session->lex= &lex_tmp;
1201
 
    lex_start(session);
1202
 
    tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
1203
 
                                                                       new Item_null())));
1204
 
    /* Create the variable */
1205
 
    if (sql_set_variables(session, &tmp_var_list))
1206
 
    {
1207
 
      session->lex= sav_lex;
1208
 
      goto err;
1209
 
    }
1210
 
    session->lex= sav_lex;
1211
 
    if (!(var_entry= get_variable(&session->user_vars, name, 0)))
1212
 
      goto err;
1213
 
  }
1214
 
  else if (var_entry->used_query_id == session->query_id ||
1215
 
           mysql_bin_log.is_query_in_union(session, var_entry->used_query_id))
1216
 
  {
1217
 
    /* 
1218
 
       If this variable was already stored in user_var_events by this query
1219
 
       (because it's used in more than one place in the query), don't store
1220
 
       it.
1221
 
    */
1222
 
    *out_entry= var_entry;
1223
 
    return 0;
1224
 
  }
1225
 
 
1226
 
  uint32_t size;
1227
 
  /*
1228
 
    First we need to store value of var_entry, when the next situation
1229
 
    appears:
1230
 
    > set @a:=1;
1231
 
    > insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
1232
 
    We have to write to binlog value @a= 1.
1233
 
 
1234
 
    We allocate the user_var_event on user_var_events_alloc pool, not on
1235
 
    the this-statement-execution pool because in SPs user_var_event objects 
1236
 
    may need to be valid after current [SP] statement execution pool is
1237
 
    destroyed.
1238
 
  */
1239
 
  size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
1240
 
  if (!(user_var_event= (BINLOG_USER_VAR_EVENT *)
1241
 
        alloc_root(session->user_var_events_alloc, size)))
1242
 
    goto err;
1243
 
 
1244
 
  user_var_event->value= (char*) user_var_event +
1245
 
    ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
1246
 
  user_var_event->user_var_event= var_entry;
1247
 
  user_var_event->type= var_entry->type;
1248
 
  user_var_event->charset_number= var_entry->collation.collation->number;
1249
 
  if (!var_entry->value)
1250
 
  {
1251
 
    /* NULL value*/
1252
 
    user_var_event->length= 0;
1253
 
    user_var_event->value= 0;
1254
 
  }
1255
 
  else
1256
 
  {
1257
 
    user_var_event->length= var_entry->length;
1258
 
    memcpy(user_var_event->value, var_entry->value,
1259
 
           var_entry->length);
1260
 
  }
1261
 
  /* Mark that this variable has been used by this query */
1262
 
  var_entry->used_query_id= session->query_id;
1263
 
  if (insert_dynamic(&session->user_var_events, (unsigned char*) &user_var_event))
1264
 
    goto err;
1265
 
 
1266
 
  *out_entry= var_entry;
1267
 
  return 0;
1268
 
 
1269
 
err:
1270
 
  *out_entry= var_entry;
1271
 
  return 1;
1272
 
}
1273
 
 
1274
 
void Item_func_get_user_var::fix_length_and_dec()
1275
 
{
1276
 
  Session *session=current_session;
1277
 
  int error;
1278
 
  maybe_null=1;
1279
 
  decimals=NOT_FIXED_DEC;
1280
 
  max_length=MAX_BLOB_WIDTH;
1281
 
 
1282
 
  error= get_var_with_binlog(session, session->lex->sql_command, name, &var_entry);
1283
 
 
1284
 
  /*
1285
 
    If the variable didn't exist it has been created as a STRING-type.
1286
 
    'var_entry' is NULL only if there occured an error during the call to
1287
 
    get_var_with_binlog.
1288
 
  */
1289
 
  if (var_entry)
1290
 
  {
1291
 
    m_cached_result_type= var_entry->type;
1292
 
    unsigned_flag= var_entry->unsigned_flag;
1293
 
    max_length= var_entry->length;
1294
 
 
1295
 
    collation.set(var_entry->collation);
1296
 
    switch(m_cached_result_type) {
1297
 
    case REAL_RESULT:
1298
 
      max_length= DBL_DIG + 8;
1299
 
      break;
1300
 
    case INT_RESULT:
1301
 
      max_length= MAX_BIGINT_WIDTH;
1302
 
      decimals=0;
1303
 
      break;
1304
 
    case STRING_RESULT:
1305
 
      max_length= MAX_BLOB_WIDTH;
1306
 
      break;
1307
 
    case DECIMAL_RESULT:
1308
 
      max_length= DECIMAL_MAX_STR_LENGTH;
1309
 
      decimals= DECIMAL_MAX_SCALE;
1310
 
      break;
1311
 
    case ROW_RESULT:                            // Keep compiler happy
1312
 
    default:
1313
 
      assert(0);
1314
 
      break;
1315
 
    }
1316
 
  }
1317
 
  else
1318
 
  {
1319
 
    collation.set(&my_charset_bin, DERIVATION_IMPLICIT);
1320
 
    null_value= 1;
1321
 
    m_cached_result_type= STRING_RESULT;
1322
 
    max_length= MAX_BLOB_WIDTH;
1323
 
  }
1324
 
}
1325
 
 
1326
 
 
1327
 
bool Item_func_get_user_var::const_item() const
1328
 
{
1329
 
  return (!var_entry || current_session->query_id != var_entry->update_query_id);
1330
 
}
1331
 
 
1332
 
 
1333
 
enum Item_result Item_func_get_user_var::result_type() const
1334
 
{
1335
 
  return m_cached_result_type;
1336
 
}
1337
 
 
1338
 
 
1339
 
void Item_func_get_user_var::print(String *str,
1340
 
                                   enum_query_type query_type __attribute__((unused)))
1341
 
{
1342
 
  str->append(STRING_WITH_LEN("(@"));
1343
 
  str->append(name.str,name.length);
1344
 
  str->append(')');
1345
 
}
1346
 
 
1347
 
 
1348
 
bool Item_func_get_user_var::eq(const Item *item,
1349
 
                                bool binary_cmp __attribute__((unused))) const
1350
 
{
1351
 
  /* Assume we don't have rtti */
1352
 
  if (this == item)
1353
 
    return 1;                                   // Same item is same.
1354
 
  /* Check if other type is also a get_user_var() object */
1355
 
  if (item->type() != FUNC_ITEM ||
1356
 
      ((Item_func*) item)->functype() != functype())
1357
 
    return 0;
1358
 
  Item_func_get_user_var *other=(Item_func_get_user_var*) item;
1359
 
  return (name.length == other->name.length &&
1360
 
          !memcmp(name.str, other->name.str, name.length));
1361
 
}
1362
 
 
1363
 
 
1364
802
bool Item_user_var_as_out_param::fix_fields(Session *session, Item **ref)
1365
803
{
1366
804
  assert(fixed == 0);
1448
886
    - 0  : error
1449
887
    - #  : constant item
1450
888
*/
1451
 
 
1452
 
 
1453
 
/**
1454
 
  Check a user level lock.
1455
 
 
1456
 
  Sets null_value=true on error.
1457
 
 
1458
 
  @retval
1459
 
    1           Available
1460
 
  @retval
1461
 
    0           Already taken, or error
1462
 
*/
1463
 
 
1464
 
int64_t Item_func_is_free_lock::val_int()
1465
 
{
1466
 
  assert(fixed == 1);
1467
 
  String *res=args[0]->val_str(&value);
1468
 
  User_level_lock *ull;
1469
 
 
1470
 
  null_value=0;
1471
 
  if (!res || !res->length())
1472
 
  {
1473
 
    null_value=1;
1474
 
    return 0;
1475
 
  }
1476
 
  
1477
 
  pthread_mutex_lock(&LOCK_user_locks);
1478
 
  ull= (User_level_lock *) hash_search(&hash_user_locks, (unsigned char*) res->ptr(),
1479
 
                                       (size_t) res->length());
1480
 
  pthread_mutex_unlock(&LOCK_user_locks);
1481
 
  if (!ull || !ull->locked)
1482
 
    return 1;
1483
 
  return 0;
1484
 
}
1485
 
 
1486
 
int64_t Item_func_is_used_lock::val_int()
1487
 
{
1488
 
  assert(fixed == 1);
1489
 
  String *res=args[0]->val_str(&value);
1490
 
  User_level_lock *ull;
1491
 
 
1492
 
  null_value=1;
1493
 
  if (!res || !res->length())
1494
 
    return 0;
1495
 
  
1496
 
  pthread_mutex_lock(&LOCK_user_locks);
1497
 
  ull= (User_level_lock *) hash_search(&hash_user_locks, (unsigned char*) res->ptr(),
1498
 
                                       (size_t) res->length());
1499
 
  pthread_mutex_unlock(&LOCK_user_locks);
1500
 
  if (!ull || !ull->locked)
1501
 
    return 0;
1502
 
 
1503
 
  null_value=0;
1504
 
  return ull->thread_id;
1505
 
}
1506
 
 
1507
 
 
1508
 
int64_t Item_func_row_count::val_int()
1509
 
{
1510
 
  assert(fixed == 1);
1511
 
  Session *session= current_session;
1512
 
 
1513
 
  return session->row_count_func;
1514
 
}
1515
 
 
1516
 
int64_t Item_func_found_rows::val_int()
1517
 
{
1518
 
  assert(fixed == 1);
1519
 
  Session *session= current_session;
1520
 
 
1521
 
  return session->found_rows();
1522
 
}