Coverage Report

Created: 2025-09-04 07:09

/src/tarantool/src/box/sql/vdbeapi.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2010-2017, Tarantool AUTHORS, please see AUTHORS file.
3
 *
4
 * Redistribution and use in source and binary forms, with or
5
 * without modification, are permitted provided that the following
6
 * conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above
9
 *    copyright notice, this list of conditions and the
10
 *    following disclaimer.
11
 *
12
 * 2. Redistributions in binary form must reproduce the above
13
 *    copyright notice, this list of conditions and the following
14
 *    disclaimer in the documentation and/or other materials
15
 *    provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21
 * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 */
31
32
/*
33
 *
34
 * This file contains code use to implement APIs that are part of the
35
 * VDBE.
36
 */
37
#include "sqlInt.h"
38
#include "mem.h"
39
#include "vdbeInt.h"
40
#include "box/session.h"
41
42
/*
43
 * Invoke the profile callback.  This routine is only called if we already
44
 * know that the profile callback is defined and needs to be invoked.
45
 */
46
static SQL_NOINLINE void
47
invokeProfileCallback(struct Vdbe *p)
48
0
{
49
0
  struct sql *db = sql_get();
50
0
  sql_int64 iNow;
51
0
  sql_int64 iElapse;
52
0
  assert(p->startTime > 0);
53
0
  assert(db->xProfile != 0 || (db->mTrace & SQL_TRACE_PROFILE) != 0);
54
0
  assert(db->init.busy == 0);
55
0
  assert(p->zSql != 0);
56
0
  sqlOsCurrentTimeInt64(db->pVfs, &iNow);
57
0
  iElapse = (iNow - p->startTime) * 1000000;
58
0
  if (db->xProfile) {
59
0
    db->xProfile(db->pProfileArg, p->zSql, iElapse);
60
0
  }
61
0
  if (db->mTrace & SQL_TRACE_PROFILE) {
62
0
    db->xTrace(SQL_TRACE_PROFILE, db->pTraceArg, p,
63
0
         (void *)&iElapse);
64
0
  }
65
0
  p->startTime = 0;
66
0
}
67
68
int
69
sql_stmt_finalize(struct Vdbe *v)
70
0
{
71
0
  if (v == NULL)
72
0
    return 0;
73
0
  if (v->startTime > 0)
74
0
    invokeProfileCallback(v);
75
0
  return sqlVdbeFinalize(v);
76
0
}
77
78
int
79
sql_stmt_reset(struct Vdbe *v)
80
0
{
81
0
  assert(v != NULL);
82
0
  if (v->startTime > 0)
83
0
    invokeProfileCallback(v);
84
0
  int rc = sqlVdbeReset(v);
85
0
  sqlVdbeRewind(v);
86
0
  return rc;
87
0
}
88
89
bool
90
sql_metadata_is_full()
91
0
{
92
0
  return current_session()->sql_flags & SQL_FullMetadata;
93
0
}
94
95
/*
96
 * Execute the statement pStmt, either until a row of data is ready, the
97
 * statement is completely executed or an error occurs.
98
 *
99
 * This routine implements the bulk of the logic behind the sql_step()
100
 * API.  The only thing omitted is the automatic recompile if a
101
 * schema change has occurred.  That detail is handled by the
102
 * outer sql_step() wrapper procedure.
103
 */
