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

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 <algorithm>
  14. #include "Code_query_group.hpp"
  15. #include "Code_root.hpp"
  16. // Plan_query_group
  17. Plan_query_group::~Plan_query_group()
  18. {
  19. }
  20. Plan_expr_row*
  21. Plan_query_group::getRow()
  22. {
  23.     ctx_assert(m_dataRow != 0);
  24.     return m_dataRow;
  25. }
  26. Plan_base*
  27. Plan_query_group::analyze(Ctx& ctx, Ctl& ctl)
  28. {
  29.     ctx_assert(m_query != 0);
  30.     m_query->analyze(ctx, ctl);
  31.     if (! ctx.ok())
  32. return 0;
  33.     ctx_assert(m_dataRow != 0);
  34.     m_dataRow->analyze(ctx, ctl);
  35.     if (! ctx.ok())
  36. return 0;
  37.     ctx_assert(m_groupRow != 0);
  38.     m_groupRow->analyze(ctx, ctl);
  39.     if (! ctx.ok())
  40. return 0;
  41.     if (m_havingPred != 0) {
  42. ctl.m_having = true;
  43. m_havingPred->analyze(ctx, ctl);
  44. if (! ctx.ok())
  45.     return 0;
  46. ctl.m_having = false;
  47.     }
  48.     return this;
  49. }
  50. Exec_base*
  51. Plan_query_group::codegen(Ctx& ctx, Ctl& ctl)
  52. {
  53.     // create code for the subquery
  54.     ctx_assert(m_query != 0);
  55.     Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
  56.     if (! ctx.ok())
  57. return 0;
  58.     ctx_assert(execQuery != 0);
  59.     // create code for the rows based on query code
  60.     ctl.m_execQuery = execQuery;
  61.     ctx_assert(m_dataRow != 0);
  62.     Exec_expr_row* execDataRow = static_cast<Exec_expr_row*>(m_dataRow->codegen(ctx, ctl));
  63.     if (! ctx.ok())
  64. return 0;
  65.     ctx_assert(execDataRow != 0);
  66.     ctx_assert(m_groupRow != 0);
  67.     Exec_expr_row* execGroupRow = static_cast<Exec_expr_row*>(m_groupRow->codegen(ctx, ctl));
  68.     if (! ctx.ok())
  69. return 0;
  70.     ctx_assert(execGroupRow != 0);
  71.     Exec_pred* execHavingPred = 0;
  72.     if (m_havingPred != 0) {
  73. ctl.m_having = true;
  74. execHavingPred = static_cast<Exec_pred*>(m_havingPred->codegen(ctx, ctl));
  75. if (! ctx.ok())
  76.     return 0;
  77. ctx_assert(execHavingPred != 0);
  78. ctl.m_having = false;
  79.     }
  80.     // the exec node
  81.     Exec_query_group* exec = new Exec_query_group(ctl.m_execRoot);
  82.     ctl.m_execRoot->saveNode(exec);
  83.     // re-use SqlSpecs from data row
  84.     const SqlSpecs& sqlSpecs = execDataRow->getCode().sqlSpecs();
  85.     Exec_query_group::Code& code = *new Exec_query_group::Code(sqlSpecs);
  86.     exec->setCode(code);
  87.     exec->setQuery(execQuery);
  88.     exec->setDataRow(execDataRow);
  89.     exec->setGroupRow(execGroupRow);
  90.     if (execHavingPred != 0)
  91. exec->setHavingPred(execHavingPred);
  92.     return exec;
  93. }
  94. void
  95. Plan_query_group::print(Ctx& ctx)
  96. {
  97.     ctx.print(" [query_group");
  98.     Plan_base* a[] = { m_query, m_dataRow, m_groupRow };
  99.     printList(ctx, a, 3);
  100.     ctx.print("]");
  101. }
  102. // Exec_query_group
  103. Exec_query_group::Code::~Code()
  104. {
  105. }
  106. Exec_query_group::Data::~Data()
  107. {
  108.     for (GroupList::iterator i = m_groupList.begin(); i != m_groupList.end(); i++) {
  109. delete (*i).first;
  110.     }
  111. }
  112. Exec_query_group::~Exec_query_group()
  113. {
  114. }
  115. const Exec_query*
  116. Exec_query_group::getRawQuery() const
  117. {
  118.     ctx_assert(m_query != 0);
  119.     return m_query;
  120. }
  121. void
  122. Exec_query_group::alloc(Ctx& ctx, Ctl& ctl)
  123. {
  124.     // allocate subquery
  125.     ctx_assert(m_query != 0);
  126.     m_query->alloc(ctx, ctl);
  127.     if (! ctx.ok())
  128. return;
  129.     // allocate rows based on subquery data
  130.     ctl.m_query = m_query;
  131.     ctx_assert(m_dataRow != 0);
  132.     m_dataRow->alloc(ctx, ctl);
  133.     if (! ctx.ok())
  134. return;
  135.     ctx_assert(m_groupRow != 0);
  136.     m_groupRow->alloc(ctx, ctl);
  137.     if (! ctx.ok())
  138. return;
  139.     if (m_havingPred != 0) {
  140. m_havingPred->alloc(ctx, ctl);
  141. if (! ctx.ok())
  142.     return;
  143.     }
  144.     Data& data = *new Data(this, getCode().sqlSpecs());
  145.     setData(data);
  146. }
  147. void
  148. Exec_query_group::execImpl(Ctx& ctx, Ctl& ctl)
  149. {
  150.     ctx_assert(m_query != 0);
  151.     m_query->execute(ctx, ctl);
  152. }
  153. bool
  154. GroupLess::operator()(const SqlRow* s1, const SqlRow* s2) const
  155. {
  156.     ctx_assert(s1 != 0 && s2 != 0);
  157.     const SqlRow& r1 = *s1;
  158.     const SqlRow& r2 = *s2;
  159.     for (unsigned i = 1; i <= r1.count(); i++) {
  160. const SqlField& f1 = r1.getEntry(i);
  161. const SqlField& f2 = r2.getEntry(i);
  162. // nulls last is default in oracle
  163. const bool f1null = f1.sqlNull();
  164. const bool f2null = f2.sqlNull();
  165. if (f1null && f2null)
  166.     continue;
  167. if (! f1null && f2null)
  168.     return true;
  169. if (f1null && ! f2null)
  170.     return false;
  171. if (f1.less(f2))
  172.     return true;
  173. if (f2.less(f1))
  174.     return false;
  175.     }
  176.     return false;
  177. }
  178. bool
  179. Exec_query_group::fetchImpl(Ctx& ctx, Ctl& ctl)
  180. {
  181.     Data& data = getData();
  182.     ctx_assert(m_query != 0 && m_groupRow != 0);
  183.     if (! data.m_grouped) {
  184. // read and group all rows
  185. while (m_query->fetch(ctx, ctl)) {
  186.     // evaluate and insert group-by values
  187.     m_groupRow->evaluate(ctx, ctl);
  188.     if (! ctx.ok())
  189. return false;
  190.     const SqlRow* groupRow = 0;
  191.     unsigned index = 0;
  192.     bool init;
  193.     GroupList::iterator i = data.m_groupList.find(&m_groupRow->getData().sqlRow());
  194.     if (i == data.m_groupList.end()) {
  195. groupRow = m_groupRow->getData().sqlRow().copy();
  196. index = ++data.m_count;
  197. const GroupList::value_type groupPair(groupRow, index);
  198. data.m_groupList.insert(groupPair);
  199. init = true;
  200.     } else {
  201. groupRow = (*i).first;
  202. index = (*i).second;
  203. ctx_assert(groupRow != 0 && index != 0);
  204. init = false;
  205.     }
  206.     // evaluate rows saving expression values at index position
  207.     ctl.m_groupIndex = index;
  208.     ctl.m_groupInit = init;
  209.     m_dataRow->evaluate(ctx, ctl);
  210.     if (! ctx.ok())
  211. return false;
  212.     if (m_havingPred != 0) {
  213. m_havingPred->evaluate(ctx, ctl);
  214. if (! ctx.ok())
  215.     return false;
  216.     }
  217.     if (ctl.m_sortRow != 0) {
  218. ctl.m_sortRow->evaluate(ctx, ctl);
  219. if (! ctx.ok())
  220.     return false;
  221.     }
  222.     ctl.m_groupIndex = 0;
  223. }
  224. if (! ctx.ok())
  225.     return false;
  226. data.m_iterator = data.m_groupList.begin();
  227. data.m_grouped = true;
  228.     }
  229.     while (data.m_iterator != data.m_groupList.end()) {
  230. const SqlRow* groupRow = (*data.m_iterator).first;
  231. const unsigned index = (*data.m_iterator).second;
  232. ctx_assert(groupRow != 0 && index != 0);
  233. if (m_havingPred != 0) {
  234.     Pred_value v = m_havingPred->getData().groupValue(index);
  235.     if (v != Pred_value_true) {
  236. data.m_iterator++;
  237. continue;
  238.     }
  239. }
  240. // make our SqlRow reference to the saved values
  241. for (unsigned i = 1; i <= data.m_sqlRow.count(); i++) {
  242.     const SqlField& currField = m_dataRow->getExpr(i)->getData().groupField(index);
  243.     SqlSpec sqlSpec(currField.sqlSpec(), SqlSpec::Reference);
  244.     SqlField sqlField(sqlSpec, &currField);
  245.     data.m_sqlRow.setEntry(i, sqlField);
  246. }
  247. // send group index up for possible order by
  248. ctl.m_groupIndex = index;
  249. data.m_iterator++;
  250. return true;
  251.     }
  252.     return false;
  253. }
  254. void
  255. Exec_query_group::close(Ctx& ctx)
  256. {
  257.     Data& data = getData();
  258.     ctx_assert(m_query != 0);
  259.     m_query->close(ctx);
  260.     ctx_assert(m_dataRow != 0);
  261.     m_dataRow->close(ctx);
  262.     ctx_assert(m_groupRow != 0);
  263.     m_groupRow->close(ctx);
  264.     if (m_havingPred != 0)
  265. m_havingPred->close(ctx);
  266.     data.m_grouped = false;
  267.     data.m_count = 0;
  268.     for (GroupList::iterator i = data.m_groupList.begin(); i != data.m_groupList.end(); i++) {
  269. delete (*i).first;
  270.     }
  271.     data.m_groupList.clear();
  272. }
  273. void
  274. Exec_query_group::print(Ctx& ctx)
  275. {
  276.     ctx.print(" [query_group");
  277.     Exec_base* a[] = { m_query, m_dataRow, m_groupRow };
  278.     printList(ctx, a, 3);
  279.     ctx.print("]");
  280. }