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

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. #include <NdbApi.hpp>
  14. #include <common/StmtArea.hpp>
  15. #include <dictionary/DictSchema.hpp>
  16. #include <dictionary/DictTable.hpp>
  17. #include <dictionary/DictColumn.hpp>
  18. #include "Code_table.hpp"
  19. #include "Code_column.hpp"
  20. #include "Code_expr_column.hpp"
  21. Plan_table::~Plan_table()
  22. {
  23. }
  24. Plan_base*
  25. Plan_table::analyze(Ctx& ctx, Ctl& ctl)
  26. {
  27.     if (m_dictTable != 0) // already done
  28. return this;
  29.     DictTable* table = dictSchema().findTable(m_name);
  30.     if (table == 0) {
  31. table = dictSchema().loadTable(ctx, m_name);
  32. if (table == 0) {
  33.     ctx.pushStatus(Sqlstate::_42S02, Error::Gen, "table %s not found", m_name.c_str());
  34.     return 0;
  35. }
  36.     }
  37.     m_dictTable = table;
  38.     // indexes
  39.     m_indexList.resize(1 + m_dictTable->indexCount());
  40.     for (unsigned i = 0; i <= indexCount(); i++) {
  41. Index& index = m_indexList[i];
  42. index.m_pos = i;
  43. if (index.m_pos == 0) {
  44.     index.m_keyCount = m_dictTable->keyCount();
  45.     index.m_rank = 0;
  46. } else {
  47.     index.m_dictIndex = m_dictTable->getIndex(i);
  48.     index.m_keyCount = index.m_dictIndex->getSize();
  49.     if (index.m_dictIndex->getType() == NdbDictionary::Object::UniqueHashIndex) {
  50. index.m_rank = 1;
  51.     } else if (index.m_dictIndex->getType() == NdbDictionary::Object::OrderedIndex) {
  52. index.m_rank = 2;
  53.     } else {
  54. ctx_assert(false);
  55.     }
  56. }
  57. index.m_keyEqList.resize(1 + index.m_keyCount);
  58.     }
  59.     return this;
  60. }
  61. int
  62. Plan_table::resolveColumn(Ctx& ctx, Plan_column* column, bool stripSchemaName)
  63. {
  64.     ctx_assert(column != 0);
  65.     bool dml, unq;
  66.     switch (column->m_type) {
  67.     case Plan_column::Type_expr:
  68. dml = false;
  69. unq = false;
  70. break;
  71.     case Plan_column::Type_dml:
  72. dml = true;
  73. unq = true;
  74. break;
  75.     case Plan_column::Type_idx:
  76. dml = false;
  77. unq = true;
  78. break;
  79.     default:
  80. ctx_assert(false);
  81. break;
  82.     }
  83.     ColumnVector& columns = ! dml ? m_exprColumns : m_dmlColumns;
  84.     const BaseString& name = column->m_name;
  85.     const BaseString& cname = column->m_cname;
  86.     ctx_log3(("resolve %s column %s in table %s", ! dml ? "expr" : "dml", column->getPrintName(), getPrintName()));
  87.     // find column in table
  88.     DictColumn* dictColumn = dictTable().findColumn(name);
  89.     if (dictColumn == 0)
  90. return 0;
  91.     // qualified column must match table correlation name
  92.     if (! cname.empty()) {
  93. const char* str;
  94. if (! m_cname.empty()) {
  95.     str = m_cname.c_str();
  96. } else {
  97.     str = m_name.c_str();
  98.     if (stripSchemaName && strrchr(str, '.') != 0)
  99. str = strrchr(str, '.') + 1;
  100. }
  101. if (strcmp(cname.c_str(), str) != 0)
  102.     return 0;
  103.     }
  104.     // find in positional list or add to it
  105.     unsigned resPos;
  106.     for (resPos = 1; resPos < columns.size(); resPos++) {
  107. if (strcmp(columns[resPos]->getName().c_str(), name.c_str()) != 0)
  108.     continue;
  109. // these columns must be unique
  110. if (unq) {
  111.     ctx.pushStatus(Error::Gen, "duplicate column %s", column->getName().c_str());
  112.     return -1;
  113. }
  114. break;
  115.     }
  116.     if (resPos >= columns.size()) {
  117. columns.push_back(column);
  118.     }
  119.     ctx_log3(("resolve to attrId %u pos %u", (unsigned)dictColumn->getAttrId(), resPos));
  120.     column->m_dictColumn = dictColumn;
  121.     column->m_resTable = this;
  122.     column->m_resPos = resPos;
  123.     // found
  124.     return 1;
  125. }
  126. bool
  127. Plan_table::resolveEq(Ctx& ctx, Plan_expr_column* column, Plan_expr* expr)
  128. {
  129.     ctx_assert(m_dictTable != 0);
  130.     const TableSet& ts = expr->tableSet();
  131.     TableSet::const_iterator i = ts.find(this);
  132.     if (i != ts.end())
  133. return false;
  134.     unsigned found = 0;
  135.     for (unsigned i = 0; i <= indexCount(); i++) {
  136. Index& index = m_indexList[i];
  137. for (unsigned n = 1, cnt = 0; n <= index.m_keyCount; n++) {
  138.     const DictColumn* dictColumn = 0;
  139.     if (index.m_pos == 0) {
  140. ctx_assert(m_dictTable != 0);
  141. dictColumn = m_dictTable->getKey(n);
  142.     } else {
  143. ctx_assert(index.m_dictIndex != 0);
  144. dictColumn = index.m_dictIndex->getColumn(n);
  145.     }
  146.     if (dictColumn != &column->dictColumn())
  147. continue;
  148.     ctx_assert(++cnt == 1);
  149.     index.m_keyEqList[n].push_back(expr);
  150.     if (index.m_pos == 0)
  151. ctx_log2(("%s: found match to primary key column %s pos %u", getPrintName(), column->getPrintName(), n));
  152.     else
  153. ctx_log2(("%s: found match to index %s column %s pos %u", getPrintName(), index.m_dictIndex->getName().c_str(), column->getPrintName(), n));
  154.     found++;
  155. }
  156.     }
  157.     return (found != 0);
  158. }
  159. void
  160. Plan_table::resolveSet(Ctx& ctx, Index& index, const TableSet& tsDone)
  161. {
  162.     index.m_keyFound = false;
  163.     ExprVector keyEq;
  164.     keyEq.resize(1 + index.m_keyCount);
  165.     resolveSet(ctx, index, tsDone, keyEq, 1);
  166. }
  167. void
  168. Plan_table::resolveSet(Ctx& ctx, Index& index, const TableSet& tsDone, ExprVector& keyEq, unsigned n)
  169. {
  170.     if (n <= index.m_keyCount) {
  171. // building up combinations
  172. ExprList& keyEqList = index.m_keyEqList[n];
  173. for (ExprList::iterator i = keyEqList.begin(); i != keyEqList.end(); i++) {
  174.     keyEq[n] = *i;
  175.     resolveSet(ctx, index, tsDone, keyEq, n + 1);
  176. }
  177. if (! keyEqList.empty() || index.m_rank <= 1 || n == 1)
  178.     return;
  179. // ordered index with maximal initial key match
  180.     }
  181.     TableSet keySet;
  182.     for (unsigned i = 1; i <= n - 1; i++) {
  183. const TableSet& tableSet = keyEq[i]->tableSet();
  184. for (TableSet::const_iterator j = tableSet.begin(); j != tableSet.end(); j++) {
  185.     if (tsDone.find(*j) == tsDone.end())
  186. keySet.insert(*j);
  187. }
  188.     }
  189.     if (! index.m_keyFound || index.m_keySet.size() > keySet.size()) {
  190. index.m_keyFound = true;
  191. index.m_keyEq = keyEq;
  192. index.m_keySet = keySet;
  193. index.m_keyCountUsed = n - 1;
  194. index.m_keyCountUnused = index.m_keyCount - index.m_keyCountUsed;
  195. // set matching size
  196. index.m_keyEq.resize(1 + index.m_keyCountUsed);
  197.     }
  198. }
  199. bool
  200. Plan_table::exactKey(Ctx& ctx, const Index* indexKey) const
  201. {
  202.     ctx_assert(indexKey != 0 && indexKey == &m_indexList[indexKey->m_pos]);
  203.     for (unsigned i = 0; i <= indexCount(); i++) {
  204. const Index& index = m_indexList[i];
  205. const ExprListVector& keyEqList = index.m_keyEqList;
  206. for (unsigned n = 1; n <= index.m_keyCount; n++) {
  207.     if (index.m_pos == indexKey->m_pos) {
  208. ctx_assert(keyEqList[n].size() >= 1);
  209. if (keyEqList[n].size() > 1) {
  210.     ctx_log2(("index %u not exact: column %u has %u > 1 matches",
  211.                              indexKey->m_pos,
  212.                              n,
  213.                              (unsigned)keyEqList[n].size()));
  214.     return false;
  215. }
  216.     } else {
  217. if (keyEqList[n].size() > 0) {
  218.     ctx_log2(("index %u not exact: index %u column %u has %u > 0 matches",
  219.                              indexKey->m_pos,
  220.                              index.m_pos,
  221.                              n,
  222.                              (unsigned)keyEqList[n].size()));
  223.     return false;
  224. }
  225.     }
  226. }
  227.     }
  228.     ctx_log2(("index %u is exact", indexKey->m_pos));
  229.     return true;
  230. }
  231. Exec_base*
  232. Plan_table::codegen(Ctx& ctx, Ctl& ctl)
  233. {
  234.     ctx_assert(false);
  235.     return 0;
  236. }
  237. void
  238. Plan_table::print(Ctx& ctx)
  239. {
  240.     ctx.print(" [table %s]", getPrintName());
  241. }