104
static int
105
sqlStep(Vdbe * p)
106
0
{
107
0
  struct sql *db = sql_get();
108
0
  int rc;
109
110
0
  assert(p);
111
0
  if (p->magic != VDBE_MAGIC_RUN)
112
0
    sql_stmt_reset(p);
113
114
0
  if (p->pc <= 0 && p->expired) {
115
0
    p->is_aborted = true;
116
0
    return -1;
117
0
  }
118
0
  if (p->pc < 0) {
119
0
    if ((db->xProfile || (db->mTrace & SQL_TRACE_PROFILE) != 0)
120
0
        && !db->init.busy && p->zSql) {
121
0
      sqlOsCurrentTimeInt64(db->pVfs, &p->startTime);
122
0
    } else {
123
0
      assert(p->startTime == 0);
124
0
    }
125
126
0
    db->nVdbeActive++;
127
0
    p->pc = 0;
128
0
  }
129
0
  if (p->explain) {
130
0
    rc = sqlVdbeList(p);
131
0
  } else {
132
0
    db->nVdbeExec++;
133
0
    rc = sqlVdbeExec(p);
134
0
    db->nVdbeExec--;
135
0
  }
136
137
  /* If the statement completed successfully, invoke the profile callback */
138
0
  if (rc != SQL_ROW && p->startTime > 0)
139
0
    invokeProfileCallback(p);
140
141
0
  if (rc != SQL_ROW && rc != SQL_DONE) {
142
    /* If this statement was prepared using sql_prepare(), and an
143
     * error has occurred, then return an error.
144
     */
145
0
    if (p->is_aborted)
146
0
      rc = -1;
147
0
  }
148
0
  return rc;
149
0
}
150
151
int
152
sql_step(struct Vdbe *v)
153
0
{
154
0
  assert(v != NULL);
155
0
  return sqlStep(v);
156
0
}
157
158
int
159
sql_column_count(struct Vdbe *pVm)
160
0
{
161
0
  return pVm ? pVm->nResColumn : 0;
162
0
}
163
164
char *
165
sql_stmt_result_to_msgpack(struct Vdbe *vdbe, uint32_t *tuple_size,
166
         struct region *region)
167
0
{
168
0
  return mem_encode_array(vdbe->pResultSet, vdbe->nResColumn, tuple_size,
169
0
        region);
170
0
}
171
172
char *
173
sql_stmt_func_result_to_msgpack(struct Vdbe *vdbe, uint32_t *size,
174
        struct region *region)
175
0
{
176
0
  assert(vdbe->nResColumn == 1);
177
0
  return mem_to_mp(vdbe->pResultSet, size, region);
178
0
}
179
180
const char *
181
sql_column_name(struct Vdbe *p, int n)
182
0
{
183
0
  assert(n < sql_column_count(p) && n >= 0);
184
0
  return p->metadata[n].name;
185
0
}
186
187
const char *
188
sql_column_datatype(struct Vdbe *p, int n)
189
0
{
190
0
  assert(n < sql_column_count(p) && n >= 0);
191
0
  return p->metadata[n].type;
192
0
}
193
194
const char *
195
sql_column_coll(struct Vdbe *p, int n)
196
0
{
197
0
  assert(n < sql_column_count(p) && n >= 0);
198
0
  return p->metadata[n].collation;
199
0
}
200
201
int
202
sql_column_nullable(struct Vdbe *p, int n)
203
0
{
204
0
  assert(n < sql_column_count(p) && n >= 0);
205
0
  return p->metadata[n].nullable;
206
0
}
207
208
bool
209
sql_column_is_autoincrement(struct Vdbe *p, int n)
210
0
{
211
0
  assert(n < sql_column_count(p) && n >= 0);
212
0
  return p->metadata[n].is_actoincrement;
213
0
}
214
215
const char *
216
0
sql_column_span(struct Vdbe *p, int n) {
217
0
  assert(n < sql_column_count(p) && n >= 0);
218
0
  return p->metadata[n].span;
219
0
}
220
221
uint64_t
222
sql_stmt_schema_version(const struct Vdbe *v)
223
0
{
224
0
  return v->schema_ver;
225
0
}
226
227
static size_t
228
sql_metadata_size(const struct sql_column_metadata *metadata)
229
0
{
230
0
  size_t size = sizeof(*metadata);
231
0
  if (metadata->type != NULL)
232
0
    size += strlen(metadata->type);
233
0
  if (metadata->name != NULL)
234
0
    size += strlen(metadata->name);
235
0
  if (metadata->collation != NULL)
236
0
    size += strlen(metadata->collation);
237
0
  return size;
238
0
}
239
240
size_t
241
sql_stmt_est_size(const struct Vdbe *v)
242
0
{
243
0
  size_t size = sizeof(*v);
244
  /* Names and types of result set columns */
245
0
  for (int i = 0; i < v->nResColumn; ++i)
246
0
    size += sql_metadata_size(&v->metadata[i]);
247
  /* Opcodes */
248
0
  size += sizeof(struct VdbeOp) * v->nOp;
249
  /* Memory cells */
250
0
  size += sizeof(struct Mem) * v->nMem;
251
  /* Bindings */
252
0
  size += sizeof(struct Mem) * v->nVar;
253
  /* Bindings included in the result set */
254
0
  size += sizeof(uint32_t) * v->res_var_count;
255
  /* Cursors */
256
0
  size += sizeof(struct VdbeCursor *) * v->nCursor;
257
258
0
  for (int i = 0; i < v->nOp; ++i) {
259
    /* Estimate size of p4 operand. */
260
0
    if (v->aOp[i].p4type == P4_NOTUSED)
261
0
      continue;
262
0
    switch (v->aOp[i].p4type) {
263
0
    case P4_DYNAMIC:
264
0
    case P4_STATIC:
265
0
      if (v->aOp[i].opcode == OP_Blob ||
266
0
          v->aOp[i].opcode == OP_String)
267
0
        size += v->aOp[i].p1;
268
0
      else if (v->aOp[i].opcode == OP_String8)
269
0
        size += strlen(v->aOp[i].p4.z);
270
0
      break;
271
0
    case P4_BOOL:
272
0
      size += sizeof(v->aOp[i].p4.b);
273
0
      break;
274
0
    case P4_INT32:
275
0
      size += sizeof(v->aOp[i].p4.i);
276
0
      break;
277
0
    case P4_UINT64:
278
0
    case P4_INT64:
279
0
      size += sizeof(*v->aOp[i].p4.pI64);
280
0
      break;
281
0
    case P4_REAL:
282
0
      size += sizeof(*v->aOp[i].p4.pReal);
283
0
      break;
284
0
    case P4_DEC:
285
0
      size += sizeof(*v->aOp[i].p4.dec);
286
0
      break;
287
0
    default:
288
0
      size += sizeof(v->aOp[i].p4.p);
289
0
      break;
290
0
    }
291
0
  }
292
0
  size += strlen(v->zSql);
293
0
  return size;
294
0
}
295
296
const char *
297
sql_stmt_query_str(const struct Vdbe *v)
298
0
{
299
0
  return v->zSql;
300
0
}
301
302
/******************************* sql_bind_  **************************
303
 *
304
 * Routines used to attach values to wildcards in a compiled SQL statement.
305
 */
