~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/row/row0mysql.c

  • Committer: Monty Taylor
  • Date: 2010-11-25 01:53:19 UTC
  • mto: (1953.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1955.
  • Revision ID: mordred@inaugust.com-20101125015319-ia85msn25uemopgc
Re-enabled -Wformat and then cleaned up the carnage.

Show diffs side-by-side

added added

removed removed

Lines of Context:
249
249
}
250
250
 
251
251
/**************************************************************//**
252
 
Pad a column with spaces. */
253
 
UNIV_INTERN
254
 
void
255
 
row_mysql_pad_col(
256
 
/*==============*/
257
 
        ulint   mbminlen,       /*!< in: minimum size of a character,
258
 
                                in bytes */
259
 
        byte*   pad,            /*!< out: padded buffer */
260
 
        ulint   len)            /*!< in: number of bytes to pad */
261
 
{
262
 
        const byte*     pad_end;
263
 
 
264
 
        switch (UNIV_EXPECT(mbminlen, 1)) {
265
 
        default:
266
 
                ut_error;
267
 
        case 1:
268
 
                /* space=0x20 */
269
 
                memset(pad, 0x20, len);
270
 
                break;
271
 
        case 2:
272
 
                /* space=0x0020 */
273
 
                pad_end = pad + len;
274
 
                ut_a(!(len % 2));
275
 
                do {
276
 
                        *pad++ = 0x00;
277
 
                        *pad++ = 0x20;
278
 
                } while (pad < pad_end);
279
 
                break;
280
 
        case 4:
281
 
                /* space=0x00000020 */
282
 
                pad_end = pad + len;
283
 
                ut_a(!(len % 4));
284
 
                do {
285
 
                        *pad++ = 0x00;
286
 
                        *pad++ = 0x00;
287
 
                        *pad++ = 0x00;
288
 
                        *pad++ = 0x20;
289
 
                } while (pad < pad_end);
290
 
                break;
291
 
        }
292
 
}
293
 
 
294
 
/**************************************************************//**
295
252
Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
296
253
The counterpart of this function is row_sel_field_store_in_mysql_format() in
297
254
row0sel.c.
383
340
                        /* Remove trailing spaces from old style VARCHAR
384
341
                        columns. */
385
342
 
386
 
                        /* Handle Unicode strings differently. */
 
343
                        /* Handle UCS2 strings differently. */
387
344
                        ulint   mbminlen        = dtype_get_mbminlen(dtype);
388
345
 
389
346
                        ptr = mysql_data;
390
347
 
391
 
                        switch (mbminlen) {
392
 
                        default:
393
 
                                ut_error;
394
 
                        case 4:
395
 
                                /* space=0x00000020 */
396
 
                                /* Trim "half-chars", just in case. */
397
 
                                col_len &= ~3;
398
 
 
399
 
                                while (col_len >= 4
400
 
                                       && ptr[col_len - 4] == 0x00
401
 
                                       && ptr[col_len - 3] == 0x00
402
 
                                       && ptr[col_len - 2] == 0x00
403
 
                                       && ptr[col_len - 1] == 0x20) {
404
 
                                        col_len -= 4;
405
 
                                }
406
 
                                break;
407
 
                        case 2:
 
348
                        if (mbminlen == 2) {
408
349
                                /* space=0x0020 */
409
350
                                /* Trim "half-chars", just in case. */
410
351
                                col_len &= ~1;
413
354
                                       && ptr[col_len - 1] == 0x20) {
414
355
                                        col_len -= 2;
415
356
                                }
416
 
                                break;
417
 
                        case 1:
 
357
                        } else {
 
358
                                ut_a(mbminlen == 1);
418
359
                                /* space=0x20 */
419
360
                                while (col_len > 0
420
361
                                       && ptr[col_len - 1] == 0x20) {
618
559
                      "InnoDB: " REFMAN "forcing-recovery.html"
619
560
                      " for help.\n", stderr);
620
561
                break;
621
 
        case DB_FOREIGN_EXCEED_MAX_CASCADE:
622
 
                fprintf(stderr, "InnoDB: Cannot delete/update rows with"
623
 
                        " cascading foreign key constraints that exceed max"
624
 
                        " depth of %lu\n"
625
 
                        "Please drop excessive foreign constraints"
626
 
                        " and try again\n", (ulong) DICT_FK_MAX_RECURSIVE_LOAD);
627
 
                break;
628
562
        default:
629
563
                fprintf(stderr, "InnoDB: unknown error code %lu\n",
630
564
                        (ulong) err);
674
608
 
675
609
        prebuilt->select_lock_type = LOCK_NONE;
676
610
        prebuilt->stored_select_lock_type = 99999999;
677
 
        UNIV_MEM_INVALID(&prebuilt->stored_select_lock_type,
678
 
                         sizeof prebuilt->stored_select_lock_type);
679
611
 
680
612
        prebuilt->search_tuple = dtuple_create(
681
613
                heap, 2 * dict_table_get_n_cols(table));
840
772
        }
