row0row.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:16k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. General row routines
  3. (c) 1996 Innobase Oy
  4. Created 4/20/1996 Heikki Tuuri
  5. *******************************************************/
  6. #include "row0row.h"
  7. #ifdef UNIV_NONINL
  8. #include "row0row.ic"
  9. #endif
  10. #include "dict0dict.h"
  11. #include "btr0btr.h"
  12. #include "mach0data.h"
  13. #include "trx0rseg.h"
  14. #include "trx0trx.h"
  15. #include "trx0roll.h"
  16. #include "trx0undo.h"
  17. #include "trx0purge.h"
  18. #include "trx0rec.h"
  19. #include "que0que.h"
  20. #include "row0row.h"
  21. #include "row0upd.h"
  22. #include "rem0cmp.h"
  23. #include "read0read.h"
  24. /*************************************************************************
  25. Reads the trx id or roll ptr field from a clustered index record: this function
  26. is slower than the specialized inline functions. */
  27. dulint
  28. row_get_rec_sys_field(
  29. /*==================*/
  30. /* out: value of the field */
  31. ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
  32. rec_t* rec, /* in: record */
  33. dict_index_t* index) /* in: clustered index */
  34. {
  35. ulint pos;
  36. byte* field;
  37. ulint len;
  38. ut_ad(index->type & DICT_CLUSTERED);
  39. pos = dict_index_get_sys_col_pos(index, type);
  40. field = rec_get_nth_field(rec, pos, &len);
  41. if (type == DATA_TRX_ID) {
  42. return(trx_read_trx_id(field));
  43. } else {
  44. ut_ad(type == DATA_ROLL_PTR);
  45. return(trx_read_roll_ptr(field));
  46. }
  47. }
  48. /*************************************************************************
  49. Sets the trx id or roll ptr field in a clustered index record: this function
  50. is slower than the specialized inline functions. */
  51. void
  52. row_set_rec_sys_field(
  53. /*==================*/
  54. /* out: value of the field */
  55. ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
  56. rec_t* rec, /* in: record */
  57. dict_index_t* index, /* in: clustered index */
  58. dulint val) /* in: value to set */
  59. {
  60. ulint pos;
  61. byte* field;
  62. ulint len;
  63. ut_ad(index->type & DICT_CLUSTERED);
  64. pos = dict_index_get_sys_col_pos(index, type);
  65. field = rec_get_nth_field(rec, pos, &len);
  66. if (type == DATA_TRX_ID) {
  67. trx_write_trx_id(field, val);
  68. } else {
  69. ut_ad(type == DATA_ROLL_PTR);
  70. trx_write_roll_ptr(field, val);
  71. }
  72. }
  73. /*********************************************************************
  74. When an insert to a table is performed, this function builds the entry which
  75. has to be inserted to an index on the table. */
  76. dtuple_t*
  77. row_build_index_entry(
  78. /*==================*/
  79. /* out: index entry which should be inserted */
  80. dtuple_t* row,  /* in: row which should be inserted to the
  81. table */
  82. dict_index_t* index,  /* in: index on the table */
  83. mem_heap_t* heap) /* in: memory heap from which the memory for
  84. the index entry is allocated */
  85. {
  86. dtuple_t* entry;
  87. ulint entry_len;
  88. dict_field_t* ind_field;
  89. dfield_t* dfield;
  90. dfield_t* dfield2;
  91. dict_col_t* col;
  92. ulint i;
  93. ut_ad(row && index && heap);
  94. ut_ad(dtuple_check_typed(row));
  95. entry_len = dict_index_get_n_fields(index);
  96. entry = dtuple_create(heap, entry_len);
  97. if (index->type & DICT_UNIVERSAL) {
  98. dtuple_set_n_fields_cmp(entry, entry_len);
  99. } else {
  100. dtuple_set_n_fields_cmp(entry,
  101. dict_index_get_n_unique_in_tree(index));
  102. }
  103. for (i = 0; i < entry_len; i++) {
  104. ind_field = dict_index_get_nth_field(index, i);
  105. col = ind_field->col;
  106. dfield = dtuple_get_nth_field(entry, i);
  107. dfield2 = dtuple_get_nth_field(row, dict_col_get_no(col));
  108. dfield_copy(dfield, dfield2);
  109. dfield->col_no = dict_col_get_no(col);
  110. }
  111. ut_ad(dtuple_check_typed(entry));
  112. return(entry);
  113. }
  114. /***********************************************************************
  115. An inverse function to dict_row_build_index_entry. Builds a row from a
  116. record in a clustered index. */
  117. dtuple_t*
  118. row_build(
  119. /*======*/
  120. /* out, own: row built; see the NOTE below! */
  121. ulint type, /* in: ROW_COPY_DATA, or ROW_COPY_POINTERS:
  122. the former copies also the data fields to
  123. heap as the latter only places pointers to
  124. data fields on the index page, and thus is
  125. more efficient */
  126. dict_index_t* index, /* in: clustered index */
  127. rec_t* rec, /* in: record in the clustered index;
  128. NOTE: in the case ROW_COPY_POINTERS
  129. the data fields in the row will point
  130. directly into this record, therefore,
  131. the buffer page of this record must be
  132. at least s-latched and the latch held
  133. as long as the row dtuple is used! */
  134. mem_heap_t* heap) /* in: memory heap from which the memory
  135. needed is allocated */
  136. {
  137. dtuple_t* row;
  138. dict_table_t* table;
  139. ulint n_fields;
  140. ulint i;
  141. dfield_t* dfield;
  142. byte* field;
  143. ulint len;
  144. ulint row_len;
  145. dict_col_t* col;
  146. byte* buf; 
  147. ut_ad(index && rec && heap);
  148. ut_ad(index->type & DICT_CLUSTERED);
  149. if (type == ROW_COPY_DATA) {
  150. /* Take a copy of rec to heap */
  151. buf = mem_heap_alloc(heap, rec_get_size(rec));
  152. rec = rec_copy(buf, rec);
  153. }
  154. table = index->table;
  155. row_len = dict_table_get_n_cols(table);
  156. row = dtuple_create(heap, row_len);
  157. dtuple_set_info_bits(row, rec_get_info_bits(rec));
  158. n_fields = dict_index_get_n_fields(index);
  159. ut_ad(n_fields == rec_get_n_fields(rec));
  160. dict_table_copy_types(row, table);
  161. for (i = 0; i < n_fields; i++) {
  162. col = dict_field_get_col(dict_index_get_nth_field(index, i));
  163. dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
  164. field = rec_get_nth_field(rec, i, &len);
  165. dfield_set_data(dfield, field, len);
  166. }
  167. ut_ad(dtuple_check_typed(row));
  168. return(row);
  169. }
  170. /***********************************************************************
  171. An inverse function to dict_row_build_index_entry. Builds a row from a
  172. record in a clustered index. */
  173. void
  174. row_build_to_tuple(
  175. /*===============*/
  176. dtuple_t* row, /* in/out: row built; see the NOTE below! */
  177. dict_index_t* index, /* in: clustered index */
  178. rec_t* rec) /* in: record in the clustered index;
  179. NOTE: the data fields in the row will point
  180. directly into this record, therefore,
  181. the buffer page of this record must be
  182. at least s-latched and the latch held
  183. as long as the row dtuple is used! */
  184. {
  185. dict_table_t* table;
  186. ulint n_fields;
  187. ulint i;
  188. dfield_t* dfield;
  189. byte* field;
  190. ulint len;
  191. ulint row_len;
  192. dict_col_t* col;
  193. ut_ad(index && rec);
  194. ut_ad(index->type & DICT_CLUSTERED);
  195. table = index->table;
  196. row_len = dict_table_get_n_cols(table);
  197. dtuple_set_info_bits(row, rec_get_info_bits(rec));
  198. n_fields = dict_index_get_n_fields(index);
  199. ut_ad(n_fields == rec_get_n_fields(rec));
  200. dict_table_copy_types(row, table);
  201. for (i = 0; i < n_fields; i++) {
  202. col = dict_field_get_col(dict_index_get_nth_field(index, i));
  203. dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
  204. field = rec_get_nth_field(rec, i, &len);
  205. dfield_set_data(dfield, field, len);
  206. }
  207. ut_ad(dtuple_check_typed(row));
  208. }
  209. /***********************************************************************
  210. Converts an index record to a typed data tuple. */
  211. dtuple_t*
  212. row_rec_to_index_entry(
  213. /*===================*/
  214. /* out, own: index entry built; see the
  215. NOTE below! */
  216. ulint type, /* in: ROW_COPY_DATA, or ROW_COPY_POINTERS:
  217. the former copies also the data fields to
  218. heap as the latter only places pointers to
  219. data fields on the index page */
  220. dict_index_t* index, /* in: index */
  221. rec_t* rec, /* in: record in the index;
  222. NOTE: in the case ROW_COPY_POINTERS
  223. the data fields in the row will point
  224. directly into this record, therefore,
  225. the buffer page of this record must be
  226. at least s-latched and the latch held
  227. as long as the dtuple is used! */
  228. mem_heap_t* heap) /* in: memory heap from which the memory
  229. needed is allocated */
  230. {
  231. dtuple_t* entry;
  232. dfield_t* dfield;
  233. ulint i;
  234. byte* field;
  235. ulint len;
  236. ulint rec_len;
  237. byte* buf;
  238. ut_ad(rec && heap && index);
  239. if (type == ROW_COPY_DATA) {
  240. /* Take a copy of rec to heap */
  241. buf = mem_heap_alloc(heap, rec_get_size(rec));
  242. rec = rec_copy(buf, rec);
  243. }
  244. rec_len = rec_get_n_fields(rec);
  245. entry = dtuple_create(heap, rec_len);
  246. dtuple_set_n_fields_cmp(entry,
  247. dict_index_get_n_unique_in_tree(index));
  248. ut_ad(rec_len == dict_index_get_n_fields(index));
  249. dict_index_copy_types(entry, index, rec_len);
  250. dtuple_set_info_bits(entry, rec_get_info_bits(rec));
  251. for (i = 0; i < rec_len; i++) {
  252. dfield = dtuple_get_nth_field(entry, i);
  253. field = rec_get_nth_field(rec, i, &len);
  254. dfield_set_data(dfield, field, len);
  255. }
  256. ut_ad(dtuple_check_typed(entry));
  257. return(entry);
  258. }
  259. /***********************************************************************
  260. Builds from a secondary index record a row reference with which we can
  261. search the clustered index record. */
  262. dtuple_t*
  263. row_build_row_ref(
  264. /*==============*/
  265. /* out, own: row reference built; see the
  266. NOTE below! */
  267. ulint type, /* in: ROW_COPY_DATA, or ROW_COPY_POINTERS:
  268. the former copies also the data fields to
  269. heap, whereas the latter only places pointers
  270. to data fields on the index page */
  271. dict_index_t* index, /* in: index */
  272. rec_t* rec, /* in: record in the index;
  273. NOTE: in the case ROW_COPY_POINTERS
  274. the data fields in the row will point
  275. directly into this record, therefore,
  276. the buffer page of this record must be
  277. at least s-latched and the latch held
  278. as long as the row reference is used! */
  279. mem_heap_t* heap) /* in: memory heap from which the memory
  280. needed is allocated */
  281. {
  282. dict_table_t* table;
  283. dict_index_t* clust_index;
  284. dfield_t* dfield;
  285. dict_col_t* col;
  286. dtuple_t* ref;
  287. byte* field;
  288. ulint len;
  289. ulint ref_len;
  290. ulint pos;
  291. byte* buf;
  292. ulint i;
  293. ut_ad(index && rec && heap);
  294. if (type == ROW_COPY_DATA) {
  295. /* Take a copy of rec to heap */
  296. buf = mem_heap_alloc(heap, rec_get_size(rec));
  297. rec = rec_copy(buf, rec);
  298. }
  299. table = index->table;
  300. clust_index = dict_table_get_first_index(table);
  301. ref_len = dict_index_get_n_unique(clust_index);
  302. ref = dtuple_create(heap, ref_len);
  303. dict_index_copy_types(ref, clust_index, ref_len);
  304. for (i = 0; i < ref_len; i++) {
  305. dfield = dtuple_get_nth_field(ref, i);
  306. col = dict_field_get_col(
  307. dict_index_get_nth_field(clust_index, i));
  308. pos = dict_index_get_nth_col_pos(index, dict_col_get_no(col));
  309. if (pos != ULINT_UNDEFINED) {
  310. field = rec_get_nth_field(rec, pos, &len);
  311. dfield_set_data(dfield, field, len);
  312. } else {
  313. ut_ad(table->type == DICT_TABLE_CLUSTER_MEMBER);
  314. ut_ad(i == table->mix_len);
  315. dfield_set_data(dfield,
  316.  mem_heap_alloc(heap, table->mix_id_len),
  317. table->mix_id_len);
  318. ut_memcpy(dfield_get_data(dfield), table->mix_id_buf,
  319. table->mix_id_len);
  320. }
  321. }
  322. ut_ad(dtuple_check_typed(ref));
  323. return(ref);
  324. }
  325. /***********************************************************************
  326. Builds from a secondary index record a row reference with which we can
  327. search the clustered index record. */
  328. void
  329. row_build_row_ref_in_tuple(
  330. /*=======================*/
  331. dtuple_t* ref, /* in/out: row reference built; see the
  332. NOTE below! */
  333. dict_index_t* index, /* in: index */
  334. rec_t* rec) /* in: record in the index;
  335. NOTE: the data fields in ref will point
  336. directly into this record, therefore,
  337. the buffer page of this record must be
  338. at least s-latched and the latch held
  339. as long as the row reference is used! */
  340. {
  341. dict_table_t* table;
  342. dict_index_t* clust_index;
  343. dfield_t* dfield;
  344. dict_col_t* col;
  345. byte* field;
  346. ulint len;
  347. ulint ref_len;
  348. ulint pos;
  349. ulint i;
  350. ut_ad(ref && index && rec);
  351. table = index->table;
  352. clust_index = dict_table_get_first_index(table);
  353. ref_len = dict_index_get_n_unique(clust_index);
  354. ut_ad(ref_len == dtuple_get_n_fields(ref));
  355. dict_index_copy_types(ref, clust_index, ref_len);
  356. for (i = 0; i < ref_len; i++) {
  357. dfield = dtuple_get_nth_field(ref, i);
  358. col = dict_field_get_col(
  359. dict_index_get_nth_field(clust_index, i));
  360. pos = dict_index_get_nth_col_pos(index, dict_col_get_no(col));
  361. if (pos != ULINT_UNDEFINED) {
  362. field = rec_get_nth_field(rec, pos, &len);
  363. dfield_set_data(dfield, field, len);
  364. } else {
  365. ut_ad(table->type == DICT_TABLE_CLUSTER_MEMBER);
  366. ut_ad(i == table->mix_len);
  367. ut_a(0);
  368. }
  369. }
  370. ut_ad(dtuple_check_typed(ref));
  371. }
  372. /***********************************************************************
  373. From a row build a row reference with which we can search the clustered
  374. index record. */
  375. void
  376. row_build_row_ref_from_row(
  377. /*=======================*/
  378. dtuple_t* ref, /* in/out: row reference built; see the
  379. NOTE below! ref must have the right number
  380. of fields! */
  381. dict_table_t* table, /* in: table */
  382. dtuple_t* row) /* in: row
  383. NOTE: the data fields in ref will point
  384. directly into data of this row */
  385. {
  386. dict_index_t* clust_index;
  387. dfield_t* dfield;
  388. dfield_t* dfield2;
  389. dict_col_t* col;
  390. ulint ref_len;
  391. ulint i;
  392. ut_ad(ref && table && row);
  393. clust_index = dict_table_get_first_index(table);
  394. ref_len = dict_index_get_n_unique(clust_index);
  395. ut_ad(ref_len == dtuple_get_n_fields(ref));
  396. for (i = 0; i < ref_len; i++) {
  397. dfield = dtuple_get_nth_field(ref, i);
  398. col = dict_field_get_col(
  399. dict_index_get_nth_field(clust_index, i));
  400. dfield2 = dtuple_get_nth_field(row, dict_col_get_no(col));
  401. dfield_copy(dfield, dfield2);
  402. }
  403. ut_ad(dtuple_check_typed(ref));
  404. }
  405. /*******************************************************************
  406. Searches the clustered index record for a row, if we have the row reference. */
  407. ibool
  408. row_search_on_row_ref(
  409. /*==================*/
  410. /* out: TRUE if found */
  411. btr_pcur_t* pcur, /* in/out: persistent cursor, which must
  412. be closed by the caller */
  413. ulint mode, /* in: BTR_MODIFY_LEAF, ... */
  414. dict_table_t* table, /* in: table */
  415. dtuple_t* ref, /* in: row reference */
  416. mtr_t* mtr) /* in: mtr */
  417. {
  418. ulint low_match;
  419. rec_t* rec;
  420. dict_index_t* index;
  421. page_t* page;
  422. ut_ad(dtuple_check_typed(ref));
  423. index = dict_table_get_first_index(table);
  424. btr_pcur_open(index, ref, PAGE_CUR_LE, mode, pcur, mtr);
  425. low_match = btr_pcur_get_low_match(pcur);
  426. rec = btr_pcur_get_rec(pcur);
  427. page = buf_frame_align(rec);
  428. if (rec == page_get_infimum_rec(page)) {
  429. return(FALSE);
  430. }
  431. if (low_match != dtuple_get_n_fields(ref)) {
  432. return(FALSE);
  433. }
  434. return(TRUE);
  435. }
  436. /*************************************************************************
  437. Fetches the clustered index record for a secondary index record. The latches
  438. on the secondary index record are preserved. */
  439. rec_t*
  440. row_get_clust_rec(
  441. /*==============*/
  442. /* out: record or NULL, if no record found */
  443. ulint mode, /* in: BTR_MODIFY_LEAF, ... */
  444. rec_t* rec, /* in: record in a secondary index */
  445. dict_index_t* index, /* in: secondary index */
  446. dict_index_t** clust_index,/* out: clustered index */
  447. mtr_t* mtr) /* in: mtr */
  448. {
  449. mem_heap_t* heap;
  450. dtuple_t* ref;
  451. dict_table_t* table;
  452. btr_pcur_t pcur;
  453. ibool found;
  454. rec_t* clust_rec;
  455. ut_ad((index->type & DICT_CLUSTERED) == 0);
  456. table = index->table;
  457. heap = mem_heap_create(256);
  458. ref = row_build_row_ref(ROW_COPY_POINTERS, index, rec, heap);
  459. found = row_search_on_row_ref(&pcur, mode, table, ref, mtr);
  460. clust_rec = btr_pcur_get_rec(&pcur);
  461. mem_heap_free(heap);
  462. btr_pcur_close(&pcur);
  463. *clust_index = dict_table_get_first_index(table);
  464. if (!found) {
  465. return(NULL);
  466. }
  467. return(clust_rec);
  468. }
  469. /*******************************************************************
  470. Searches an index record. */
  471. ibool
  472. row_search_index_entry(
  473. /*===================*/
  474. /* out: TRUE if found */
  475. dict_index_t* index, /* in: index */
  476. dtuple_t* entry, /* in: index entry */
  477. ulint mode, /* in: BTR_MODIFY_LEAF, ... */
  478. btr_pcur_t* pcur, /* in/out: persistent cursor, which must
  479. be closed by the caller */
  480. mtr_t* mtr) /* in: mtr */
  481. {
  482. ulint n_fields;
  483. ulint low_match;
  484. page_t* page;
  485. rec_t* rec;
  486. ut_ad(dtuple_check_typed(entry));
  487. btr_pcur_open(index, entry, PAGE_CUR_LE, mode, pcur, mtr);
  488. low_match = btr_pcur_get_low_match(pcur);
  489. rec = btr_pcur_get_rec(pcur);
  490. page = buf_frame_align(rec);
  491. n_fields = dtuple_get_n_fields(entry);
  492. if (rec == page_get_infimum_rec(page)) {
  493. return(FALSE);
  494. }
  495. if (low_match != n_fields) {
  496. /* Not found */
  497. return(FALSE);
  498. }
  499. return(TRUE);
  500. }