306
/*
307
 * Unbind the value bound to variable i in virtual machine p. This is the
308
 * the same as binding a NULL value to the column.
309
 */
310
static int
311
vdbeUnbind(struct Vdbe *p, int i)
312
0
{
313
0
  Mem *pVar;
314
0
  assert(p != NULL);
315
0
  assert(p->magic == VDBE_MAGIC_RUN && p->pc < 0);
316
0
  assert(i > 0);
317
0
  if(i > p->nVar) {
318
0
    diag_set(ClientError, ER_SQL_EXECUTE, "The number of "\
319
0
       "parameters is too large");
320
0
    return -1;
321
0
  }
322
0
  i--;
323
0
  pVar = &p->aVar[i];
324
0
  mem_destroy(pVar);
325
0
  return 0;
326
0
}
327
328
/**
329
 * This function sets type for bound variable.
330
 * We should bind types only for variables which occur in
331
 * result set of SELECT query. For example:
332
 *
333
 * SELECT id, ?, ?, a WHERE id = ?;
334
 *
335
 * In this case we should set types only for two variables.
336
 * That one which is situated under WHERE condition - is out
337
 * of our interest.
338
 *
339
 * For named binding parameters we should propagate type
340
 * for all occurrences of this parameter - since binding
341
 * routine takes place only once for each DISTINCT parameter
342
 * from list.
343
 *
344
 * @param v Current VDBE.
345
 * @param position Ordinal position of binding parameter.
346
 * @param type String literal representing type of binding param.
347
 * @retval 0 on success.
348
 */
