~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-12-02 22:51:54 UTC
  • mto: (1975.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1976.
  • Revision ID: mordred@inaugust.com-20101202225154-h54ifmga9x6cckgs
Refactored syslog module and changed it to use sys_var directly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 2000, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 2000, 2010, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
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) {
486
427
                                        row is used, as row may contain
487
428
                                        pointers to this record! */
488
429
{
489
 
        const mysql_row_templ_t*templ;
 
430
        mysql_row_templ_t*      templ;
490
431
        dfield_t*               dfield;
491
432
        ulint                   i;
492
433
 
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);
659
593
 
660
594
        heap = mem_heap_create(sizeof *prebuilt + 128);
661
595
 
662
 
        prebuilt = static_cast<row_prebuilt_t *>(mem_heap_zalloc(heap, sizeof *prebuilt));
 
596
        prebuilt = mem_heap_zalloc(heap, sizeof *prebuilt);
663
597
 
664
598
        prebuilt->magic_n = ROW_PREBUILT_ALLOCATED;
665
599
        prebuilt->magic_n2 = ROW_PREBUILT_ALLOCATED;
840
774
        }
841
775
}
842
776
 
843
 
dtuple_t* row_get_prebuilt_insert_row(row_prebuilt_t*   prebuilt);
844
 
 
845
777
/*********************************************************************//**
846
778
Gets pointer to a prebuilt dtuple used in insertions. If the insert graph
847
779
has not yet been built in the prebuilt struct, then this function first
848
780
builds it.
849
781
@return prebuilt dtuple; the column type information is also set in it */
 
782
static
850
783
dtuple_t*
851
784
row_get_prebuilt_insert_row(
852
785
/*========================*/
869
802
                prebuilt->ins_node = node;
870
803
 
871
804
                if (prebuilt->ins_upd_rec_buff == NULL) {
872
 
                        prebuilt->ins_upd_rec_buff = static_cast<byte *>(mem_heap_alloc(
873
 
                                prebuilt->heap, prebuilt->mysql_row_len));
 
805
                        prebuilt->ins_upd_rec_buff = mem_heap_alloc(
 
806
                                prebuilt->heap, prebuilt->mysql_row_len);
874
807
                }
875
808
 
876
809
                row = dtuple_create(prebuilt->heap,
880
813
 
881
814
                ins_node_set_new_row(node, row);
882
815
 
883
 
                prebuilt->ins_graph = static_cast<que_fork_t *>(que_node_get_parent(
 
816
                prebuilt->ins_graph = que_node_get_parent(
884
817
                        pars_complete_graph_for_exec(node,
885
818
                                                     prebuilt->trx,
886
 
                                                     prebuilt->heap)));
 
819
                                                     prebuilt->heap));
887
820
                prebuilt->ins_graph->state = QUE_FORK_ACTIVE;
888
821
        }
889
822
 
914
847
        if (counter > 2000000000
915
848
            || ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
916
849
 
917
 
                dict_update_statistics(table, FALSE /* update even if stats
918
 
                                                    are initialized */);
 
850
                dict_update_statistics(table);
919
851
        }
920
852
}
921
853
 
1066
998
        trx_start_if_not_started(trx);
1067
999
 
1068
1000
        if (table) {
1069
 
                err = lock_table(0, table, static_cast<lock_mode>(mode), thr);
 
1001
                err = lock_table(0, table, mode, thr);
1070
1002
        } else {
1071
1003
                err = lock_table(0, prebuilt->table,
1072
 
                                 static_cast<lock_mode>(prebuilt->select_lock_type), thr);
 
1004
                                 prebuilt->select_lock_type, thr);
1073
1005
        }
1074
1006
 
1075
1007
        trx->error_state = err;
1244
1176
 
1245
1177
                node = sel_node_create(prebuilt->heap);
1246
1178
 
1247
 
                prebuilt->sel_graph = static_cast<que_fork_t *>(que_node_get_parent(
 
1179
                prebuilt->sel_graph = que_node_get_parent(
1248
1180
                        pars_complete_graph_for_exec(node,
1249
1181
                                                     prebuilt->trx,
1250
 
                                                     prebuilt->heap)));
 
1182
                                                     prebuilt->heap));
1251
1183
 
1252
1184
                prebuilt->sel_graph->state = QUE_FORK_ACTIVE;
1253
1185
        }
1315
1247
 
1316
1248
                prebuilt->upd_node = node;
1317
1249
 
