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

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #define DBTUX_SEARCH_CPP
  14. #include "Dbtux.hpp"
  15. /*
  16.  * Search for entry to add.
  17.  *
  18.  * Similar to searchToRemove (see below).
  19.  *
  20.  * TODO optimize for initial equal attrs in node min/max
  21.  */
  22. void
  23. Dbtux::searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos)
  24. {
  25.   const TreeHead& tree = frag.m_tree;
  26.   const unsigned numAttrs = frag.m_numAttrs;
  27.   NodeHandle currNode(frag);
  28.   currNode.m_loc = tree.m_root;
  29.   // assume success
  30.   treePos.m_match = false;
  31.   if (currNode.m_loc == NullTupLoc) {
  32.     // empty tree
  33.     jam();
  34.     return;
  35.   }
  36.   NodeHandle glbNode(frag);     // potential g.l.b of final node
  37.   /*
  38.    * In order to not (yet) change old behaviour, a position between
  39.    * 2 nodes returns the one at the bottom of the tree.
  40.    */
  41.   NodeHandle bottomNode(frag);
  42.   while (true) {
  43.     jam();
  44.     selectNode(currNode, currNode.m_loc);
  45.     int ret;
  46.     // compare prefix
  47.     unsigned start = 0;
  48.     ret = cmpSearchKey(frag, start, searchKey, currNode.getPref(), tree.m_prefSize);
  49.     if (ret == NdbSqlUtil::CmpUnknown) {
  50.       jam();
  51.       // read and compare remaining attributes
  52.       ndbrequire(start < numAttrs);
  53.       readKeyAttrs(frag, currNode.getMinMax(0), start, c_entryKey);
  54.       ret = cmpSearchKey(frag, start, searchKey, c_entryKey);
  55.       ndbrequire(ret != NdbSqlUtil::CmpUnknown);
  56.     }
  57.     if (ret == 0) {
  58.       jam();
  59.       // keys are equal, compare entry values
  60.       ret = searchEnt.cmp(currNode.getMinMax(0));
  61.     }
  62.     if (ret < 0) {
  63.       jam();
  64.       const TupLoc loc = currNode.getLink(0);
  65.       if (loc != NullTupLoc) {
  66.         jam();
  67.         // continue to left subtree
  68.         currNode.m_loc = loc;
  69.         continue;
  70.       }
  71.       if (! glbNode.isNull()) {
  72.         jam();
  73.         // move up to the g.l.b but remember the bottom node
  74.         bottomNode = currNode;
  75.         currNode = glbNode;
  76.       }
  77.     } else if (ret > 0) {
  78.       jam();
  79.       const TupLoc loc = currNode.getLink(1);
  80.       if (loc != NullTupLoc) {
  81.         jam();
  82.         // save potential g.l.b
  83.         glbNode = currNode;
  84.         // continue to right subtree
  85.         currNode.m_loc = loc;
  86.         continue;
  87.       }
  88.     } else {
  89.       jam();
  90.       treePos.m_loc = currNode.m_loc;
  91.       treePos.m_pos = 0;
  92.       // failed
  93.       treePos.m_match = true;
  94.       return;
  95.     }
  96.     break;
  97.   }
  98.   // anticipate
  99.   treePos.m_loc = currNode.m_loc;
  100.   // binary search
  101.   int lo = -1;
  102.   unsigned hi = currNode.getOccup();
  103.   int ret;
  104.   while (1) {
  105.     jam();
  106.     // hi - lo > 1 implies lo < j < hi
  107.     int j = (hi + lo) / 2;
  108.     // read and compare attributes
  109.     unsigned start = 0;
  110.     readKeyAttrs(frag, currNode.getEnt(j), start, c_entryKey);
  111.     ret = cmpSearchKey(frag, start, searchKey, c_entryKey);
  112.     ndbrequire(ret != NdbSqlUtil::CmpUnknown);
  113.     if (ret == 0) {
  114.       jam();
  115.       // keys are equal, compare entry values
  116.       ret = searchEnt.cmp(currNode.getEnt(j));
  117.     }
  118.     if (ret < 0)
  119.       hi = j;
  120.     else if (ret > 0)
  121.       lo = j;
  122.     else {
  123.       treePos.m_pos = j;
  124.       // failed
  125.       treePos.m_match = true;
  126.       return;
  127.     }
  128.     if (hi - lo == 1)
  129.       break;
  130.   }
  131.   if (ret < 0) {
  132.     jam();
  133.     treePos.m_pos = hi;
  134.     return;
  135.   }
  136.   if (hi < currNode.getOccup()) {
  137.     jam();
  138.     treePos.m_pos = hi;
  139.     return;
  140.   }
  141.   if (bottomNode.isNull()) {
  142.     jam();
  143.     treePos.m_pos = hi;
  144.     return;
  145.   }
  146.   jam();
  147.   // backwards compatible for now
  148.   treePos.m_loc = bottomNode.m_loc;
  149.   treePos.m_pos = 0;
  150. }
  151. /*
  152.  * Search for entry to remove.
  153.  *
  154.  * Compares search key to each node min.  A move to right subtree can
  155.  * overshoot target node.  The last such node is saved.  The final node
  156.  * is a semi-leaf or leaf.  If search key is less than final node min
  157.  * then the saved node is the g.l.b of the final node and we move back
  158.  * to it.
  159.  */
  160. void
  161. Dbtux::searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos)
  162. {
  163.   const TreeHead& tree = frag.m_tree;
  164.   const unsigned numAttrs = frag.m_numAttrs;
  165.   NodeHandle currNode(frag);
  166.   currNode.m_loc = tree.m_root;
  167.   // assume success
  168.   treePos.m_match = true;
  169.   if (currNode.m_loc == NullTupLoc) {
  170.     // empty tree
  171.     jam();
  172.     // failed
  173.     treePos.m_match = false;
  174.     return;
  175.   }
  176.   NodeHandle glbNode(frag);     // potential g.l.b of final node
  177.   while (true) {
  178.     jam();
  179.     selectNode(currNode, currNode.m_loc);
  180.     int ret;
  181.     // compare prefix
  182.     unsigned start = 0;
  183.     ret = cmpSearchKey(frag, start, searchKey, currNode.getPref(), tree.m_prefSize);
  184.     if (ret == NdbSqlUtil::CmpUnknown) {
  185.       jam();
  186.       // read and compare remaining attributes
  187.       ndbrequire(start < numAttrs);
  188.       readKeyAttrs(frag, currNode.getMinMax(0), start, c_entryKey);
  189.       ret = cmpSearchKey(frag, start, searchKey, c_entryKey);
  190.       ndbrequire(ret != NdbSqlUtil::CmpUnknown);
  191.     }
  192.     if (ret == 0) {
  193.       jam();
  194.       // keys are equal, compare entry values
  195.       ret = searchEnt.cmp(currNode.getMinMax(0));
  196.     }
  197.     if (ret < 0) {
  198.       jam();
  199.       const TupLoc loc = currNode.getLink(0);
  200.       if (loc != NullTupLoc) {
  201.         jam();
  202.         // continue to left subtree
  203.         currNode.m_loc = loc;
  204.         continue;
  205.       }
  206.       if (! glbNode.isNull()) {
  207.         jam();
  208.         // move up to the g.l.b
  209.         currNode = glbNode;
  210.       }
  211.     } else if (ret > 0) {
  212.       jam();
  213.       const TupLoc loc = currNode.getLink(1);
  214.       if (loc != NullTupLoc) {
  215.         jam();
  216.         // save potential g.l.b
  217.         glbNode = currNode;
  218.         // continue to right subtree
  219.         currNode.m_loc = loc;
  220.         continue;
  221.       }
  222.     } else {
  223.       jam();
  224.       treePos.m_loc = currNode.m_loc;
  225.       treePos.m_pos = 0;
  226.       return;
  227.     }
  228.     break;
  229.   }
  230.   // anticipate
  231.   treePos.m_loc = currNode.m_loc;
  232.   // pos 0 was handled above
  233.   for (unsigned j = 1, occup = currNode.getOccup(); j < occup; j++) {
  234.     jam();
  235.     // compare only the entry
  236.     if (searchEnt.eq(currNode.getEnt(j))) {
  237.       jam();
  238.       treePos.m_pos = j;
  239.       return;
  240.     }
  241.   }
  242.   treePos.m_pos = currNode.getOccup();
  243.   // failed
  244.   treePos.m_match = false;
  245. }
  246. /*
  247.  * Search for scan start position.
  248.  *
  249.  * Similar to searchToAdd.
  250.  */
  251. void
  252. Dbtux::searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos)
  253. {
  254.   const TreeHead& tree = frag.m_tree;
  255.   NodeHandle currNode(frag);
  256.   currNode.m_loc = tree.m_root;
  257.   if (currNode.m_loc == NullTupLoc) {
  258.     // empty tree
  259.     jam();
  260.     treePos.m_match = false;
  261.     return;
  262.   }
  263.   NodeHandle glbNode(frag);     // potential g.l.b of final node
  264.   NodeHandle bottomNode(frag);
  265.   while (true) {
  266.     jam();
  267.     selectNode(currNode, currNode.m_loc);
  268.     int ret;
  269.     // compare prefix
  270.     ret = cmpScanBound(frag, 0, boundInfo, boundCount, currNode.getPref(), tree.m_prefSize);
  271.     if (ret == NdbSqlUtil::CmpUnknown) {
  272.       jam();
  273.       // read and compare all attributes
  274.       readKeyAttrs(frag, currNode.getMinMax(0), 0, c_entryKey);
  275.       ret = cmpScanBound(frag, 0, boundInfo, boundCount, c_entryKey);
  276.       ndbrequire(ret != NdbSqlUtil::CmpUnknown);
  277.     }
  278.     if (ret < 0) {
  279.       jam();
  280.       const TupLoc loc = currNode.getLink(0);
  281.       if (loc != NullTupLoc) {
  282.         jam();
  283.         // continue to left subtree
  284.         currNode.m_loc = loc;
  285.         continue;
  286.       }
  287.       if (! glbNode.isNull()) {
  288.         jam();
  289.         // move up to the g.l.b but remember the bottom node
  290.         bottomNode = currNode;
  291.         currNode = glbNode;
  292.       } else {
  293.         // start scanning this node
  294.         treePos.m_loc = currNode.m_loc;
  295.         treePos.m_pos = 0;
  296.         treePos.m_match = false;
  297.         treePos.m_dir = 3;
  298.         return;
  299.       }
  300.     } else if (ret > 0) {
  301.       jam();
  302.       const TupLoc loc = currNode.getLink(1);
  303.       if (loc != NullTupLoc) {
  304.         jam();
  305.         // save potential g.l.b
  306.         glbNode = currNode;
  307.         // continue to right subtree
  308.         currNode.m_loc = loc;
  309.         continue;
  310.       }
  311.     } else {
  312.       ndbassert(false);
  313.     }
  314.     break;
  315.   }
  316.   for (unsigned j = 0, occup = currNode.getOccup(); j < occup; j++) {
  317.     jam();
  318.     int ret;
  319.     // read and compare attributes
  320.     readKeyAttrs(frag, currNode.getEnt(j), 0, c_entryKey);
  321.     ret = cmpScanBound(frag, 0, boundInfo, boundCount, c_entryKey);
  322.     ndbrequire(ret != NdbSqlUtil::CmpUnknown);
  323.     if (ret < 0) {
  324.       // start scanning from current entry
  325.       treePos.m_loc = currNode.m_loc;
  326.       treePos.m_pos = j;
  327.       treePos.m_match = false;
  328.       treePos.m_dir = 3;
  329.       return;
  330.     }
  331.   }
  332.   if (! bottomNode.isNull()) {
  333.     jam();
  334.     // start scanning the l.u.b
  335.     treePos.m_loc = bottomNode.m_loc;
  336.     treePos.m_pos = 0;
  337.     treePos.m_match = false;
  338.     treePos.m_dir = 3;
  339.     return;
  340.   }
  341.   // start scanning upwards (pretend we came from right child)
  342.   treePos.m_loc = currNode.m_loc;
  343.   treePos.m_dir = 1;
  344. }