349
static int
350
sql_bind_type(struct Vdbe *v, uint32_t position, const char *type)
351
0
{
352
0
  if (v->res_var_count < position)
353
0
    return 0;
354
0
  int rc = 0;
355
0
  if (vdbe_metadata_set_col_type(v, v->var_pos[position - 1], type) != 0)
356
0
    rc = -1;
357
0
  const char *bind_name = v->metadata[position - 1].name;
358
0
  if (strcmp(bind_name, "?") == 0)
359
0
    return rc;
360
0
  for (uint32_t i = position; i < v->res_var_count; ++i) {
361
0
    if (strcmp(bind_name, v->metadata[i].name) == 0) {
362
0
      if (vdbe_metadata_set_col_type(v, v->var_pos[i],
363
0
                   type) != 0)
364
0
        return -1;
365
0
    }
366
0
  }
367
0
  return 0;
368
0
}
369
370
void
371
sql_unbind(struct Vdbe *v)
372
0
{
373
0
  for (int i = 1; i < v->nVar + 1; ++i) {
374
0
    int rc = vdbeUnbind(v, i);
375
0
    assert(rc == 0);
376
0
    (void) rc;
377
    /*
378
     * We should re-set boolean type - unassigned
379
     * binding slots are assumed to contain NULL
380
     * value, which has boolean type.
381
     */
382
0
    sql_bind_type(v, i, "boolean");
383
0
  }
384
0
}
385
386
void
387
sql_reset_autoinc_id_list(struct Vdbe *v)
388
0
{
389
0
  stailq_create(&v->autoinc_id_list);
390
0
}
391
392
int
393
sql_bind_double(struct Vdbe *p, int i, double rValue)
394
0
{
395
0
  if (vdbeUnbind(p, i) != 0)
396
0
    return -1;
397
0
  int rc = sql_bind_type(p, i, "numeric");
398
0
  mem_set_double(&p->aVar[i - 1], rValue);
399
0
  return rc;
400
0
}
401
402
int
403
sql_bind_boolean(struct Vdbe *p, int i, bool value)
404
0
{
405
0
  if (vdbeUnbind(p, i) != 0)
406
0
    return -1;
407
0
  int rc = sql_bind_type(p, i, "boolean");
408
0
  mem_set_bool(&p->aVar[i - 1], value);
409
0
  return rc;
410
0
}
411
412
int
413
sql_bind_int(struct Vdbe *p, int i, int iValue)
414
0
{
415
0
  return sql_bind_int64(p, i, (i64) iValue);
416
0
}
417
418
int
419
sql_bind_int64(struct Vdbe *p, int i, int64_t iValue)
420
0
{
421
0
  if (vdbeUnbind(p, i) != 0)
422
0
    return -1;
423
0
  int rc = sql_bind_type(p, i, "integer");
424
0
  mem_set_int(&p->aVar[i - 1], iValue);
425
0
  return rc;
426
0
}
427
428
int
429
sql_bind_uint64(struct Vdbe *p, int i, uint64_t value)
430
0
{
431
0
  if (vdbeUnbind(p, i) != 0)
432
0
    return -1;
433
0
  int rc = sql_bind_type(p, i, "integer");
434
0
  mem_set_uint(&p->aVar[i - 1], value);
435
0
  return rc;
436
0
}
437
438
int
439
sql_bind_null(struct Vdbe *p, int i)
440
0
{
441
0
  if (vdbeUnbind(p, i) != 0)
442
0
    return -1;
443
0
  return sql_bind_type(p, i, "boolean");
444
0
}
445
446
int
447
sql_bind_ptr(struct Vdbe *p, int i, void *ptr)
448
0
{
449
0
  int rc = vdbeUnbind(p, i);
450
0
  if (rc == 0) {
451
0
    rc = sql_bind_type(p, i, "varbinary");
452
0
    mem_set_ptr(&p->aVar[i - 1], ptr);
453
0
  }
454
0
  return rc;
455
0
}
456
457
int
458
sql_bind_str_static(struct Vdbe *vdbe, int i, const char *str, uint32_t len)
459
0
{
460
0
  mem_set_str_static(&vdbe->aVar[i - 1], (char *)str, len);
461
0
  return sql_bind_type(vdbe, i, "text");
462
0
}
463
464
int
465
sql_bind_bin_static(struct Vdbe *vdbe, int i, const char *str, uint32_t size)
466
0
{
467
0
  mem_set_bin_static(&vdbe->aVar[i - 1], (char *)str, size);
468
0
  return sql_bind_type(vdbe, i, "text");
469
0
}
470
471
int
472
sql_bind_array_static(struct Vdbe *vdbe, int i, const char *str, uint32_t size)
473
0
{
474
0
  mem_set_array_static(&vdbe->aVar[i - 1], (char *)str, size);
475
0
  return sql_bind_type(vdbe, i, "array");
476
0
}
477
478
int
479
sql_bind_map_static(struct Vdbe *vdbe, int i, const char *str, uint32_t size)
480
0
{
481
0
  mem_set_map_static(&vdbe->aVar[i - 1], (char *)str, size);
482
0
  return sql_bind_type(vdbe, i, "map");
483
0
}
484
485
int
486
sql_bind_uuid(struct Vdbe *p, int i, const struct tt_uuid *uuid)
487
0
{
488
0
  if (vdbeUnbind(p, i) != 0 || sql_bind_type(p, i, "uuid") != 0)
489
0
    return -1;
490
0
  mem_set_uuid(&p->aVar[i - 1], uuid);
491
0
  return 0;
492
0
}
493
494
int
495
sql_bind_dec(struct Vdbe *p, int i, const decimal_t *dec)
496
0
{
497
0
  if (vdbeUnbind(p, i) != 0 || sql_bind_type(p, i, "decimal") != 0)
498
0
    return -1;
499
0
  mem_set_dec(&p->aVar[i - 1], dec);
500
0
  return 0;
501
0
}
502
503
int
504
sql_bind_datetime(struct Vdbe *p, int i, const struct datetime *dt)
505
0
{
506
0
  if (vdbeUnbind(p, i) != 0 || sql_bind_type(p, i, "datetime") != 0)
507
0
    return -1;
508
0
  mem_set_datetime(&p->aVar[i - 1], dt);
509
0
  return 0;
510
0
}
511
512
int
513
sql_bind_interval(struct Vdbe *p, int i, const struct interval *itv)
514
0
{
515
0
  if (vdbeUnbind(p, i) != 0 || sql_bind_type(p, i, "interval") != 0)
516
0
    return -1;
517
0
  mem_set_interval(&p->aVar[i - 1], itv);
518
0
  return 0;
519
0
}
520
521
int
522
sql_bind_parameter_count(const struct Vdbe *p)
523
0
{
524
0
  return p->nVar;
525
0
}
526
527
const char *
528
sql_bind_parameter_name(const struct Vdbe *p, int i)
529
0
{
530
0
  if (p == NULL)
531
0
    return NULL;
532
0
  return sqlVListNumToName(p->pVList, i+1);
533
0
}
534
535
/*
536
 * Given a wildcard parameter name, return the index of the variable
537
 * with that name.  If there is no variable with the given name,
538
 * return 0.
539
 */
