data0data.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:15k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /************************************************************************
  2. SQL data field and tuple
  3. (c) 1994-1996 Innobase Oy
  4. Created 5/30/1994 Heikki Tuuri
  5. *************************************************************************/
  6. #include "data0data.h"
  7. #ifdef UNIV_NONINL
  8. #include "data0data.ic"
  9. #endif
  10. #include "rem0rec.h"
  11. #include "rem0cmp.h"
  12. #include "page0page.h"
  13. #include "dict0dict.h"
  14. #include "btr0cur.h"
  15. byte data_error; /* data pointers of tuple fields are initialized
  16. to point here for error checking */
  17. #ifdef UNIV_DEBUG
  18. ulint data_dummy; /* this is used to fool the compiler in
  19. dtuple_validate */
  20. #endif /* UNIV_DEBUG */
  21. /* Some non-inlined functions used in the MySQL interface: */
  22. void 
  23. dfield_set_data_noninline(
  24. dfield_t*  field, /* in: field */
  25. void* data, /* in: data */
  26. ulint len) /* in: length or UNIV_SQL_NULL */
  27. {
  28. dfield_set_data(field, data, len);
  29. }
  30. void* 
  31. dfield_get_data_noninline(
  32. dfield_t* field) /* in: field */
  33. {
  34. return(dfield_get_data(field));
  35. }
  36. ulint
  37. dfield_get_len_noninline(
  38. dfield_t* field) /* in: field */
  39. {
  40. return(dfield_get_len(field));
  41. }
  42. ulint 
  43. dtuple_get_n_fields_noninline(
  44. dtuple_t*  tuple) /* in: tuple */
  45. {
  46. return(dtuple_get_n_fields(tuple));
  47. }
  48. dfield_t* 
  49. dtuple_get_nth_field_noninline(
  50. dtuple_t*  tuple, /* in: tuple */
  51. ulint n) /* in: index of field */
  52. {
  53. return(dtuple_get_nth_field(tuple, n));
  54. }
  55. /*************************************************************************
  56. Tests if dfield data length and content is equal to the given. */
  57. ibool
  58. dfield_data_is_binary_equal(
  59. /*========================*/
  60. /* out: TRUE if equal */
  61. dfield_t* field, /* in: field */
  62. ulint len, /* in: data length or UNIV_SQL_NULL */
  63. byte* data) /* in: data */
  64. {
  65. if (len != field->len) {
  66. return(FALSE);
  67. }
  68. if (len == UNIV_SQL_NULL) {
  69. return(TRUE);
  70. }
  71. if (0 != ut_memcmp(field->data, data, len)) {
  72.     
  73. return(FALSE);
  74. }
  75. return(TRUE);
  76. }
  77. /****************************************************************
  78. Returns TRUE if lengths of two dtuples are equal and respective data fields
  79. in them are equal when compared with collation in char fields (not as binary
  80. strings). */
  81. ibool
  82. dtuple_datas_are_ordering_equal(
  83. /*============================*/
  84. /* out: TRUE if length and fieds are equal
  85. when compared with cmp_data_data:
  86. NOTE: in character type fields some letters
  87. are identified with others! (collation) */
  88. dtuple_t* tuple1, /* in: tuple 1 */
  89. dtuple_t* tuple2) /* in: tuple 2 */
  90. {
  91. dfield_t* field1;
  92. dfield_t* field2;
  93. ulint n_fields;
  94. ulint i;
  95. ut_ad(tuple1 && tuple2);
  96. ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N);
  97. ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N);
  98. ut_ad(dtuple_check_typed(tuple1));
  99. ut_ad(dtuple_check_typed(tuple2));
  100. n_fields = dtuple_get_n_fields(tuple1);
  101. if (n_fields != dtuple_get_n_fields(tuple2)) {
  102. return(FALSE);
  103. }
  104. for (i = 0; i < n_fields; i++) {
  105. field1 = dtuple_get_nth_field(tuple1, i);
  106. field2 = dtuple_get_nth_field(tuple2, i);
  107. if (0 != cmp_dfield_dfield(field1, field2)) {
  108. return(FALSE);
  109. }
  110. }
  111. return(TRUE);
  112. }
  113. /*************************************************************************
  114. Creates a dtuple for use in MySQL. */
  115. dtuple_t*
  116. dtuple_create_for_mysql(
  117. /*====================*/
  118. /* out, own created dtuple */
  119. void**  heap,     /* out: created memory heap */
  120. ulint  n_fields)  /* in: number of fields */
  121. {
  122.    *heap = (void*)mem_heap_create(500);
  123.  
  124.    return(dtuple_create(*((mem_heap_t**)heap), n_fields));  
  125. }
  126. /*************************************************************************
  127. Frees a dtuple used in MySQL. */
  128. void
  129. dtuple_free_for_mysql(
  130. /*==================*/
  131. void* heap) /* in: memory heap where tuple was created */
  132. {
  133.    mem_heap_free((mem_heap_t*)heap);
  134. }
  135. /*************************************************************************
  136. Sets number of fields used in a tuple. Normally this is set in
  137. dtuple_create, but if you want later to set it smaller, you can use this. */ 
  138. void
  139. dtuple_set_n_fields(
  140. /*================*/
  141. dtuple_t* tuple, /* in: tuple */
  142. ulint n_fields) /* in: number of fields */
  143. {
  144. ut_ad(tuple);
  145. tuple->n_fields = n_fields;
  146. tuple->n_fields_cmp = n_fields;
  147. }
  148. /**************************************************************
  149. Checks that a data field is typed. */
  150. static
  151. ibool
  152. dfield_check_typed_no_assert(
  153. /*=========================*/
  154. /* out: TRUE if ok */
  155. dfield_t* field) /* in: data field */
  156. {
  157. if (dfield_get_type(field)->mtype > DATA_MYSQL
  158.     || dfield_get_type(field)->mtype < DATA_VARCHAR) {
  159. fprintf(stderr,
  160. "InnoDB: Error: data field type %lu, len %lun",
  161. (ulong) dfield_get_type(field)->mtype,
  162. (ulong) dfield_get_len(field));
  163. return(FALSE);
  164. }
  165. return(TRUE);
  166. }
  167. /**************************************************************
  168. Checks that a data tuple is typed. */
  169. ibool
  170. dtuple_check_typed_no_assert(
  171. /*=========================*/
  172. /* out: TRUE if ok */
  173. dtuple_t* tuple) /* in: tuple */
  174. {
  175. dfield_t* field;
  176. ulint   i;
  177. if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) {
  178. fprintf(stderr,
  179. "InnoDB: Error: index entry has %lu fieldsn",
  180. (ulong) dtuple_get_n_fields(tuple));
  181. dump:
  182. fputs("InnoDB: Tuple contents: ", stderr);
  183. dtuple_print(stderr, tuple);
  184. putc('n', stderr);
  185. return(FALSE);
  186. }
  187. for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
  188. field = dtuple_get_nth_field(tuple, i);
  189. if (!dfield_check_typed_no_assert(field)) {
  190. goto dump;
  191. }
  192. }
  193. return(TRUE);
  194. }
  195. /**************************************************************
  196. Checks that a data field is typed. Asserts an error if not. */
  197. ibool
  198. dfield_check_typed(
  199. /*===============*/
  200. /* out: TRUE if ok */
  201. dfield_t* field) /* in: data field */
  202. {
  203. if (dfield_get_type(field)->mtype > DATA_MYSQL
  204.     || dfield_get_type(field)->mtype < DATA_VARCHAR) {
  205. fprintf(stderr,
  206. "InnoDB: Error: data field type %lu, len %lun",
  207. (ulong) dfield_get_type(field)->mtype,
  208. (ulong) dfield_get_len(field));
  209. ut_error;
  210. }
  211. return(TRUE);
  212. }
  213. /**************************************************************
  214. Checks that a data tuple is typed. Asserts an error if not. */
  215. ibool
  216. dtuple_check_typed(
  217. /*===============*/
  218. /* out: TRUE if ok */
  219. dtuple_t* tuple) /* in: tuple */
  220. {
  221. dfield_t* field;
  222. ulint   i;
  223. for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
  224. field = dtuple_get_nth_field(tuple, i);
  225. ut_a(dfield_check_typed(field));
  226. }
  227. return(TRUE);
  228. }
  229. #ifdef UNIV_DEBUG
  230. /**************************************************************
  231. Validates the consistency of a tuple which must be complete, i.e,
  232. all fields must have been set. */
  233. ibool
  234. dtuple_validate(
  235. /*============*/
  236. /* out: TRUE if ok */
  237. dtuple_t* tuple) /* in: tuple */
  238. {
  239. dfield_t* field;
  240. byte*   data;
  241. ulint   n_fields;
  242. ulint   len;
  243. ulint   i;
  244. ulint   j;
  245. ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
  246. n_fields = dtuple_get_n_fields(tuple);
  247. /* We dereference all the data of each field to test
  248. for memory traps */
  249. for (i = 0; i < n_fields; i++) {
  250. field = dtuple_get_nth_field(tuple, i);
  251. len = dfield_get_len(field);
  252. if (len != UNIV_SQL_NULL) {
  253. data = field->data;
  254. for (j = 0; j < len; j++) {
  255. data_dummy  += *data; /* fool the compiler not
  256. to optimize out this
  257. code */
  258. data++;
  259. }
  260. }
  261. }
  262. ut_a(dtuple_check_typed(tuple));
  263. return(TRUE);
  264. }
  265. #endif /* UNIV_DEBUG */
  266. /*****************************************************************
  267. Pretty prints a dfield value according to its data type. */
  268. void
  269. dfield_print(
  270. /*=========*/
  271. dfield_t* dfield)  /* in: dfield */
  272. {
  273. byte* data;
  274. ulint len;
  275. ulint mtype;
  276. ulint i;
  277. len = dfield_get_len(dfield);
  278. data = dfield_get_data(dfield);
  279. if (len == UNIV_SQL_NULL) {
  280. fputs("NULL", stderr);
  281. return;
  282. }
  283. mtype = dtype_get_mtype(dfield_get_type(dfield));
  284. if ((mtype == DATA_CHAR) || (mtype == DATA_VARCHAR)) {
  285. for (i = 0; i < len; i++) {
  286. int c = *data++;
  287. putc(isprint(c) ? c : ' ', stderr);
  288. }
  289. } else if (mtype == DATA_INT) {
  290. ut_a(len == 4); /* only works for 32-bit integers */
  291. fprintf(stderr, "%d", (int)mach_read_from_4(data));
  292. } else {
  293. ut_error;
  294. }
  295. }
  296. /*****************************************************************
  297. Pretty prints a dfield value according to its data type. Also the hex string
  298. is printed if a string contains non-printable characters. */ 
  299. void
  300. dfield_print_also_hex(
  301. /*==================*/
  302. dfield_t* dfield)  /* in: dfield */
  303. {
  304. byte* data;
  305. ulint len;
  306. ulint mtype;
  307. ulint i;
  308. ibool print_also_hex;
  309. len = dfield_get_len(dfield);
  310. data = dfield_get_data(dfield);
  311. if (len == UNIV_SQL_NULL) {
  312. fputs("NULL", stderr);
  313. return;
  314. }
  315. mtype = dtype_get_mtype(dfield_get_type(dfield));
  316. if ((mtype == DATA_CHAR) || (mtype == DATA_VARCHAR)) {
  317. print_also_hex = FALSE;
  318. for (i = 0; i < len; i++) {
  319. int c = *data++;
  320. if (!isprint(c)) {
  321. print_also_hex = TRUE;
  322. c = ' ';
  323. }
  324. putc(c, stderr);
  325. }
  326. if (!print_also_hex) {
  327. return;
  328. }
  329. fputs(" Hex: ", stderr);
  330. data = dfield_get_data(dfield);
  331. for (i = 0; i < len; i++) {
  332. fprintf(stderr, "%02lx", (ulint)*data);
  333. data++;
  334. }
  335. } else if (mtype == DATA_INT) {
  336. ut_a(len == 4); /* only works for 32-bit integers */
  337. fprintf(stderr, "%d", (int)mach_read_from_4(data));
  338. } else {
  339. ut_error;
  340. }
  341. }
  342. /**************************************************************
  343. The following function prints the contents of a tuple. */
  344. void
  345. dtuple_print(
  346. /*=========*/
  347. FILE* f, /* in: output stream */
  348. dtuple_t* tuple) /* in: tuple */
  349. {
  350. dfield_t* field;
  351. ulint n_fields;
  352. ulint i;
  353. n_fields = dtuple_get_n_fields(tuple);
  354. fprintf(f, "DATA TUPLE: %lu fields;n", (ulong) n_fields);
  355. for (i = 0; i < n_fields; i++) {
  356. fprintf(f, " %lu:", (ulong) i);
  357. field = dtuple_get_nth_field(tuple, i);
  358. if (field->len != UNIV_SQL_NULL) {
  359. ut_print_buf(f, field->data, field->len);
  360. } else {
  361. fputs(" SQL NULL", f);
  362. }
  363. putc(';', f);
  364. }
  365. putc('n', f);
  366. ut_ad(dtuple_validate(tuple));
  367. }
  368. /******************************************************************
  369. Moves parts of long fields in entry to the big record vector so that
  370. the size of tuple drops below the maximum record size allowed in the
  371. database. Moves data only from those fields which are not necessary
  372. to determine uniquely the insertion place of the tuple in the index. */
  373. big_rec_t*
  374. dtuple_convert_big_rec(
  375. /*===================*/
  376. /* out, own: created big record vector,
  377. NULL if we are not able to shorten
  378. the entry enough, i.e., if there are
  379. too many short fields in entry */
  380. dict_index_t* index, /* in: index */
  381. dtuple_t* entry, /* in: index entry */
  382. ulint* ext_vec,/* in: array of externally stored fields,
  383. or NULL: if a field already is externally
  384. stored, then we cannot move it to the vector
  385. this function returns */
  386. ulint n_ext_vec)/* in: number of elements is ext_vec */
  387. {
  388. mem_heap_t* heap;
  389. big_rec_t* vector;
  390. dfield_t* dfield;
  391. ulint size;
  392. ulint n_fields;
  393. ulint longest;
  394. ulint longest_i = ULINT_MAX;
  395. ibool is_externally_stored;
  396. ulint i;
  397. ulint j;
  398. ut_a(dtuple_check_typed_no_assert(entry));
  399. size = rec_get_converted_size(entry);
  400. if (size > 1000000000) {
  401. fprintf(stderr,
  402. "InnoDB: Warning: tuple size very big: %lun", (ulong) size);
  403. fputs("InnoDB: Tuple contents: ", stderr);
  404. dtuple_print(stderr, entry);
  405. putc('n', stderr);
  406. }
  407. heap = mem_heap_create(size + dtuple_get_n_fields(entry)
  408. * sizeof(big_rec_field_t) + 1000);
  409. vector = mem_heap_alloc(heap, sizeof(big_rec_t));
  410. vector->heap = heap;
  411. vector->fields = mem_heap_alloc(heap, dtuple_get_n_fields(entry)
  412. * sizeof(big_rec_field_t));
  413. /* Decide which fields to shorten: the algorithm is to look for
  414. the longest field whose type is DATA_BLOB */
  415. n_fields = 0;
  416. while ((rec_get_converted_size(entry)
  417. >= page_get_free_space_of_empty() / 2)
  418.        || rec_get_converted_size(entry) >= REC_MAX_DATA_SIZE) {
  419. longest = 0;
  420. for (i = dict_index_get_n_unique_in_tree(index);
  421. i < dtuple_get_n_fields(entry); i++) {
  422. /* Skip over fields which already are externally
  423. stored */
  424. is_externally_stored = FALSE;
  425. if (ext_vec) {
  426. for (j = 0; j < n_ext_vec; j++) {
  427. if (ext_vec[j] == i) {
  428. is_externally_stored = TRUE;
  429. }
  430. }
  431. }
  432. if (!is_externally_stored
  433.     && dict_index_get_nth_type(index, i)->mtype
  434.        == DATA_BLOB) {
  435. dfield = dtuple_get_nth_field(entry, i);
  436. if (dfield->len != UNIV_SQL_NULL &&
  437.          dfield->len > longest) {
  438.          longest = dfield->len;
  439.          longest_i = i;
  440. }
  441. }
  442. }
  443. /* We do not store externally fields which are smaller than
  444. DICT_MAX_COL_PREFIX_LEN */
  445. ut_a(DICT_MAX_COL_PREFIX_LEN > REC_1BYTE_OFFS_LIMIT);
  446. if (longest < BTR_EXTERN_FIELD_REF_SIZE + 10
  447. + DICT_MAX_COL_PREFIX_LEN) {
  448. /* Cannot shorten more */
  449. mem_heap_free(heap);
  450. return(NULL);
  451. }
  452. /* Move data from field longest_i to big rec vector;
  453. we do not let data size of the remaining entry
  454. drop below 128 which is the limit for the 2-byte
  455. offset storage format in a physical record. This
  456. we accomplish by storing 128 bytes of data in entry
  457. itself, and only the remaining part to big rec vec.
  458. We store the first bytes locally to the record. Then
  459. we can calculate all ordering fields in all indexes
  460. from locally stored data. */
  461. dfield = dtuple_get_nth_field(entry, longest_i);
  462. vector->fields[n_fields].field_no = longest_i;
  463. ut_a(dfield->len > DICT_MAX_COL_PREFIX_LEN);
  464. vector->fields[n_fields].len = dfield->len
  465. - DICT_MAX_COL_PREFIX_LEN;
  466. vector->fields[n_fields].data = mem_heap_alloc(heap,
  467. vector->fields[n_fields].len);
  468. /* Copy data (from the end of field) to big rec vector */
  469. ut_memcpy(vector->fields[n_fields].data,
  470. ((byte*)dfield->data) + dfield->len
  471. - vector->fields[n_fields].len,
  472. vector->fields[n_fields].len);
  473. dfield->len = dfield->len - vector->fields[n_fields].len
  474. + BTR_EXTERN_FIELD_REF_SIZE;
  475. /* Set the extern field reference in dfield to zero */
  476. memset(((byte*)dfield->data)
  477. + dfield->len - BTR_EXTERN_FIELD_REF_SIZE,
  478. 0, BTR_EXTERN_FIELD_REF_SIZE);
  479. n_fields++;
  480. }
  481. vector->n_fields = n_fields;
  482. return(vector);
  483. }
  484. /******************************************************************
  485. Puts back to entry the data stored in vector. Note that to ensure the
  486. fields in entry can accommodate the data, vector must have been created
  487. from entry with dtuple_convert_big_rec. */
  488. void
  489. dtuple_convert_back_big_rec(
  490. /*========================*/
  491. dict_index_t* index __attribute__((unused)), /* in: index */
  492. dtuple_t* entry, /* in: entry whose data was put to vector */
  493. big_rec_t* vector) /* in, own: big rec vector; it is
  494. freed in this function */
  495. {
  496. dfield_t* dfield;
  497. ulint i;
  498. for (i = 0; i < vector->n_fields; i++) {
  499. dfield = dtuple_get_nth_field(entry,
  500. vector->fields[i].field_no);
  501. /* Copy data from big rec vector */
  502. ut_memcpy(((byte*)dfield->data)
  503. + dfield->len - BTR_EXTERN_FIELD_REF_SIZE,
  504.   vector->fields[i].data,
  505.           vector->fields[i].len);
  506. dfield->len = dfield->len + vector->fields[i].len
  507. - BTR_EXTERN_FIELD_REF_SIZE;
  508. }
  509. mem_heap_free(vector->heap);
  510. }
  511. /******************************************************************
  512. Frees the memory in a big rec vector. */
  513. void
  514. dtuple_big_rec_free(
  515. /*================*/
  516. big_rec_t* vector) /* in, own: big rec vector; it is
  517. freed in this function */
  518. {
  519. mem_heap_free(vector->heap);
  520. }