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

MySQL数据库

开发平台:

Visual C++

  1. /***********************************************************************
  2. Comparison services for records
  3. (c) 1994-1996 Innobase Oy
  4. Created 7/1/1994 Heikki Tuuri
  5. ************************************************************************/
  6. #include "rem0cmp.h"
  7. #ifdef UNIV_NONINL
  8. #include "rem0cmp.ic"
  9. #endif
  10. #include "srv0srv.h"
  11. /* ALPHABETICAL ORDER
  12. ==================
  13. The records are put into alphabetical order in the following
  14. way: let F be the first field where two records disagree.
  15. If there is a character in some position n where the the
  16. records disagree, the order is determined by comparison of
  17. the characters at position n, possibly after
  18. collating transformation. If there is no such character,
  19. but the corresponding fields have different lengths, then
  20. if the data type of the fields is paddable,
  21. shorter field is padded with a padding character. If the
  22. data type is not paddable, longer field is considered greater.
  23. Finally, the SQL null is bigger than any other value.
  24. At the present, the comparison functions return 0 in the case,
  25. where two records disagree only in the way that one 
  26. has more fields than the other. */
  27. #ifdef UNIV_DEBUG
  28. /*****************************************************************
  29. Used in debug checking of cmp_dtuple_... .
  30. This function is used to compare a data tuple to a physical record. If
  31. dtuple has n fields then rec must have either m >= n fields, or it must
  32. differ from dtuple in some of the m fields rec has. */
  33. static
  34. int
  35. cmp_debug_dtuple_rec_with_match(
  36. /*============================*/
  37. /* out: 1, 0, -1, if dtuple is greater, equal, 
  38. less than rec, respectively, when only the 
  39. common first fields are compared */
  40. dtuple_t* dtuple, /* in: data tuple */
  41. rec_t* rec, /* in: physical record which differs from
  42. dtuple in some of the common fields, or which
  43. has an equal number or more fields than
  44. dtuple */
  45. ulint*   matched_fields);/* in/out: number of already
  46. completely  matched fields; when function
  47. returns, contains the value for current
  48. comparison */
  49. #endif /* UNIV_DEBUG */
  50. /*****************************************************************
  51. This function is used to compare two data fields for which the data type
  52. is such that we must use MySQL code to compare them. The prototype here
  53. must be a copy of the the one in ha_innobase.cc! */
  54. extern
  55. int
  56. innobase_mysql_cmp(
  57. /*===============*/
  58. /* out: 1, 0, -1, if a is greater,
  59. equal, less than b, respectively */
  60. int mysql_type, /* in: MySQL type */
  61. uint charset_number, /* in: number of the charset */
  62. unsigned char* a, /* in: data field */
  63. unsigned int a_length, /* in: data field length,
  64. not UNIV_SQL_NULL */
  65. unsigned char* b, /* in: data field */
  66. unsigned int b_length); /* in: data field length,
  67. not UNIV_SQL_NULL */
  68. /*************************************************************************
  69. Transforms the character code so that it is ordered appropriately for the
  70. language. This is only used for the latin1 char set. MySQL does the
  71. comparisons for other char sets. */
  72. UNIV_INLINE
  73. ulint
  74. cmp_collate(
  75. /*========*/
  76. /* out: collation order position */
  77. ulint code) /* in: code of a character stored in database record */
  78. {
  79. return((ulint) srv_latin1_ordering[code]);
  80. }
  81. /*****************************************************************
  82. Returns TRUE if two types are equal for comparison purposes. */
  83. ibool
  84. cmp_types_are_equal(
  85. /*================*/
  86. /* out: TRUE if the types are considered
  87. equal in comparisons */
  88. dtype_t* type1, /* in: type 1 */
  89. dtype_t* type2) /* in: type 2 */
  90. {
  91. if (dtype_is_non_binary_string_type(type1->mtype, type1->prtype)
  92.     && dtype_is_non_binary_string_type(type2->mtype, type2->prtype)) {
  93. /* Both are non-binary string types: they can be compared if
  94. and only if the charset-collation is the same */
  95. if (dtype_get_charset_coll(type1->prtype)
  96. == dtype_get_charset_coll(type2->prtype)) {
  97. return(TRUE);
  98. }
  99. return(FALSE);
  100.         }
  101. if (dtype_is_binary_string_type(type1->mtype, type1->prtype)
  102.     && dtype_is_binary_string_type(type2->mtype, type2->prtype)) {
  103. /* Both are binary string types: they can be compared */
  104. return(TRUE);
  105. }
  106.         if (type1->mtype != type2->mtype) {
  107. return(FALSE);
  108. }
  109.         if (type1->mtype == DATA_INT
  110.     && (type1->prtype & DATA_UNSIGNED)
  111. != (type2->prtype & DATA_UNSIGNED)) {
  112. /* The storage format of an unsigned integer is different
  113. from a signed integer: in a signed integer we OR
  114. 0x8000... to the value of positive integers. */
  115. return(FALSE);
  116. }
  117.         if (type1->mtype == DATA_INT && type1->len != type2->len) {
  118. return(FALSE);
  119. }
  120. return(TRUE);
  121. }
  122. /*****************************************************************
  123. Innobase uses this function to compare two data fields for which the data type
  124. is such that we must compare whole fields or call MySQL to do the comparison */
  125. static
  126. int
  127. cmp_whole_field(
  128. /*============*/
  129. /* out: 1, 0, -1, if a is greater,
  130. equal, less than b, respectively */
  131. dtype_t* type, /* in: data type */
  132. unsigned char* a, /* in: data field */
  133. unsigned int a_length, /* in: data field length,
  134. not UNIV_SQL_NULL */
  135. unsigned char* b, /* in: data field */
  136. unsigned int b_length) /* in: data field length,
  137. not UNIV_SQL_NULL */
  138. {
  139. float f_1;
  140. float f_2;
  141. double d_1;
  142. double d_2;
  143. int swap_flag = 1;
  144. ulint data_type;
  145. data_type = type->mtype;
  146. switch (data_type) {
  147.      case DATA_DECIMAL:
  148. /* Remove preceding spaces */
  149. for (; a_length && *a == ' '; a++, a_length--);
  150. for (; b_length && *b == ' '; b++, b_length--);
  151.        if (*a == '-') {
  152. if (*b != '-') {
  153.    return(-1);
  154.    }
  155. a++; b++;
  156. a_length--;
  157. b_length--;
  158. swap_flag = -1;
  159.        } else if (*b == '-') {
  160. return(1);
  161. }
  162.        while (a_length > 0 && (*a == '+' || *a == '0')) {
  163. a++; a_length--;
  164.        }
  165.        while (b_length > 0 && (*b == '+' || *b == '0')) {
  166. b++; b_length--;
  167.        }
  168.       
  169.        if (a_length != b_length) {
  170. if (a_length < b_length) {
  171. return(-swap_flag);
  172. }
  173. return(swap_flag);
  174. }
  175. while (a_length > 0 && *a == *b) {
  176. a++; b++; a_length--;
  177. }
  178. if (a_length == 0) {
  179. return(0);
  180. }
  181. if (*a > *b) {
  182. return(swap_flag);
  183. }
  184. return(-swap_flag);
  185.      case DATA_DOUBLE:
  186. d_1 = mach_double_read(a);
  187. d_2 = mach_double_read(b);
  188.        if (d_1 > d_2) {
  189.        return(1);
  190.        } else if (d_2 > d_1) {
  191.        return(-1);
  192.        }
  193.        return(0);
  194. case DATA_FLOAT:
  195. f_1 = mach_float_read(a);
  196. f_2 = mach_float_read(b);
  197.        if (f_1 > f_2) {
  198.        return(1);
  199.        } else if (f_2 > f_1) {
  200.        return(-1);
  201.        }
  202.        return(0);
  203. case DATA_VARMYSQL:
  204. case DATA_MYSQL:
  205. case DATA_BLOB:
  206. if (data_type == DATA_BLOB
  207.     && 0 != (type->prtype & DATA_BINARY_TYPE)) {
  208. ut_print_timestamp(stderr);
  209.         fprintf(stderr,
  210. "  InnoDB: Error: comparing a binary BLOB with a character set sensitiven"
  211. "InnoDB: comparison!n");
  212. }    
  213. return(innobase_mysql_cmp(
  214. (int)(type->prtype & DATA_MYSQL_TYPE_MASK),
  215. (uint)dtype_get_charset_coll(type->prtype),
  216. a, a_length, b, b_length));
  217. default:
  218.         fprintf(stderr,
  219. "InnoDB: unknown type number %lun",
  220. (ulong) data_type);
  221.         ut_error;
  222. }
  223. return(0);
  224. }
  225. /*****************************************************************
  226. This function is used to compare two data fields for which we know the
  227. data type. */
  228. int
  229. cmp_data_data_slow(
  230. /*===============*/
  231. /* out: 1, 0, -1, if data1 is greater, equal, 
  232. less than data2, respectively */
  233. dtype_t* cur_type,/* in: data type of the fields */
  234. byte* data1, /* in: data field (== a pointer to a memory
  235. buffer) */
  236. ulint len1, /* in: data field length or UNIV_SQL_NULL */
  237. byte* data2, /* in: data field (== a pointer to a memory
  238. buffer) */
  239. ulint len2) /* in: data field length or UNIV_SQL_NULL */
  240. {
  241. ulint data1_byte;
  242. ulint data2_byte;
  243. ulint cur_bytes;
  244. ut_ad(dtype_validate(cur_type));
  245. if (len1 == UNIV_SQL_NULL || len2 == UNIV_SQL_NULL) {
  246. if (len1 == len2) {
  247. return(0);
  248. }
  249. if (len1 == UNIV_SQL_NULL) {
  250. /* We define the SQL null to be the smallest possible
  251. value of a field in the alphabetical order */
  252. return(-1);
  253. }
  254. return(1);
  255. }
  256. if (cur_type->mtype >= DATA_FLOAT
  257.     || (cur_type->mtype == DATA_BLOB
  258.         && 0 == (cur_type->prtype & DATA_BINARY_TYPE)
  259. && dtype_get_charset_coll(cur_type->prtype) !=
  260. data_mysql_latin1_swedish_charset_coll)) {
  261. return(cmp_whole_field(cur_type,
  262. data1, (unsigned) len1,
  263. data2, (unsigned) len2));
  264. }
  265. /* Compare then the fields */
  266. cur_bytes = 0;
  267. for (;;) {
  268. if (len1 <= cur_bytes) {
  269. if (len2 <= cur_bytes) {
  270. return(0);
  271. }
  272. data1_byte = dtype_get_pad_char(cur_type);
  273. if (data1_byte == ULINT_UNDEFINED) {
  274. return(-1);
  275. }
  276. } else {
  277. data1_byte = *data1;
  278. }
  279. if (len2 <= cur_bytes) {
  280. data2_byte = dtype_get_pad_char(cur_type);
  281. if (data2_byte == ULINT_UNDEFINED) {
  282. return(1);
  283. }
  284. } else {
  285. data2_byte = *data2;
  286. }
  287. if (data1_byte == data2_byte) {
  288. /* If the bytes are equal, they will remain such even
  289. after the collation transformation below */
  290. goto next_byte;
  291. }
  292. if (cur_type->mtype <= DATA_CHAR
  293.     || (cur_type->mtype == DATA_BLOB
  294.         && 0 == (cur_type->prtype & DATA_BINARY_TYPE))) {
  295. data1_byte = cmp_collate(data1_byte);
  296. data2_byte = cmp_collate(data2_byte);
  297. }
  298. if (data1_byte > data2_byte) {
  299. return(1);
  300. } else if (data1_byte < data2_byte) {
  301. return(-1);
  302. }
  303. next_byte:
  304. /* Next byte */
  305. cur_bytes++;
  306. data1++;
  307. data2++;
  308. }
  309. return(0); /* Not reached */
  310. }
  311. /*****************************************************************
  312. This function is used to compare a data tuple to a physical record.
  313. Only dtuple->n_fields_cmp first fields are taken into account for
  314. the the data tuple! If we denote by n = n_fields_cmp, then rec must
  315. have either m >= n fields, or it must differ from dtuple in some of
  316. the m fields rec has. If rec has an externally stored field we do not
  317. compare it but return with value 0 if such a comparison should be
  318. made. */
  319. int
  320. cmp_dtuple_rec_with_match(
  321. /*======================*/
  322. /* out: 1, 0, -1, if dtuple is greater, equal, 
  323. less than rec, respectively, when only the 
  324. common first fields are compared, or
  325. until the first externally stored field in
  326. rec */
  327. dtuple_t* dtuple, /* in: data tuple */
  328. rec_t* rec, /* in: physical record which differs from
  329. dtuple in some of the common fields, or which
  330. has an equal number or more fields than
  331. dtuple */
  332. ulint*   matched_fields, /* in/out: number of already completely 
  333. matched fields; when function returns,
  334. contains the value for current comparison */
  335. ulint*    matched_bytes) /* in/out: number of already matched 
  336. bytes within the first field not completely
  337. matched; when function returns, contains the
  338. value for current comparison */
  339. {
  340. dtype_t* cur_type; /* pointer to type of the current
  341. field in dtuple */
  342. dfield_t* dtuple_field; /* current field in logical record */
  343. ulint dtuple_f_len; /* the length of the current field 
  344. in the logical record */
  345. byte* dtuple_b_ptr; /* pointer to the current byte in 
  346. logical field data */
  347. ulint dtuple_byte; /* value of current byte to be compared 
  348. in dtuple*/
  349. ulint rec_f_len; /* length of current field in rec */
  350. byte* rec_b_ptr; /* pointer to the current byte in 
  351. rec field */
  352. ulint rec_byte; /* value of current byte to be 
  353. compared in rec */
  354. ulint cur_field; /* current field number */
  355. ulint cur_bytes;  /* number of already matched bytes 
  356. in current field */
  357. int ret = 3333; /* return value */
  358. ut_ad(dtuple && rec && matched_fields && matched_bytes);
  359. ut_ad(dtuple_check_typed(dtuple));
  360. cur_field = *matched_fields;
  361. cur_bytes = *matched_bytes;
  362. ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple));
  363. ut_ad(cur_field <= rec_get_n_fields(rec));
  364. /* Match fields in a loop; stop if we run out of fields in dtuple
  365. or find an externally stored field */
  366. while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
  367. dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
  368. cur_type = dfield_get_type(dtuple_field);
  369. dtuple_f_len = dfield_get_len(dtuple_field);
  370. rec_b_ptr = rec_get_nth_field(rec, cur_field, &rec_f_len);
  371. /* If we have matched yet 0 bytes, it may be that one or
  372. both the fields are SQL null, or the record or dtuple may be
  373. the predefined minimum record, or the field is externally
  374. stored */
  375. if (cur_bytes == 0) {
  376. if (cur_field == 0) {
  377. if (rec_get_info_bits(rec)
  378.     & REC_INFO_MIN_REC_FLAG) {
  379. if (dtuple_get_info_bits(dtuple)
  380.          & REC_INFO_MIN_REC_FLAG) {
  381.      ret = 0;
  382.      } else {
  383.      ret = 1;
  384.      }
  385. goto order_resolved;
  386. }
  387. if (dtuple_get_info_bits(dtuple)
  388.     & REC_INFO_MIN_REC_FLAG) {
  389.        ret = -1;
  390. goto order_resolved;
  391. }
  392. }
  393. if (rec_get_nth_field_extern_bit(rec, cur_field)) {
  394. /* We do not compare to an externally
  395. stored field */
  396. ret = 0;
  397. goto order_resolved;
  398. }
  399.      if (dtuple_f_len == UNIV_SQL_NULL
  400.             || rec_f_len == UNIV_SQL_NULL) {
  401. if (dtuple_f_len == rec_f_len) {
  402. goto next_field;
  403. }
  404. if (rec_f_len == UNIV_SQL_NULL) {
  405. /* We define the SQL null to be the 
  406. smallest possible value of a field 
  407. in the alphabetical order */
  408. ret = 1;
  409. } else {
  410. ret = -1;
  411. }
  412. goto order_resolved;
  413. }
  414. }
  415. if (cur_type->mtype >= DATA_FLOAT
  416.          || (cur_type->mtype == DATA_BLOB
  417.          && 0 == (cur_type->prtype & DATA_BINARY_TYPE)
  418. && dtype_get_charset_coll(cur_type->prtype) !=
  419. data_mysql_latin1_swedish_charset_coll)) {
  420. ret = cmp_whole_field(
  421. cur_type,
  422. dfield_get_data(dtuple_field),
  423. (unsigned) dtuple_f_len,
  424. rec_b_ptr, (unsigned) rec_f_len);
  425. if (ret != 0) {
  426. cur_bytes = 0;
  427. goto order_resolved;
  428. } else {
  429. goto next_field;
  430. }
  431. }
  432. /* Set the pointers at the current byte */
  433. rec_b_ptr = rec_b_ptr + cur_bytes;
  434. dtuple_b_ptr = (byte*)dfield_get_data(dtuple_field) 
  435. + cur_bytes;
  436. /* Compare then the fields */
  437. for (;;) {
  438. if (rec_f_len <= cur_bytes) {
  439. if (dtuple_f_len <= cur_bytes) {
  440. goto next_field;
  441. }
  442. rec_byte = dtype_get_pad_char(cur_type);
  443. if (rec_byte == ULINT_UNDEFINED) {
  444. ret = 1;
  445. goto order_resolved;
  446. }
  447. } else {
  448. rec_byte = *rec_b_ptr;
  449. }
  450. if (dtuple_f_len <= cur_bytes) {
  451. dtuple_byte = dtype_get_pad_char(cur_type);
  452. if (dtuple_byte == ULINT_UNDEFINED) {
  453. ret = -1;
  454. goto order_resolved;
  455. }
  456. } else {
  457. dtuple_byte = *dtuple_b_ptr;
  458. }
  459. if (dtuple_byte == rec_byte) {
  460. /* If the bytes are equal, they will
  461. remain such even after the collation
  462. transformation below */
  463. goto next_byte;
  464. }
  465. if (cur_type->mtype <= DATA_CHAR
  466.     || (cur_type->mtype == DATA_BLOB
  467.         && 0 ==
  468.     (cur_type->prtype & DATA_BINARY_TYPE))) {
  469. rec_byte = cmp_collate(rec_byte);
  470. dtuple_byte = cmp_collate(dtuple_byte);
  471. }
  472. if (dtuple_byte > rec_byte) {
  473. ret = 1;
  474. goto order_resolved;
  475. } else if (dtuple_byte < rec_byte) {
  476. ret = -1;
  477. goto order_resolved;
  478. }
  479. next_byte:
  480. /* Next byte */
  481. cur_bytes++;
  482. rec_b_ptr++;
  483. dtuple_b_ptr++;
  484. }
  485. next_field:
  486. cur_field++;
  487. cur_bytes = 0;
  488. }
  489. ut_ad(cur_bytes == 0);
  490. ret = 0; /* If we ran out of fields, dtuple was equal to rec
  491. up to the common fields */
  492. order_resolved:
  493. ut_ad((ret >= - 1) && (ret <= 1));
  494. ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec,
  495. matched_fields));
  496. ut_ad(*matched_fields == cur_field); /* In the debug version, the
  497. above cmp_debug_... sets
  498. *matched_fields to a value */
  499. *matched_fields = cur_field;
  500. *matched_bytes = cur_bytes;
  501. return(ret);
  502. }
  503. /******************************************************************
  504. Compares a data tuple to a physical record. */
  505. int
  506. cmp_dtuple_rec(
  507. /*===========*/
  508. /* out: 1, 0, -1, if dtuple is greater, equal, 
  509. less than rec, respectively; see the comments
  510. for cmp_dtuple_rec_with_match */
  511. dtuple_t*  dtuple, /* in: data tuple */
  512. rec_t*    rec) /* in: physical record */
  513. {
  514. ulint matched_fields = 0;
  515. ulint matched_bytes = 0;
  516. return(cmp_dtuple_rec_with_match(dtuple, rec, &matched_fields,
  517. &matched_bytes));
  518. }
  519. /******************************************************************
  520. Checks if a dtuple is a prefix of a record. The last field in dtuple
  521. is allowed to be a prefix of the corresponding field in the record. */
  522. ibool
  523. cmp_dtuple_is_prefix_of_rec(
  524. /*========================*/
  525. /* out: TRUE if prefix */
  526. dtuple_t*  dtuple, /* in: data tuple */
  527. rec_t*    rec) /* in: physical record */
  528. {
  529. ulint n_fields;
  530. ulint matched_fields = 0;
  531. ulint matched_bytes = 0;
  532. n_fields = dtuple_get_n_fields(dtuple);
  533. if (n_fields > rec_get_n_fields(rec)) {
  534. return(FALSE);
  535. }
  536. cmp_dtuple_rec_with_match(dtuple, rec, &matched_fields,
  537. &matched_bytes);
  538. if (matched_fields == n_fields) {
  539. return(TRUE);
  540. }
  541. if (matched_fields == n_fields - 1
  542. && matched_bytes == dfield_get_len(
  543. dtuple_get_nth_field(dtuple, n_fields - 1))) {
  544. return(TRUE);
  545. }
  546. return(FALSE);
  547. }
  548. /******************************************************************
  549. Compares a prefix of a data tuple to a prefix of a physical record for
  550. equality. If there are less fields in rec than parameter n_fields, FALSE
  551. is returned. NOTE that n_fields_cmp of dtuple does not affect this
  552. comparison. */
  553. ibool
  554. cmp_dtuple_rec_prefix_equal(
  555. /*========================*/
  556. /* out: TRUE if equal */
  557. dtuple_t* dtuple, /* in: data tuple */
  558. rec_t* rec, /* in: physical record */
  559. ulint n_fields) /* in: number of fields which should be 
  560. compared; must not exceed the number of 
  561. fields in dtuple */
  562. {
  563. ulint matched_fields = 0;
  564. ulint matched_bytes = 0;
  565. ut_ad(n_fields <= dtuple_get_n_fields(dtuple));
  566. if (rec_get_n_fields(rec) < n_fields) {
  567. return(FALSE);
  568. }
  569. cmp_dtuple_rec_with_match(dtuple, rec, &matched_fields, 
  570. &matched_bytes);
  571. if (matched_fields >= n_fields) {
  572. return(TRUE);
  573. }
  574. return(FALSE);
  575. }
  576. /*****************************************************************
  577. This function is used to compare two physical records. Only the common
  578. first fields are compared, and if an externally stored field is
  579. encountered, then 0 is returned. */
  580. int
  581. cmp_rec_rec_with_match(
  582. /*===================*/
  583. /* out: 1, 0 , -1 if rec1 is greater, equal,
  584. less, respectively, than rec2; only the common
  585. first fields are compared */
  586. rec_t* rec1, /* in: physical record */
  587. rec_t* rec2, /* in: physical record */
  588. dict_index_t* index, /* in: data dictionary index */
  589. ulint*   matched_fields, /* in/out: number of already completely 
  590. matched fields; when the function returns,
  591. contains the value the for current
  592. comparison */
  593. ulint*    matched_bytes) /* in/out: number of already matched 
  594. bytes within the first field not completely
  595. matched; when the function returns, contains
  596. the value for the current comparison */
  597. {
  598. dtype_t* cur_type; /* pointer to type struct of the
  599. current field in index */
  600. ulint rec1_n_fields; /* the number of fields in rec */
  601. ulint rec1_f_len; /* length of current field in rec */
  602. byte* rec1_b_ptr; /* pointer to the current byte in rec field */
  603. ulint rec1_byte; /* value of current byte to be compared in
  604. rec */
  605. ulint rec2_n_fields; /* the number of fields in rec */
  606. ulint rec2_f_len; /* length of current field in rec */
  607. byte* rec2_b_ptr; /* pointer to the current byte in rec field */
  608. ulint rec2_byte; /* value of current byte to be compared in
  609. rec */
  610. ulint cur_field; /* current field number */
  611. ulint cur_bytes;  /* number of already matched bytes in current
  612. field */
  613. int ret = 3333; /* return value */
  614. ut_ad(rec1 && rec2 && index);
  615. rec1_n_fields = rec_get_n_fields(rec1);
  616. rec2_n_fields = rec_get_n_fields(rec2);
  617. cur_field = *matched_fields;
  618. cur_bytes = *matched_bytes;
  619. /* Match fields in a loop; stop if we run out of fields in either
  620. record */
  621. while ((cur_field < rec1_n_fields) && (cur_field < rec2_n_fields)) {
  622. if (index->type & DICT_UNIVERSAL) {
  623. cur_type = dtype_binary;
  624. } else {
  625. cur_type = dict_col_get_type(
  626.       dict_field_get_col(
  627. dict_index_get_nth_field(index, cur_field)));
  628. }
  629. rec1_b_ptr = rec_get_nth_field(rec1, cur_field, &rec1_f_len);
  630. rec2_b_ptr = rec_get_nth_field(rec2, cur_field, &rec2_f_len);
  631. if (cur_bytes == 0) {
  632. if (cur_field == 0) {
  633. /* Test if rec is the predefined minimum
  634. record */
  635. if (rec_get_info_bits(rec1)
  636. & REC_INFO_MIN_REC_FLAG) {
  637. if (rec_get_info_bits(rec2) 
  638.     & REC_INFO_MIN_REC_FLAG) {
  639. ret = 0;
  640. } else {
  641. ret = -1;
  642. }
  643. goto order_resolved;
  644. } else if (rec_get_info_bits(rec2) 
  645.    & REC_INFO_MIN_REC_FLAG) {
  646. ret = 1;
  647. goto order_resolved;
  648. }
  649. }
  650. if (rec_get_nth_field_extern_bit(rec1, cur_field)
  651.     || rec_get_nth_field_extern_bit(rec2, cur_field)) {
  652. /* We do not compare to an externally
  653. stored field */
  654. ret = 0;
  655. goto order_resolved;
  656. }
  657.      if (rec1_f_len == UNIV_SQL_NULL
  658.             || rec2_f_len == UNIV_SQL_NULL) {
  659. if (rec1_f_len == rec2_f_len) {
  660. goto next_field;
  661. } else if (rec2_f_len == UNIV_SQL_NULL) {
  662. /* We define the SQL null to be the 
  663. smallest possible value of a field 
  664. in the alphabetical order */
  665. ret = 1;
  666. } else {
  667. ret = -1;
  668. }
  669. goto order_resolved;
  670. }
  671. }
  672. if (cur_type->mtype >= DATA_FLOAT
  673.          || (cur_type->mtype == DATA_BLOB
  674.          && 0 == (cur_type->prtype & DATA_BINARY_TYPE)
  675. && dtype_get_charset_coll(cur_type->prtype) !=
  676. data_mysql_latin1_swedish_charset_coll)) {
  677. ret = cmp_whole_field(cur_type,
  678. rec1_b_ptr, (unsigned) rec1_f_len,
  679. rec2_b_ptr, (unsigned) rec2_f_len);
  680. if (ret != 0) {
  681. cur_bytes = 0;
  682. goto order_resolved;
  683. } else {
  684. goto next_field;
  685. }
  686. }
  687. /* Set the pointers at the current byte */
  688. rec1_b_ptr = rec1_b_ptr + cur_bytes;
  689. rec2_b_ptr = rec2_b_ptr + cur_bytes;
  690. /* Compare then the fields */
  691. for (;;) {
  692. if (rec2_f_len <= cur_bytes) {
  693. if (rec1_f_len <= cur_bytes) {
  694. goto next_field;
  695. }
  696. rec2_byte = dtype_get_pad_char(cur_type);
  697. if (rec2_byte == ULINT_UNDEFINED) {
  698. ret = 1;
  699. goto order_resolved;
  700. }
  701. } else {
  702. rec2_byte = *rec2_b_ptr;
  703. }
  704. if (rec1_f_len <= cur_bytes) {
  705. rec1_byte = dtype_get_pad_char(cur_type);
  706. if (rec1_byte == ULINT_UNDEFINED) {
  707. ret = -1;
  708. goto order_resolved;
  709. }
  710. } else {
  711. rec1_byte = *rec1_b_ptr;
  712. }
  713. if (rec1_byte == rec2_byte) {
  714. /* If the bytes are equal, they will remain
  715. such even after the collation transformation 
  716. below */
  717. goto next_byte;
  718. }
  719. if (cur_type->mtype <= DATA_CHAR
  720.     || (cur_type->mtype == DATA_BLOB
  721.         && 0 ==
  722.     (cur_type->prtype & DATA_BINARY_TYPE))) {
  723. rec1_byte = cmp_collate(rec1_byte);
  724. rec2_byte = cmp_collate(rec2_byte);
  725. }
  726. if (rec1_byte < rec2_byte) {
  727. ret = -1;
  728. goto order_resolved;
  729. } else if (rec1_byte > rec2_byte) {
  730. ret = 1;
  731. goto order_resolved;
  732. }
  733. next_byte:
  734. /* Next byte */
  735. cur_bytes++;
  736. rec1_b_ptr++;
  737. rec2_b_ptr++;
  738. }
  739. next_field:
  740. cur_field++;
  741. cur_bytes = 0;
  742. }
  743. ut_ad(cur_bytes == 0);
  744. ret = 0; /* If we ran out of fields, rec1 was equal to rec2 up
  745. to the common fields */
  746. order_resolved:
  747. ut_ad((ret >= - 1) && (ret <= 1));
  748. *matched_fields = cur_field;
  749. *matched_bytes = cur_bytes;
  750. return(ret);
  751. }
  752. #ifdef UNIV_DEBUG
  753. /*****************************************************************
  754. Used in debug checking of cmp_dtuple_... .
  755. This function is used to compare a data tuple to a physical record. If
  756. dtuple has n fields then rec must have either m >= n fields, or it must
  757. differ from dtuple in some of the m fields rec has. If encounters an
  758. externally stored field, returns 0. */
  759. static
  760. int
  761. cmp_debug_dtuple_rec_with_match(
  762. /*============================*/
  763. /* out: 1, 0, -1, if dtuple is greater, equal, 
  764. less than rec, respectively, when only the 
  765. common first fields are compared */
  766. dtuple_t* dtuple, /* in: data tuple */
  767. rec_t* rec, /* in: physical record which differs from
  768. dtuple in some of the common fields, or which
  769. has an equal number or more fields than
  770. dtuple */
  771. ulint*   matched_fields) /* in/out: number of already
  772. completely matched fields; when function
  773. returns, contains the value for current
  774. comparison */
  775. {
  776. dtype_t* cur_type; /* pointer to type of the current
  777. field in dtuple */
  778. dfield_t* dtuple_field; /* current field in logical record */
  779. ulint dtuple_f_len; /* the length of the current field 
  780. in the logical record */
  781. byte* dtuple_f_data; /* pointer to the current logical
  782. field data */
  783. ulint rec_f_len; /* length of current field in rec */
  784. byte* rec_f_data; /* pointer to the current rec field */
  785. int ret = 3333; /* return value */
  786. ulint cur_field; /* current field number */
  787. ut_ad(dtuple && rec && matched_fields);
  788. ut_ad(dtuple_check_typed(dtuple));
  789. ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple));
  790. ut_ad(*matched_fields <= rec_get_n_fields(rec));
  791. cur_field = *matched_fields;
  792. if (cur_field == 0) {
  793. if (rec_get_info_bits(rec) & REC_INFO_MIN_REC_FLAG) {
  794. if (dtuple_get_info_bits(dtuple)
  795.          & REC_INFO_MIN_REC_FLAG) {
  796. ret = 0;
  797. } else {
  798. ret = 1;
  799. }
  800. goto order_resolved;
  801. }
  802. if (dtuple_get_info_bits(dtuple) & REC_INFO_MIN_REC_FLAG) {
  803.   ret = -1;
  804. goto order_resolved;
  805. }
  806. }
  807. /* Match fields in a loop; stop if we run out of fields in dtuple */
  808. while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
  809. dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
  810. cur_type = dfield_get_type(dtuple_field);
  811. dtuple_f_data = dfield_get_data(dtuple_field);
  812. dtuple_f_len = dfield_get_len(dtuple_field);
  813. rec_f_data = rec_get_nth_field(rec, cur_field, &rec_f_len);
  814. if (rec_get_nth_field_extern_bit(rec, cur_field)) {
  815. /* We do not compare to an externally stored field */
  816. ret = 0;
  817. goto order_resolved;
  818. }
  819. ret = cmp_data_data(cur_type, dtuple_f_data, dtuple_f_len,
  820. rec_f_data, rec_f_len);
  821. if (ret != 0) {
  822. goto order_resolved;
  823. cur_field++;
  824. }
  825. ret = 0; /* If we ran out of fields, dtuple was equal to rec
  826. up to the common fields */
  827. order_resolved:
  828. ut_ad((ret >= - 1) && (ret <= 1));
  829. *matched_fields = cur_field;
  830. return(ret);
  831. }
  832. #endif /* UNIV_DEBUG */