841
773
}
842
774
 
843
 
dtuple_t* row_get_prebuilt_insert_row(row_prebuilt_t*   prebuilt);
844
 
 
845
775
/*********************************************************************//**
846
776
Gets pointer to a prebuilt dtuple used in insertions. If the insert graph
847
777
has not yet been built in the prebuilt struct, then this function first
848
778
builds it.
849
779
@return prebuilt dtuple; the column type information is also set in it */
 
780
static
850
781
dtuple_t*
851
782
row_get_prebuilt_insert_row(
852
783
/*========================*/
1431
1362
run_again:
1432
1363
        thr->run_node = node;
1433
1364
        thr->prev_node = node;
1434
 
        thr->fk_cascade_depth = 0;
1435
1365
 
1436
1366
        row_upd_step(thr);
1437
1367
 
1438
 
        /* The recursive call for cascading update/delete happens
1439
 
        in above row_upd_step(), reset the counter once we come
1440
 
        out of the recursive call, so it does not accumulate for
1441
 
        different row deletes */
1442
 
        thr->fk_cascade_depth = 0;
1443
 
 
1444
1368
        err = trx->error_state;
1445
1369
 
1446
 
        /* Reset fk_cascade_depth back to 0 */
1447
 
        thr->fk_cascade_depth = 0;
1448
 
 
1449
1370
        if (err != DB_SUCCESS) {
1450
1371
                que_thr_stop_for_mysql(thr);
1451
1372
 
1482
1403
                srv_n_rows_updated++;
1483
1404
        }
1484
1405
 
1485
 
        /* We update table statistics only if it is a DELETE or UPDATE
1486
 
        that changes indexed columns, UPDATEs that change only non-indexed
1487
 
        columns would not affect statistics. */
1488
 
        if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
1489
 
                row_update_statistics_if_needed(prebuilt->table);
1490
 
        }
 
1406
        row_update_statistics_if_needed(prebuilt->table);
1491
1407
 
1492
1408
        trx->op_info = "";
1493
1409
 
1495
1411
}
1496
1412
 
1497
1413
/*********************************************************************//**
1498
 
This can only be used when srv_locks_unsafe_for_binlog is TRUE or this
1499
 
session is using a READ COMMITTED or READ UNCOMMITTED isolation level.
1500
 
Before calling this function row_search_for_mysql() must have
1501
 
initialized prebuilt->new_rec_locks to store the information which new
1502
 
record locks really were set. This function removes a newly set
1503
 
clustered index record lock under prebuilt->pcur or
1504
 
prebuilt->clust_pcur.  Thus, this implements a 'mini-rollback' that
1505
 
releases the latest clustered index record lock we set.
1506
 
@return error code or DB_SUCCESS */
 
1414
This can only be used when srv_locks_unsafe_for_binlog is TRUE or
 
1415
this session is using a READ COMMITTED isolation level. Before
 
1416
calling this function we must use trx_reset_new_rec_lock_info() and
 
