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

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 "Code_query.hpp"
  14. #include "Code_query_join.hpp"
  15. #include "Code_query_scan.hpp"
  16. #include "Code_root.hpp"
  17. // Plan_query_join
  18. Plan_query_join::~Plan_query_join()
  19. {
  20. }
  21. Plan_base*
  22. Plan_query_join::analyze(Ctx& ctx, Ctl& ctl)
  23. {
  24.     ctx_assert(m_inner != 0);
  25.     m_inner->analyze(ctx, ctl);
  26.     if (! ctx.ok())
  27. return 0;
  28.     ctx_assert(m_outer != 0);
  29.     m_outer->analyze(ctx, ctl);
  30.     if (! ctx.ok())
  31. return 0;
  32.     return this;
  33. }
  34. Exec_base*
  35. Plan_query_join::codegen(Ctx& ctx, Ctl& ctl)
  36. {
  37.     // generate code for subqueries
  38.     ctx_assert(m_inner != 0);
  39.     Exec_query* execInner = static_cast<Exec_query*>(m_inner->codegen(ctx, ctl));
  40.     if (! ctx.ok())
  41. return 0;
  42.     ctx_assert(execInner != 0);
  43.     ctx_assert(m_outer != 0);
  44.     ctl.m_execQuery = execInner;
  45.     Exec_query* execOuter = static_cast<Exec_query*>(m_outer->codegen(ctx, ctl));
  46.     if (! ctx.ok())
  47. return 0;
  48.     ctx_assert(execOuter != 0);
  49.     // combine sql specs from subqueries
  50.     const SqlSpecs& specsInner = execInner->getCode().sqlSpecs();
  51.     const SqlSpecs& specsOuter = execOuter->getCode().sqlSpecs();
  52.     SqlSpecs sqlSpecs(specsInner.count() + specsOuter.count());
  53.     for (unsigned i = 1; i <= specsInner.count(); i++) {
  54. const SqlSpec sqlSpec(specsInner.getEntry(i), SqlSpec::Reference);
  55. sqlSpecs.setEntry(i, sqlSpec);
  56.     }
  57.     for (unsigned i = 1; i <= specsOuter.count(); i++) {
  58. const SqlSpec sqlSpec(specsOuter.getEntry(i), SqlSpec::Reference);
  59. sqlSpecs.setEntry(specsInner.count() + i, sqlSpec);
  60.     }
  61.     // create the code
  62.     Exec_query_join* exec = new Exec_query_join(ctl.m_execRoot);
  63.     ctl.m_execRoot->saveNode(exec);
  64.     exec->setInner(execInner);
  65.     exec->setOuter(execOuter);
  66.     Exec_query_join::Code& code = *new Exec_query_join::Code(sqlSpecs);
  67.     exec->setCode(code);
  68.     return exec;
  69. }
  70. void
  71. Plan_query_join::print(Ctx& ctx)
  72. {
  73.     ctx.print(" [query_join");
  74.     Plan_base* a[] = { m_inner, m_outer };
  75.     printList(ctx, a, 2);
  76.     ctx.print("]");
  77. }
  78. // Exec_query_join
  79. Exec_query_join::Code::~Code()
  80. {
  81. }
  82. Exec_query_join::Data::~Data()
  83. {
  84. }
  85. Exec_query_join::~Exec_query_join()
  86. {
  87. }
  88. void
  89. Exec_query_join::alloc(Ctx& ctx, Ctl& ctl)
  90. {
  91.     // allocate the subqueries
  92.     ctx_assert(m_inner != 0);
  93.     m_inner->alloc(ctx, ctl);
  94.     if (! ctx.ok())
  95. return;
  96.     ctx_assert(m_outer != 0);
  97.     ctl.m_query = m_inner;
  98.     m_outer->alloc(ctx, ctl);
  99.     if (! ctx.ok())
  100. return;
  101.     // combine data rows from subqueries
  102.     const Code& code = getCode();
  103.     const SqlRow& rowInner = m_inner->getData().sqlRow();
  104.     const SqlRow& rowOuter = m_outer->getData().sqlRow();
  105.     SqlRow sqlRow(code.m_sqlSpecs);
  106.     for (unsigned i = 1; i <= rowInner.count(); i++) {
  107. const SqlSpec& sqlSpec = code.m_sqlSpecs.getEntry(i);
  108. const SqlField sqlField(sqlSpec, &rowInner.getEntry(i));
  109. sqlRow.setEntry(i, sqlField);
  110.     }
  111.     for (unsigned i = 1; i <= rowOuter.count(); i++) {
  112. const SqlSpec& sqlSpec = code.m_sqlSpecs.getEntry(rowInner.count() + i);
  113. const SqlField sqlField(sqlSpec, &rowOuter.getEntry(i));
  114. sqlRow.setEntry(rowInner.count() + i, sqlField);
  115.     }
  116.     // create the data
  117.     Data& data = *new Data(this, sqlRow);
  118.     setData(data);
  119. }
  120. void
  121. Exec_query_join::execImpl(Ctx& ctx, Ctl& ctl)
  122. {
  123.     // execute only inner query
  124.     ctx_assert(m_inner != 0);
  125.     m_inner->execute(ctx, ctl);
  126. }
  127. bool
  128. Exec_query_join::fetchImpl(Ctx& ctx, Ctl& ctl)
  129. {
  130.     ctx_assert(m_inner != 0);
  131.     ctx_assert(m_outer != 0);
  132.     if (getData().getState() == ResultSet::State_init) {
  133. // fetch first row from inner
  134. if (! m_inner->fetch(ctx, ctl))
  135.     return false;
  136.     }
  137.     while (1) {
  138. if (m_outer->getData().getState() == ResultSet::State_end) {
  139.     // execute or re-execute outer
  140.     Ctl ctl(0);
  141.     m_outer->close(ctx);
  142.     if (! ctx.ok())
  143. return false;
  144.     m_outer->execute(ctx, ctl);
  145.     if (! ctx.ok())
  146. return false;
  147. }
  148. if (! m_outer->fetch(ctx, ctl)) {
  149.     if (! ctx.ok())
  150. return false;
  151.     // fetch next row from inner
  152.     if (! m_inner->fetch(ctx, ctl))
  153. return false;
  154. }
  155. else
  156.     return true;
  157.     }
  158. }
  159. void
  160. Exec_query_join::close(Ctx& ctx)
  161. {
  162.     ctx_assert(m_inner != 0);
  163.     m_inner->close(ctx);
  164.     ctx_assert(m_outer != 0);
  165.     m_outer->close(ctx);
  166. }
  167. void
  168. Exec_query_join::print(Ctx& ctx)
  169. {
  170.     ctx.print(" [query_join");
  171.     Exec_base* a[] = { m_inner, m_outer };
  172.     printList(ctx, a, 2);
  173.     ctx.print("]");
  174. }