540
int
541
sqlVdbeParameterIndex(Vdbe * p, const char *zName, int nName)
542
0
{
543
0
  if (p == 0 || zName == 0)
544
0
    return 0;
545
0
  return sqlVListNameToNum(p->pVList, zName, nName);
546
0
}
547
548
int
549
sql_bind_parameter_lindex(struct Vdbe *v, const char *zName, int nName)
550
0
{
551
0
  return sqlVdbeParameterIndex(v, zName, nName);
552
0
}
553
554
int
555
sqlTransferBindings(struct Vdbe *pFrom, struct Vdbe *pTo)
556
0
{
557
0
  int i;
558
0
  assert(pTo->nVar == pFrom->nVar);
559
0
  for (i = 0; i < pFrom->nVar; i++) {
560
0
    mem_move(&pTo->aVar[i], &pFrom->aVar[i]);
561
0
  }
562
0
  return 0;
563
0
}
564
565
int
566
sql_stmt_busy(const struct Vdbe *v)
567
8.64k
{
568
8.64k
  assert(v != NULL);
569
8.64k
  return v->magic == VDBE_MAGIC_RUN && v->pc >= 0;
570
8.64k
}
571
572
const char *
573
sql_sql(struct Vdbe *p)
574
0
{
575
0
  return p ? p->zSql : 0;
576
0
}