1318
 
                prebuilt->upd_graph = static_cast<que_fork_t *>(que_node_get_parent(
 
1250
                prebuilt->upd_graph = que_node_get_parent(
1319
1251
                        pars_complete_graph_for_exec(node,
1320
1252
                                                     prebuilt->trx,
1321
 
                                                     prebuilt->heap)));
 
1253
                                                     prebuilt->heap));
1322
1254
                prebuilt->upd_graph->state = QUE_FORK_ACTIVE;
1323
1255
        }
1324
1256
 
1432
1364
run_again:
1433
1365
        thr->run_node = node;
1434
1366
        thr->prev_node = node;
1435
 
        thr->fk_cascade_depth = 0;
1436
1367
 
1437
1368
        row_upd_step(thr);
1438
1369
 
1439
 
        /* The recursive call for cascading update/delete happens
1440
 
        in above row_upd_step(), reset the counter once we come
1441
 
        out of the recursive call, so it does not accumulate for
1442
 
        different row deletes */
1443
 
        thr->fk_cascade_depth = 0;
1444
 
 
1445
1370
        err = trx->error_state;
1446
1371
 
1447
 
        /* Reset fk_cascade_depth back to 0 */
1448
 
        thr->fk_cascade_depth = 0;
1449
 
 
1450
1372
        if (err != DB_SUCCESS) {
1451
1373
                que_thr_stop_for_mysql(thr);
1452
1374
 
1483
1405
                srv_n_rows_updated++;
1484
1406
        }
1485
1407
 
1486
 
        /* We update table statistics only if it is a DELETE or UPDATE
1487
 
        that changes indexed columns, UPDATEs that change only non-indexed
1488
 
        columns would not affect statistics. */
1489
 
        if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
1490
 
                row_update_statistics_if_needed(prebuilt->table);
1491
 
        }
 
1408
        row_update_statistics_if_needed(prebuilt->table);
1492
1409
 
1493
1410
        trx->op_info = "";
1494
1411
 
1598
1515
                        }
1599
1516
                }
1600
1517
 
1601
 
                if (rec_trx_id != trx->id) {
 
1518
                if (ut_dulint_cmp(rec_trx_id, trx->id) != 0) {
1602
1519
                        /* We did not update the record: unlock it */
1603
1520
 
1604
1521
                        rec = btr_pcur_get_rec(pcur);
1605
1522
                        index = btr_pcur_get_btr_cur(pcur)->index;
1606
1523
 
1607
1524
                        lock_rec_unlock(trx, btr_pcur_get_block(pcur),
1608
 
                                        rec, static_cast<lock_mode>(prebuilt->select_lock_type));
 
1525
                                        rec, prebuilt->select_lock_type);
1609
1526
 
1610
1527
                        if (prebuilt->new_rec_locks >= 2) {
1611
1528
                                rec = btr_pcur_get_rec(clust_pcur);
1614
1531
                                lock_rec_unlock(trx,
1615
1532
                                                btr_pcur_get_block(clust_pcur),
1616
1533
                                                rec,
1617
 
                                                static_cast<lock_mode>(prebuilt->select_lock_type));
 
1534
                                                prebuilt->select_lock_type);
1618
1535
                        }
1619
1536
                }
1620
1537
no_unlock:
1642
1559
        trx_t*  trx;
1643
1560
 
1644
1561
        trx = thr_get_trx(thr);
1645
 
 
1646
 
        /* Increment fk_cascade_depth to record the recursive call depth on
1647
 
        a single update/delete that affects multiple tables chained
1648
 
        together with foreign key relations. */
1649
 
        thr->fk_cascade_depth++;
1650
 
 
1651
 
        if (thr->fk_cascade_depth > FK_MAX_CASCADE_DEL) {
1652
 
                return (DB_FOREIGN_EXCEED_MAX_CASCADE);
1653
 
        }
1654
1562
run_again:
1655
1563
        thr->run_node = node;
1656
1564
        thr->prev_node = node;
1657
1565
 
1658
1566
        row_upd_step(thr);
1659
1567
 
1660
 
        /* The recursive call for cascading update/delete happens
1661
 
        in above row_upd_step(), reset the counter once we come
1662
 
        out of the recursive call, so it does not accumulate for
1663
 
        different row deletes */
1664
 
        thr->fk_cascade_depth = 0;
1665
 
 
1666
1568
        err = trx->error_state;
1667
1569
 
1668
1570
        /* Note that the cascade node is a subnode of another InnoDB
1912
1814
 
1913
1815
        thr = pars_complete_graph_for_exec(node, trx, heap);
1914
1816
 
1915
 
        ut_a(thr == que_fork_start_command(static_cast<que_fork_t *>(que_node_get_parent(thr))));
 
1817
        ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
1916
1818
        que_run_threads(thr);
1917
1819
 
1918
1820
        err = trx->error_state;
1919
1821
 
 
1822
        if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
 
1823
                trx->error_state = DB_SUCCESS;
 
1824
                trx_general_rollback_for_mysql(trx, NULL);
 
1825
                /* TO DO: free table?  The code below will dereference
 
1826
                table->name, though. */
 