1417
trx_register_new_rec_lock() to store the information which new record locks
 
1418
really were set. This function removes a newly set lock under prebuilt->pcur,
 
1419
and also under prebuilt->clust_pcur. Currently, this is only used and tested
 
1420
in the case of an UPDATE or a DELETE statement, where the row lock is of the
 
1421
LOCK_X type.
 
1422
Thus, this implements a 'mini-rollback' that releases the latest record
 
1423
locks we set.
 
1424
@return error code or DB_SUCCESS */
1507
1425
UNIV_INTERN
1508
1426
int
1509
1427
row_unlock_for_mysql(
1510
1428
/*=================*/
1511
 
        row_prebuilt_t* prebuilt,       /*!< in/out: prebuilt struct in MySQL
 
1429
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL
1512
1430
                                        handle */
1513
 
        ibool           has_latches_on_recs)/*!< in: TRUE if called so
1514
 
                                        that we have the latches on
1515
 
                                        the records under pcur and
1516
 
                                        clust_pcur, and we do not need
1517
 
                                        to reposition the cursors. */
 
1431
        ibool           has_latches_on_recs)/*!< TRUE if called so that we have
 
1432
                                        the latches on the records under pcur
 
1433
                                        and clust_pcur, and we do not need to
 
1434
                                        reposition the cursors. */
1518
1435
{
1519
1436
        btr_pcur_t*     pcur            = prebuilt->pcur;
1520
1437
        btr_pcur_t*     clust_pcur      = prebuilt->clust_pcur;
1597
1514
                        }
1598
1515
                }
1599
1516
 
