You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

610 lines
14 KiB

20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
branches/zip: Implement the reporting of duplicate key values to MySQL. innobase_rec_to_mysql(): New function, for converting an InnoDB clustered index record to MySQL table->record[0]. TODO: convert integer fields. Currently, integer fields are in big-endian byte order instead of host byte order, and signed integer fields are offset by 0x80000000. innobase_rec_reset(): New function, for resetting table->record[0]. row_merge_build_indexes(): Add the parameter TABLE* table (the MySQL table handle) for reporting duplicate key values. dtuple_from_fields(): New function, to convert an array of dfield_t* to dtuple_t. dtuple_get_n_ext(): New function, to compute the number of externally stored fields. row_merge_dup_t: Structure for counting and reporting duplicate records. row_merge_dup_report(): Function for counting and reporting duplicate records. row_merge_tuple_cmp(), row_merge_tuple_sort(): Replace the ulint* n_dup parameter with row_merge_dup_t* dup. row_merge_buf_sort(): Add the parameter row_merge_dup_t* dup, which is NULL when sorting a non-unique index. row_merge_buf_write(), row_merge_heap_create(), row_merge_read_rec(), row_merge_cmp(), row_merge_read_clustered_index(), row_merge_blocks(), row_merge(), row_merge_sort(): Add const qualifiers. row_merge_read_clustered_index(): Use a common error handling branch err_exit. Invoke row_merge_buf_sort() differently on unique indexes. row_merge_blocks(): note TODO: We could invoke innobase_rec_to_mysql() to report duplicate key values when creating a clustered index.
18 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
branches/zip: Implement the reporting of duplicate key values to MySQL. innobase_rec_to_mysql(): New function, for converting an InnoDB clustered index record to MySQL table->record[0]. TODO: convert integer fields. Currently, integer fields are in big-endian byte order instead of host byte order, and signed integer fields are offset by 0x80000000. innobase_rec_reset(): New function, for resetting table->record[0]. row_merge_build_indexes(): Add the parameter TABLE* table (the MySQL table handle) for reporting duplicate key values. dtuple_from_fields(): New function, to convert an array of dfield_t* to dtuple_t. dtuple_get_n_ext(): New function, to compute the number of externally stored fields. row_merge_dup_t: Structure for counting and reporting duplicate records. row_merge_dup_report(): Function for counting and reporting duplicate records. row_merge_tuple_cmp(), row_merge_tuple_sort(): Replace the ulint* n_dup parameter with row_merge_dup_t* dup. row_merge_buf_sort(): Add the parameter row_merge_dup_t* dup, which is NULL when sorting a non-unique index. row_merge_buf_write(), row_merge_heap_create(), row_merge_read_rec(), row_merge_cmp(), row_merge_read_clustered_index(), row_merge_blocks(), row_merge(), row_merge_sort(): Add const qualifiers. row_merge_read_clustered_index(): Use a common error handling branch err_exit. Invoke row_merge_buf_sort() differently on unique indexes. row_merge_blocks(): note TODO: We could invoke innobase_rec_to_mysql() to report duplicate key values when creating a clustered index.
18 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
20 years ago
  1. /*****************************************************************************
  2. Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
  3. This program is free software; you can redistribute it and/or modify it under
  4. the terms of the GNU General Public License as published by the Free Software
  5. Foundation; version 2 of the License.
  6. This program is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along with
  10. this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  11. Place, Suite 330, Boston, MA 02111-1307 USA
  12. *****************************************************************************/
  13. /************************************************************************
  14. SQL data field and tuple
  15. Created 5/30/1994 Heikki Tuuri
  16. *************************************************************************/
  17. #include "mem0mem.h"
  18. #include "ut0rnd.h"
  19. #ifdef UNIV_DEBUG
  20. extern byte data_error;
  21. /*************************************************************************
  22. Gets pointer to the type struct of SQL data field. */
  23. UNIV_INLINE
  24. dtype_t*
  25. dfield_get_type(
  26. /*============*/
  27. /* out: pointer to the type struct */
  28. const dfield_t* field) /* in: SQL data field */
  29. {
  30. ut_ad(field);
  31. return((dtype_t*) &(field->type));
  32. }
  33. #endif /* UNIV_DEBUG */
  34. /*************************************************************************
  35. Sets the type struct of SQL data field. */
  36. UNIV_INLINE
  37. void
  38. dfield_set_type(
  39. /*============*/
  40. dfield_t* field, /* in: SQL data field */
  41. dtype_t* type) /* in: pointer to data type struct */
  42. {
  43. ut_ad(field && type);
  44. field->type = *type;
  45. }
  46. #ifdef UNIV_DEBUG
  47. /*************************************************************************
  48. Gets pointer to the data in a field. */
  49. UNIV_INLINE
  50. void*
  51. dfield_get_data(
  52. /*============*/
  53. /* out: pointer to data */
  54. const dfield_t* field) /* in: field */
  55. {
  56. ut_ad(field);
  57. ut_ad((field->len == UNIV_SQL_NULL)
  58. || (field->data != &data_error));
  59. return((void*) field->data);
  60. }
  61. #endif /* UNIV_DEBUG */
  62. /*************************************************************************
  63. Gets length of field data. */
  64. UNIV_INLINE
  65. ulint
  66. dfield_get_len(
  67. /*===========*/
  68. /* out: length of data; UNIV_SQL_NULL if
  69. SQL null data */
  70. const dfield_t* field) /* in: field */
  71. {
  72. ut_ad(field);
  73. ut_ad((field->len == UNIV_SQL_NULL)
  74. || (field->data != &data_error));
  75. return(field->len);
  76. }
  77. /*************************************************************************
  78. Sets length in a field. */
  79. UNIV_INLINE
  80. void
  81. dfield_set_len(
  82. /*===========*/
  83. dfield_t* field, /* in: field */
  84. ulint len) /* in: length or UNIV_SQL_NULL */
  85. {
  86. ut_ad(field);
  87. #ifdef UNIV_VALGRIND_DEBUG
  88. if (len != UNIV_SQL_NULL) UNIV_MEM_ASSERT_RW(field->data, len);
  89. #endif /* UNIV_VALGRIND_DEBUG */
  90. field->ext = 0;
  91. field->len = len;
  92. }
  93. /*************************************************************************
  94. Determines if a field is SQL NULL */
  95. UNIV_INLINE
  96. ulint
  97. dfield_is_null(
  98. /*===========*/
  99. /* out: nonzero if SQL null data */
  100. const dfield_t* field) /* in: field */
  101. {
  102. ut_ad(field);
  103. return(field->len == UNIV_SQL_NULL);
  104. }
  105. /*************************************************************************
  106. Determines if a field is externally stored */
  107. UNIV_INLINE
  108. ulint
  109. dfield_is_ext(
  110. /*==========*/
  111. /* out: nonzero if externally stored */
  112. const dfield_t* field) /* in: field */
  113. {
  114. ut_ad(field);
  115. return(UNIV_UNLIKELY(field->ext));
  116. }
  117. /*************************************************************************
  118. Sets the "external storage" flag */
  119. UNIV_INLINE
  120. void
  121. dfield_set_ext(
  122. /*===========*/
  123. dfield_t* field) /* in/out: field */
  124. {
  125. ut_ad(field);
  126. field->ext = 1;
  127. }
  128. /*************************************************************************
  129. Sets pointer to the data and length in a field. */
  130. UNIV_INLINE
  131. void
  132. dfield_set_data(
  133. /*============*/
  134. dfield_t* field, /* in: field */
  135. const void* data, /* in: data */
  136. ulint len) /* in: length or UNIV_SQL_NULL */
  137. {
  138. ut_ad(field);
  139. #ifdef UNIV_VALGRIND_DEBUG
  140. if (len != UNIV_SQL_NULL) UNIV_MEM_ASSERT_RW(data, len);
  141. #endif /* UNIV_VALGRIND_DEBUG */
  142. field->data = (void*) data;
  143. field->ext = 0;
  144. field->len = len;
  145. }
  146. /*************************************************************************
  147. Sets a data field to SQL NULL. */
  148. UNIV_INLINE
  149. void
  150. dfield_set_null(
  151. /*============*/
  152. dfield_t* field) /* in/out: field */
  153. {
  154. dfield_set_data(field, NULL, UNIV_SQL_NULL);
  155. }
  156. /*************************************************************************
  157. Copies the data and len fields. */
  158. UNIV_INLINE
  159. void
  160. dfield_copy_data(
  161. /*=============*/
  162. dfield_t* field1, /* out: field to copy to */
  163. const dfield_t* field2) /* in: field to copy from */
  164. {
  165. ut_ad(field1 && field2);
  166. field1->data = field2->data;
  167. field1->len = field2->len;
  168. field1->ext = field2->ext;
  169. }
  170. /*************************************************************************
  171. Copies a data field to another. */
  172. UNIV_INLINE
  173. void
  174. dfield_copy(
  175. /*========*/
  176. dfield_t* field1, /* out: field to copy to */
  177. const dfield_t* field2) /* in: field to copy from */
  178. {
  179. *field1 = *field2;
  180. }
  181. /*************************************************************************
  182. Copies the data pointed to by a data field. */
  183. UNIV_INLINE
  184. void
  185. dfield_dup(
  186. /*=======*/
  187. dfield_t* field, /* in/out: data field */
  188. mem_heap_t* heap) /* in: memory heap where allocated */
  189. {
  190. if (!dfield_is_null(field)) {
  191. UNIV_MEM_ASSERT_RW(field->data, field->len);
  192. field->data = mem_heap_dup(heap, field->data, field->len);
  193. }
  194. }
  195. /*************************************************************************
  196. Tests if data length and content is equal for two dfields. */
  197. UNIV_INLINE
  198. ibool
  199. dfield_datas_are_binary_equal(
  200. /*==========================*/
  201. /* out: TRUE if equal */
  202. const dfield_t* field1, /* in: field */
  203. const dfield_t* field2) /* in: field */
  204. {
  205. ulint len;
  206. len = field1->len;
  207. return(len == field2->len
  208. && (len == UNIV_SQL_NULL
  209. || !memcmp(field1->data, field2->data, len)));
  210. }
  211. /*************************************************************************
  212. Gets info bits in a data tuple. */
  213. UNIV_INLINE
  214. ulint
  215. dtuple_get_info_bits(
  216. /*=================*/
  217. /* out: info bits */
  218. const dtuple_t* tuple) /* in: tuple */
  219. {
  220. ut_ad(tuple);
  221. return(tuple->info_bits);
  222. }
  223. /*************************************************************************
  224. Sets info bits in a data tuple. */
  225. UNIV_INLINE
  226. void
  227. dtuple_set_info_bits(
  228. /*=================*/
  229. dtuple_t* tuple, /* in: tuple */
  230. ulint info_bits) /* in: info bits */
  231. {
  232. ut_ad(tuple);
  233. tuple->info_bits = info_bits;
  234. }
  235. /*************************************************************************
  236. Gets number of fields used in record comparisons. */
  237. UNIV_INLINE
  238. ulint
  239. dtuple_get_n_fields_cmp(
  240. /*====================*/
  241. /* out: number of fields used in comparisons
  242. in rem0cmp.* */
  243. const dtuple_t* tuple) /* in: tuple */
  244. {
  245. ut_ad(tuple);
  246. return(tuple->n_fields_cmp);
  247. }
  248. /*************************************************************************
  249. Sets number of fields used in record comparisons. */
  250. UNIV_INLINE
  251. void
  252. dtuple_set_n_fields_cmp(
  253. /*====================*/
  254. dtuple_t* tuple, /* in: tuple */
  255. ulint n_fields_cmp) /* in: number of fields used in
  256. comparisons in rem0cmp.* */
  257. {
  258. ut_ad(tuple);
  259. ut_ad(n_fields_cmp <= tuple->n_fields);
  260. tuple->n_fields_cmp = n_fields_cmp;
  261. }
  262. /*************************************************************************
  263. Gets number of fields in a data tuple. */
  264. UNIV_INLINE
  265. ulint
  266. dtuple_get_n_fields(
  267. /*================*/
  268. /* out: number of fields */
  269. const dtuple_t* tuple) /* in: tuple */
  270. {
  271. ut_ad(tuple);
  272. return(tuple->n_fields);
  273. }
  274. #ifdef UNIV_DEBUG
  275. /*************************************************************************
  276. Gets nth field of a tuple. */
  277. UNIV_INLINE
  278. dfield_t*
  279. dtuple_get_nth_field(
  280. /*=================*/
  281. /* out: nth field */
  282. const dtuple_t* tuple, /* in: tuple */
  283. ulint n) /* in: index of field */
  284. {
  285. ut_ad(tuple);
  286. ut_ad(n < tuple->n_fields);
  287. return((dfield_t*) tuple->fields + n);
  288. }
  289. #endif /* UNIV_DEBUG */
  290. /**************************************************************
  291. Creates a data tuple to a memory heap. The default value for number
  292. of fields used in record comparisons for this tuple is n_fields. */
  293. UNIV_INLINE
  294. dtuple_t*
  295. dtuple_create(
  296. /*==========*/
  297. /* out, own: created tuple */
  298. mem_heap_t* heap, /* in: memory heap where the tuple
  299. is created */
  300. ulint n_fields) /* in: number of fields */
  301. {
  302. dtuple_t* tuple;
  303. ut_ad(heap);
  304. tuple = (dtuple_t*) mem_heap_alloc(heap, sizeof(dtuple_t)
  305. + n_fields * sizeof(dfield_t));
  306. tuple->info_bits = 0;
  307. tuple->n_fields = n_fields;
  308. tuple->n_fields_cmp = n_fields;
  309. tuple->fields = (dfield_t*) &tuple[1];
  310. #ifdef UNIV_DEBUG
  311. tuple->magic_n = DATA_TUPLE_MAGIC_N;
  312. { /* In the debug version, initialize fields to an error value */
  313. ulint i;
  314. for (i = 0; i < n_fields; i++) {
  315. dfield_t* field;
  316. field = dtuple_get_nth_field(tuple, i);
  317. dfield_set_len(field, UNIV_SQL_NULL);
  318. field->data = &data_error;
  319. dfield_get_type(field)->mtype = DATA_ERROR;
  320. }
  321. }
  322. UNIV_MEM_INVALID(tuple->fields, n_fields * sizeof *tuple->fields);
  323. #endif
  324. return(tuple);
  325. }
  326. /**************************************************************
  327. Wrap data fields in a tuple. The default value for number
  328. of fields used in record comparisons for this tuple is n_fields. */
  329. UNIV_INLINE
  330. const dtuple_t*
  331. dtuple_from_fields(
  332. /*===============*/
  333. /* out: data tuple */
  334. dtuple_t* tuple, /* in: storage for data tuple */
  335. const dfield_t* fields, /* in: fields */
  336. ulint n_fields) /* in: number of fields */
  337. {
  338. tuple->info_bits = 0;
  339. tuple->n_fields = tuple->n_fields_cmp = n_fields;
  340. tuple->fields = (dfield_t*) fields;
  341. ut_d(tuple->magic_n = DATA_TUPLE_MAGIC_N);
  342. return(tuple);
  343. }
  344. /*************************************************************************
  345. Copies a data tuple to another. This is a shallow copy; if a deep copy
  346. is desired, dfield_dup() will have to be invoked on each field. */
  347. UNIV_INLINE
  348. dtuple_t*
  349. dtuple_copy(
  350. /*========*/
  351. /* out, own: copy of tuple */
  352. const dtuple_t* tuple, /* in: tuple to copy from */
  353. mem_heap_t* heap) /* in: memory heap
  354. where the tuple is created */
  355. {
  356. ulint n_fields = dtuple_get_n_fields(tuple);
  357. dtuple_t* new_tuple = dtuple_create(heap, n_fields);
  358. ulint i;
  359. for (i = 0; i < n_fields; i++) {
  360. dfield_copy(dtuple_get_nth_field(new_tuple, i),
  361. dtuple_get_nth_field(tuple, i));
  362. }
  363. return(new_tuple);
  364. }
  365. /**************************************************************
  366. The following function returns the sum of data lengths of a tuple. The space
  367. occupied by the field structs or the tuple struct is not counted. Neither
  368. is possible space in externally stored parts of the field. */
  369. UNIV_INLINE
  370. ulint
  371. dtuple_get_data_size(
  372. /*=================*/
  373. /* out: sum of data lengths */
  374. const dtuple_t* tuple, /* in: typed data tuple */
  375. ulint comp) /* in: nonzero=ROW_FORMAT=COMPACT */
  376. {
  377. const dfield_t* field;
  378. ulint n_fields;
  379. ulint len;
  380. ulint i;
  381. ulint sum = 0;
  382. ut_ad(tuple);
  383. ut_ad(dtuple_check_typed(tuple));
  384. ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
  385. n_fields = tuple->n_fields;
  386. for (i = 0; i < n_fields; i++) {
  387. field = dtuple_get_nth_field(tuple, i);
  388. len = dfield_get_len(field);
  389. if (len == UNIV_SQL_NULL) {
  390. len = dtype_get_sql_null_size(dfield_get_type(field),
  391. comp);
  392. }
  393. sum += len;
  394. }
  395. return(sum);
  396. }
  397. /*************************************************************************
  398. Computes the number of externally stored fields in a data tuple. */
  399. UNIV_INLINE
  400. ulint
  401. dtuple_get_n_ext(
  402. /*=============*/
  403. /* out: number of externally stored fields */
  404. const dtuple_t* tuple) /* in: tuple */
  405. {
  406. ulint n_ext = 0;
  407. ulint n_fields = tuple->n_fields;
  408. ulint i;
  409. ut_ad(tuple);
  410. ut_ad(dtuple_check_typed(tuple));
  411. ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
  412. for (i = 0; i < n_fields; i++) {
  413. n_ext += dtuple_get_nth_field(tuple, i)->ext;
  414. }
  415. return(n_ext);
  416. }
  417. /***********************************************************************
  418. Sets types of fields binary in a tuple. */
  419. UNIV_INLINE
  420. void
  421. dtuple_set_types_binary(
  422. /*====================*/
  423. dtuple_t* tuple, /* in: data tuple */
  424. ulint n) /* in: number of fields to set */
  425. {
  426. dtype_t* dfield_type;
  427. ulint i;
  428. for (i = 0; i < n; i++) {
  429. dfield_type = dfield_get_type(dtuple_get_nth_field(tuple, i));
  430. dtype_set(dfield_type, DATA_BINARY, 0, 0);
  431. }
  432. }
  433. /****************************************************************
  434. Folds a prefix given as the number of fields of a tuple. */
  435. UNIV_INLINE
  436. ulint
  437. dtuple_fold(
  438. /*========*/
  439. /* out: the folded value */
  440. const dtuple_t* tuple, /* in: the tuple */
  441. ulint n_fields,/* in: number of complete fields to fold */
  442. ulint n_bytes,/* in: number of bytes to fold in an
  443. incomplete last field */
  444. dulint tree_id)/* in: index tree id */
  445. {
  446. const dfield_t* field;
  447. ulint i;
  448. const byte* data;
  449. ulint len;
  450. ulint fold;
  451. ut_ad(tuple);
  452. ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
  453. ut_ad(dtuple_check_typed(tuple));
  454. fold = ut_fold_dulint(tree_id);
  455. for (i = 0; i < n_fields; i++) {
  456. field = dtuple_get_nth_field(tuple, i);
  457. data = (const byte*) dfield_get_data(field);
  458. len = dfield_get_len(field);
  459. if (len != UNIV_SQL_NULL) {
  460. fold = ut_fold_ulint_pair(fold,
  461. ut_fold_binary(data, len));
  462. }
  463. }
  464. if (n_bytes > 0) {
  465. field = dtuple_get_nth_field(tuple, i);
  466. data = (const byte*) dfield_get_data(field);
  467. len = dfield_get_len(field);
  468. if (len != UNIV_SQL_NULL) {
  469. if (len > n_bytes) {
  470. len = n_bytes;
  471. }
  472. fold = ut_fold_ulint_pair(fold,
  473. ut_fold_binary(data, len));
  474. }
  475. }
  476. return(fold);
  477. }
  478. /**************************************************************************
  479. Writes an SQL null field full of zeros. */
  480. UNIV_INLINE
  481. void
  482. data_write_sql_null(
  483. /*================*/
  484. byte* data, /* in: pointer to a buffer of size len */
  485. ulint len) /* in: SQL null size in bytes */
  486. {
  487. memset(data, 0, len);
  488. }
  489. /**************************************************************************
  490. Checks if a dtuple contains an SQL null value. */
  491. UNIV_INLINE
  492. ibool
  493. dtuple_contains_null(
  494. /*=================*/
  495. /* out: TRUE if some field is SQL null */
  496. const dtuple_t* tuple) /* in: dtuple */
  497. {
  498. ulint n;
  499. ulint i;
  500. n = dtuple_get_n_fields(tuple);
  501. for (i = 0; i < n; i++) {
  502. if (dfield_is_null(dtuple_get_nth_field(tuple, i))) {
  503. return(TRUE);
  504. }
  505. }
  506. return(FALSE);
  507. }
  508. /******************************************************************
  509. Frees the memory in a big rec vector. */
  510. UNIV_INLINE
  511. void
  512. dtuple_big_rec_free(
  513. /*================*/
  514. big_rec_t* vector) /* in, own: big rec vector; it is
  515. freed in this function */
  516. {
  517. mem_heap_free(vector->heap);
  518. }