1827
        }
 
1828
 
1920
1829
        switch (err) {
1921
 
        case DB_SUCCESS:
1922
 
                break;
1923
1830
        case DB_OUT_OF_FILE_SPACE:
1924
 
                trx->error_state = DB_SUCCESS;
1925
 
                trx_general_rollback_for_mysql(trx, NULL);
1926
 
 
1927
1831
                ut_print_timestamp(stderr);
1928
1832
                fputs("  InnoDB: Warning: cannot create table ",
1929
1833
                      stderr);
1938
1842
                break;
1939
1843
 
1940
1844
        case DB_DUPLICATE_KEY:
1941
 
        default:
1942
1845
                /* We may also get err == DB_ERROR if the .ibd file for the
1943
1846
                table already exists */
1944
1847
 
1945
 
                trx->error_state = DB_SUCCESS;
1946
 
                trx_general_rollback_for_mysql(trx, NULL);
1947
 
                dict_mem_table_free(table);
1948
1848
                break;
1949
1849
        }
1950
1850
 
2053
1953
 
2054
1954
        thr = pars_complete_graph_for_exec(node, trx, heap);
2055
1955
 
2056
 
        ut_a(thr == que_fork_start_command(static_cast<que_fork_t *>(que_node_get_parent(thr))));
 
1956
        ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
2057
1957
        que_run_threads(thr);
2058
1958
 
2059
1959
        err = trx->error_state;
2127
2027
                                              name, reject_fks);
2128
2028
        if (err == DB_SUCCESS) {
2129
2029
                /* Check that also referencing constraints are ok */
2130
 
                err = dict_load_foreigns(name, FALSE, TRUE);
 
2030
                err = dict_load_foreigns(name, TRUE);
2131
2031
        }
2132
2032
 
2133
2033
        if (err != DB_SUCCESS) {
2326
2226
                drop = UT_LIST_GET_NEXT(row_mysql_drop_list, drop);
2327
2227
        }
2328
2228
 
2329
 
        drop = static_cast<row_mysql_drop_t *>(mem_alloc(sizeof(row_mysql_drop_t)));
 
2229
        drop = mem_alloc(sizeof(row_mysql_drop_t));
2330
2230
 
2331
2231
        drop->table_name = mem_strdup(name);
2332
2232
 
2354
2254
        trx_t*          trx)    /*!< in: transaction handle */
2355
2255
{
2356
2256
        dict_foreign_t* foreign;
2357
 
        table_id_t      new_id;
 
2257
        dulint          new_id;
2358
2258
        dict_table_t*   table;
2359
2259
        ibool           success;
2360
2260
        ulint           err;
2476
2376
        info = pars_info_create();
2477
2377
 
2478
2378
        pars_info_add_str_literal(info, "table_name", name);
2479
 
        pars_info_add_ull_literal(info, "new_id", new_id);
 
2379
        pars_info_add_dulint_literal(info, "new_id", new_id);
2480
2380
 
2481
2381
        err = que_eval_sql(info,
2482
2382
                           "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
2690
2590
        dict_index_t*   sys_index;
2691
2591
        btr_pcur_t      pcur;
2692
2592
        mtr_t           mtr;
2693
 
        table_id_t      new_id;
 
2593
        dulint          new_id;
2694
2594
        ulint           recreate_space = 0;
2695
2595
        pars_info_t*    info = NULL;
2696
2596
 
2832
2732
 
2833
2733
                        dict_hdr_get_new_id(NULL, NULL, &space);
2834
2734
 
2835
 
                        /* Lock all index trees for this table. We must
2836
 
                        do so after dict_hdr_get_new_id() to preserve
2837
 
                        the latch order */
2838
 
                        dict_table_x_lock_indexes(table);
2839
 
 
2840
2735
                        if (space == ULINT_UNDEFINED
2841
2736
                            || fil_create_new_single_table_tablespace(
2842
2737
                                    space, table->name, FALSE, flags,
2843
2738
                                    FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2844
 
                                dict_table_x_unlock_indexes(table);
2845
2739
                                ut_print_timestamp(stderr);
2846
2740
                                fprintf(stderr,
2847
2741
                                        "  InnoDB: TRUNCATE TABLE %s failed to"
2870
2764
                                        FIL_IBD_FILE_INITIAL_SIZE, &mtr);
2871
2765
                        mtr_commit(&mtr);
2872
2766
                }
2873
 
        } else {
2874
 
                /* Lock all index trees for this table, as we will
2875
 
                truncate the table/index and possibly change their metadata.
2876
 
                All DML/DDL are blocked by table level lock, with
2877
 
                a few exceptions such as queries into information schema
2878
 
                about the table, MySQL could try to access index stats
2879
 
                for this kind of query, we need to use index locks to
2880
 
                sync up */
2881
 
                dict_table_x_lock_indexes(table);
2882
2767
        }
2883
2768
 
2884
2769
        /* scan SYS_INDEXES for all indexes of the table */
2887
2772
        tuple = dtuple_create(heap, 1);
2888
2773
        dfield = dtuple_get_nth_field(tuple, 0);
2889
2774
 
2890
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 8));
 