1600
 
                if (rec_trx_id != trx->id) {
 
1517
                if (ut_dulint_cmp(rec_trx_id, trx->id) != 0) {
1601
1518
                        /* We did not update the record: unlock it */
1602
1519
 
1603
1520
                        rec = btr_pcur_get_rec(pcur);
1641
1558
        trx_t*  trx;
1642
1559
 
1643
1560
        trx = thr_get_trx(thr);
1644
 
 
1645
 
        /* Increment fk_cascade_depth to record the recursive call depth on
1646
 
        a single update/delete that affects multiple tables chained
1647
 
        together with foreign key relations. */
1648
 
        thr->fk_cascade_depth++;
1649
 
 
1650
 
        if (thr->fk_cascade_depth > FK_MAX_CASCADE_DEL) {
1651
 
                return (DB_FOREIGN_EXCEED_MAX_CASCADE);
1652
 
        }
1653
1561
run_again:
1654
1562
        thr->run_node = node;
1655
1563
        thr->prev_node = node;
1656
1564
 
1657
1565
        row_upd_step(thr);
1658
1566
 
1659
 
        /* The recursive call for cascading update/delete happens
1660
 
        in above row_upd_step(), reset the counter once we come
1661
 
        out of the recursive call, so it does not accumulate for
1662
 
        different row deletes */
1663
 
        thr->fk_cascade_depth = 0;
1664
 
 
1665
1567
        err = trx->error_state;
1666
1568
 
1667
1569
        /* Note that the cascade node is a subnode of another InnoDB
2124
2026
                                              name, reject_fks);
2125
2027
        if (err == DB_SUCCESS) {
2126
2028
                /* Check that also referencing constraints are ok */
2127
 
                err = dict_load_foreigns(name, FALSE, TRUE);
 
2029
                err = dict_load_foreigns(name, TRUE);
2128
2030
        }
2129
2031
 
2130
2032
        if (err != DB_SUCCESS) {
2351
2253
        trx_t*          trx)    /*!< in: transaction handle */
2352
2254
{
2353
2255
        dict_foreign_t* foreign;
2354
 
        table_id_t      new_id;
 
2256
        dulint          new_id;
2355
2257
        dict_table_t*   table;
2356
2258
        ibool           success;
2357
2259
        ulint           err;
2473
2375
        info = pars_info_create();
2474
2376
 
2475
2377
        pars_info_add_str_literal(info, "table_name", name);
2476
 
        pars_info_add_ull_literal(info, "new_id", new_id);
 
2378
        pars_info_add_dulint_literal(info, "new_id", new_id);
2477
2379
 
2478
2380
        err = que_eval_sql(info,
2479
2381
                           "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
2687
2589
        dict_index_t*   sys_index;
2688
2590
        btr_pcur_t      pcur;
2689
2591
        mtr_t           mtr;
2690
 
        table_id_t      new_id;
 
2592
        dulint          new_id;
2691
2593
        ulint           recreate_space = 0;
2692
2594
        pars_info_t*    info = NULL;
2693
2595
 
2817
2719
 
2818
2720
        trx->table_id = table->id;
2819
2721
 
2820
 
        /* Lock all index trees for this table, as we will
2821
 
        truncate the table/index and possibly change their metadata.
2822
 
        All DML/DDL are blocked by table level lock, with
2823
 
        a few exceptions such as queries into information schema
2824
 
        about the table, MySQL could try to access index stats
2825
 
        for this kind of query, we need to use index locks to
2826
 
        sync up */
2827
 
        dict_table_x_lock_indexes(table);
2828
 
 
2829
2722
        if (table->space && !table->dir_path_of_temp_table) {
2830
2723
                /* Discard and create the single-table tablespace. */
2831
2724
                ulint   space   = table->space;
2842
2735
                            || fil_create_new_single_table_tablespace(
2843
2736
                                    space, table->name, FALSE, flags,
2844
2737
                                    FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2845
 
                                dict_table_x_unlock_indexes(table);
2846
2738
                                ut_print_timestamp(stderr);
2847
2739
                                fprintf(stderr,
2848
2740
                                        "  InnoDB: TRUNCATE TABLE %s failed to"
2946
2838
 
2947
2839
        mem_heap_free(heap);
2948
2840
 
2949
 
        /* Done with index truncation, release index tree locks,
2950
 
        subsequent work relates to table level metadata change */
2951
 
        dict_table_x_unlock_indexes(table);
2952
 
 
2953
2841
        dict_hdr_get_new_id(&new_id, NULL, NULL);
2954
2842
 
2955
2843
        info = pars_info_create();
2956
2844
 
2957
2845
        pars_info_add_int4_literal(info, "space", (lint) table->space);
2958
 
        pars_info_add_ull_literal(info, "old_id", table->id);
2959
 
        pars_info_add_ull_literal(info, "new_id", new_id);
 
2846
        pars_info_add_dulint_literal(info, "old_id", table->id);
 
2847
        pars_info_add_dulint_literal(info, "new_id", new_id);
2960
2848
 
2961
2849
        err = que_eval_sql(info,
2962
2850
                           "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
3343
3231
 
3344
3232
                dict_table_remove_from_cache(table);
3345
3233
 
3346
 
                if (dict_load_table(name, TRUE) != NULL) {
 
3234
                if (dict_load_table(name) != NULL) {
3347
3235
                        ut_print_timestamp(stderr);
3348
3236
                        fputs("  InnoDB: Error: not able to remove table ",
3349
3237
                              stderr);
3489
3377
                btr_pcur_store_position(&pcur, &mtr);
3490
3378
                btr_pcur_commit_specify_mtr(&pcur, &mtr);
3491
3379
 
3492
 
                table = dict_load_table(table_name, TRUE);
 
3380
                table = dict_load_table(table_name);
3493
3381
 
3494
3382
                if (table) {
3495
3383
                        row_drop_table_for_mysql(table_name, trx, FALSE);
4001
3889
                an ALTER, not in a RENAME. */
4002
3890
 
4003
3891
                err = dict_load_foreigns(
4004
 
                        new_name, FALSE, !old_is_tmp || trx->check_foreigns);
 
3892
                        new_name, !old_is_tmp || trx->check_foreigns);
4005
3893
 
4006
3894
                if (err != DB_SUCCESS) {
4007
3895
                        ut_print_timestamp(stderr);