2775
        buf = mem_heap_alloc(heap, 8);
2891
2776
        mach_write_to_8(buf, table->id);
2892
2777
 
2893
2778
        dfield_set_data(dfield, buf, 8);
2954
2839
 
2955
2840
        mem_heap_free(heap);
2956
2841
 
2957
 
        /* Done with index truncation, release index tree locks,
2958
 
        subsequent work relates to table level metadata change */
2959
 
        dict_table_x_unlock_indexes(table);
2960
 
 
2961
2842
        dict_hdr_get_new_id(&new_id, NULL, NULL);
2962
2843
 
2963
2844
        info = pars_info_create();
2964
2845
 
2965
2846
        pars_info_add_int4_literal(info, "space", (lint) table->space);
2966
 
        pars_info_add_ull_literal(info, "old_id", table->id);
2967
 
        pars_info_add_ull_literal(info, "new_id", new_id);
 
2847
        pars_info_add_dulint_literal(info, "old_id", table->id);
 
2848
        pars_info_add_dulint_literal(info, "new_id", new_id);
2968
2849
 
2969
2850
        err = que_eval_sql(info,
2970
2851
                           "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
3004
2885
        dict_table_autoinc_lock(table);
3005
2886
        dict_table_autoinc_initialize(table, 1);
3006
2887
        dict_table_autoinc_unlock(table);
3007
 
        dict_update_statistics(table, FALSE /* update even if stats are
3008
 
                                            initialized */);
 
2888
        dict_update_statistics(table);
3009
2889
 
3010
2890
        trx_commit_for_mysql(trx);
3011
2891
 
3213
3093
 
3214
3094
        if (table->n_foreign_key_checks_running > 0) {
3215
3095
 
3216
 
                const char*     i_table_name = table->name;
 
3096
                const char*     table_name = table->name;
3217
3097
                ibool           added;
3218
3098
 
3219
 
                added = row_add_table_to_background_drop_list(i_table_name);
 
3099
                added = row_add_table_to_background_drop_list(table_name);
3220
3100
 
3221
3101
                if (added) {
3222
3102
                        ut_print_timestamp(stderr);
3223
3103
                        fputs("  InnoDB: You are trying to drop table ",
3224
3104
                              stderr);
3225
 
                        ut_print_name(stderr, trx, TRUE, i_table_name);
 
3105
                        ut_print_name(stderr, trx, TRUE, table_name);
3226
3106
                        fputs("\n"
3227
3107
                              "InnoDB: though there is a"
3228
3108
                              " foreign key check running on it.\n"
4010
3890
                an ALTER, not in a RENAME. */
4011
3891
 
4012
3892
                err = dict_load_foreigns(
4013
 
                        new_name, FALSE, !old_is_tmp || trx->check_foreigns);
 
3893
                        new_name, !old_is_tmp || trx->check_foreigns);
4014
3894
 
4015
3895
                if (err != DB_SUCCESS) {
4016
3896
                        ut_print_timestamp(stderr);
4095
3975
 
4096
3976
        *n_rows = 0;
4097
3977
 
4098
 
        buf = static_cast<byte *>(mem_alloc(UNIV_PAGE_SIZE));
 
3978
        buf = mem_alloc(UNIV_PAGE_SIZE);
4099
3979
        heap = mem_heap_create(100);
4100
3980
 
4101
3981
        cnt = 1000;
4196
4076
                                * sizeof *offsets;
4197
4077
 
4198
4078
                        tmp_heap = mem_heap_create(size);
4199
 
                        offsets = static_cast<ulint *>(mem_heap_dup(tmp_heap, offsets, size));
 
4079
                        offsets = mem_heap_dup(tmp_heap, offsets, size);
4200
4080
                }
4201
4081
 
4202
4082
                mem_heap_empty(heap);