summaryrefslogtreecommitdiff
path: root/storage/ndb/src/old_files/client/odbc/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'storage/ndb/src/old_files/client/odbc/codegen')
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/CodeGen.cpp229
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/CodeGen.hpp69
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_base.cpp167
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_base.hpp237
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_column.cpp72
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_column.hpp122
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_comp_op.cpp485
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_comp_op.hpp172
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_create_index.cpp124
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_create_index.hpp203
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_create_row.cpp162
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_create_row.hpp99
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_create_table.cpp137
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_create_table.hpp178
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_data_type.cpp44
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_data_type.hpp49
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_ddl.cpp37
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_ddl.hpp63
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_column.cpp104
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_column.hpp150
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.cpp51
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.hpp65
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_row.cpp54
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_row.hpp72
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_delete.cpp205
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_delete.hpp69
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_delete_index.cpp164
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_delete_index.hpp156
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.cpp162
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.hpp152
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_delete_scan.cpp110
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_delete_scan.hpp130
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_dml.cpp51
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_dml.hpp67
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_dml_column.cpp47
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_dml_column.hpp46
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_dml_row.cpp56
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_dml_row.hpp76
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_drop_index.cpp87
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_drop_index.hpp136
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_drop_table.cpp87
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_drop_table.hpp124
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr.cpp79
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr.hpp219
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_column.cpp160
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_column.hpp120
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_const.cpp138
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_const.hpp120
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_conv.cpp273
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_conv.hpp141
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_func.cpp401
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_func.hpp193
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_op.cpp424
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_op.hpp166
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_param.cpp279
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_param.hpp136
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_row.cpp204
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_expr_row.hpp272
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_idx_column.cpp49
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_idx_column.hpp50
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_insert.cpp253
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_insert.hpp229
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_pred.cpp70
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_pred.hpp172
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_pred_op.cpp188
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_pred_op.hpp158
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query.cpp299
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query.hpp155
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_count.cpp177
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_count.hpp162
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_distinct.cpp204
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_distinct.hpp165
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_filter.cpp161
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_filter.hpp162
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_group.cpp301
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_group.hpp221
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_index.cpp186
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_index.hpp160
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_join.cpp192
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_join.hpp159
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_lookup.cpp184
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_lookup.hpp155
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_project.cpp184
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_project.hpp178
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_range.cpp211
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_range.hpp186
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_repeat.cpp109
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_repeat.hpp133
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_scan.cpp177
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_scan.hpp174
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_sort.cpp239
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_sort.hpp208
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_sys.cpp130
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_query_sys.hpp148
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_root.cpp307
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_root.hpp162
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_select.cpp406
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_select.hpp132
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_set_row.cpp44
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_set_row.hpp76
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_stmt.cpp49
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_stmt.hpp76
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_table.cpp254
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_table.hpp202
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_table_list.cpp53
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_table_list.hpp73
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_update.cpp246
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_update.hpp102
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_update_index.cpp196
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_update_index.hpp171
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_update_lookup.cpp194
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_update_lookup.hpp167
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_update_scan.cpp146
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Code_update_scan.hpp160
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/Makefile104
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/SimpleGram.ypp1649
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/SimpleParser.cpp96
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/SimpleParser.hpp161
-rw-r--r--storage/ndb/src/old_files/client/odbc/codegen/SimpleScan.lpp243
119 files changed, 20153 insertions, 0 deletions
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/CodeGen.cpp b/storage/ndb/src/old_files/client/odbc/codegen/CodeGen.cpp
new file mode 100644
index 00000000000..6be78b62bd9
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/CodeGen.cpp
@@ -0,0 +1,229 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include <common/CodeTree.hpp>
+#include <executor/Executor.hpp>
+#include "CodeGen.hpp"
+#include "Code_root.hpp"
+
+#include <FlexLexer.h>
+#include "SimpleParser.hpp"
+
+void
+CodeGen::prepare(Ctx& ctx)
+{
+ parse(ctx);
+ if (! ctx.ok())
+ return;
+ analyze(ctx);
+ if (! ctx.ok())
+ return;
+ describe(ctx);
+}
+
+void
+CodeGen::execute(Ctx& ctx)
+{
+ DescArea& ipd = m_stmtArea.descArea(Desc_usage_IPD);
+ if (m_stmtArea.m_unbound) {
+ analyze(ctx);
+ if (! ctx.ok())
+ return;
+ describe(ctx);
+ if (! ctx.ok())
+ return;
+ if (m_stmtArea.m_unbound) {
+ ctx.pushStatus(Sqlstate::_HY010, Error::Gen, "%u input parameters have unbound SQL type", m_stmtArea.m_unbound);
+ return;
+ }
+ ipd.setBound(true);
+ }
+ if (! ipd.isBound()) {
+ ctx_log2(("IPD changed between executes - reanalyze"));
+ // jdbc can change parameter length at each execute
+ analyze(ctx);
+ if (! ctx.ok())
+ return;
+ describe(ctx);
+ if (! ctx.ok())
+ return;
+ freeExec(ctx);
+ codegen(ctx);
+ if (! ctx.ok())
+ return;
+ alloc(ctx);
+ if (! ctx.ok())
+ return;
+ ipd.setBound(true);
+ }
+ if (m_stmtArea.m_execTree == 0) {
+ codegen(ctx);
+ if (! ctx.ok())
+ return;
+ alloc(ctx);
+ if (! ctx.ok())
+ return;
+ }
+ Executor executor(m_stmtArea);
+ executor.execute(ctx);
+}
+
+void
+CodeGen::fetch(Ctx& ctx)
+{
+ // XXX parameter types are not checked any more
+ ctx_assert(! m_stmtArea.m_unbound);
+ Executor executor(m_stmtArea);
+ executor.fetch(ctx);
+}
+
+void
+CodeGen::parse(Ctx& ctx)
+{
+ Plan_root* planRoot = new Plan_root(m_stmtArea);
+ SimpleParser simpleParser(ctx, m_stmtArea, planRoot);
+ simpleParser.yyparse();
+ if (! ctx.ok())
+ return;
+ planRoot->m_paramList.resize(1 + simpleParser.paramNumber());
+ ctx_log2(("CodeGen: parse done - plan tree follows"));
+ if (ctx.logLevel() >= 2)
+ planRoot->print(ctx);
+ m_stmtArea.m_planTree = planRoot;
+}
+
+void
+CodeGen::analyze(Ctx& ctx)
+{
+ Plan_root* planRoot = static_cast<Plan_root*>(m_stmtArea.m_planTree);
+ ctx_assert(planRoot != 0);
+ Plan_base::Ctl ctl(0);
+ planRoot->analyze(ctx, ctl); // returns itself
+ if (! ctx.ok())
+ return;
+ ctx_log2(("CodeGen: analyze done - plan tree follows"));
+ if (ctx.logLevel() >= 2)
+ planRoot->print(ctx);
+}
+
+void
+CodeGen::describe(Ctx& ctx)
+{
+ Plan_root* planRoot = static_cast<Plan_root*>(m_stmtArea.m_planTree);
+ ctx_assert(planRoot != 0);
+ planRoot->describe(ctx);
+ ctx_log2(("CodeGen: describe done"));
+}
+
+void
+CodeGen::codegen(Ctx& ctx)
+{
+ Plan_root* planRoot = static_cast<Plan_root*>(m_stmtArea.m_planTree);
+ ctx_assert(planRoot != 0);
+ Plan_base::Ctl ctl(0);
+ Exec_root* execRoot = static_cast<Exec_root*>(planRoot->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return;
+ ctx_assert(execRoot != 0);
+ ctx_log2(("CodeGen: codegen done - code tree follows"));
+ if (ctx.logLevel() >= 2)
+ execRoot->print(ctx);
+ m_stmtArea.m_execTree = execRoot;
+}
+
+void
+CodeGen::alloc(Ctx& ctx)
+{
+ Exec_root* execRoot = static_cast<Exec_root*>(m_stmtArea.m_execTree);
+ ctx_assert(execRoot != 0);
+ Exec_base::Ctl ctl(0);
+ execRoot->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ ctx_log2(("CodeGen: alloc done"));
+}
+
+void
+CodeGen::close(Ctx& ctx)
+{
+ Exec_root* execRoot = static_cast<Exec_root*>(m_stmtArea.m_execTree);
+ if (execRoot != 0) {
+ execRoot->close(ctx);
+ ctx_log2(("CodeGen: close done"));
+ }
+}
+
+void
+CodeGen::free(Ctx& ctx)
+{
+ freePlan(ctx);
+ freeExec(ctx);
+}
+
+void
+CodeGen::freePlan(Ctx & ctx)
+{
+ if (m_stmtArea.m_planTree != 0) {
+ Plan_root* planRoot = static_cast<Plan_root*>(m_stmtArea.m_planTree);
+ ctx_assert(planRoot != 0);
+ unsigned count = 1 + planRoot->m_nodeList.size();
+ planRoot->freeNodeList();
+ delete planRoot;
+ m_stmtArea.m_planTree = 0;
+ ctx_log3(("CodeGen: freed %u plan tree nodes", count));
+ }
+}
+
+void
+CodeGen::freeExec(Ctx & ctx)
+{
+ if (m_stmtArea.m_execTree != 0) {
+ Exec_root* execRoot = static_cast<Exec_root*>(m_stmtArea.m_execTree);
+ ctx_assert(execRoot != 0);
+ unsigned count = 1 + execRoot->m_nodeList.size();
+ execRoot->freeNodeList();
+ delete execRoot;
+ m_stmtArea.m_execTree = 0;
+ ctx_log3(("CodeGen: freed %u exec tree nodes", count));
+ }
+}
+
+// odbc support
+
+void
+CodeGen::sqlGetData(Ctx& ctx, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValue, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_Ind)
+{
+ Exec_root* execRoot = static_cast<Exec_root*>(m_stmtArea.m_execTree);
+ ctx_assert(execRoot != 0);
+ execRoot->sqlGetData(ctx, columnNumber, targetType, targetValue, bufferLength, strlen_or_Ind);
+}
+
+void
+CodeGen::sqlParamData(Ctx& ctx, SQLPOINTER* value)
+{
+ Exec_root* execRoot = static_cast<Exec_root*>(m_stmtArea.m_execTree);
+ ctx_assert(execRoot != 0);
+ execRoot->sqlParamData(ctx, value);
+}
+
+void
+CodeGen::sqlPutData(Ctx& ctx, SQLPOINTER data, SQLINTEGER strlen_or_Ind)
+{
+ Exec_root* execRoot = static_cast<Exec_root*>(m_stmtArea.m_execTree);
+ ctx_assert(execRoot != 0);
+ execRoot->sqlPutData(ctx, data, strlen_or_Ind);
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/CodeGen.hpp b/storage/ndb/src/old_files/client/odbc/codegen/CodeGen.hpp
new file mode 100644
index 00000000000..ae61dab0c2a
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/CodeGen.hpp
@@ -0,0 +1,69 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_CodeGen_hpp
+#define ODBC_CODEGEN_CodeGen_hpp
+
+#include <common/common.hpp>
+
+class StmtArea;
+class SqlField;
+class ExtField;
+
+/**
+ * @class CodeGen
+ * @brief Compiles SQL text into ExecTree::Code
+ */
+class CodeGen {
+public:
+ CodeGen(StmtArea& stmtArea);
+ ~CodeGen();
+ // parse and analyze SQL statement
+ void prepare(Ctx& ctx);
+ // these are passed to Executor
+ void execute(Ctx& ctx);
+ void fetch(Ctx& ctx);
+ // close statement (mainly scan)
+ void close(Ctx& ctx);
+ // free data structures
+ void free(Ctx& ctx);
+ // odbc support
+ void sqlGetData(Ctx& ctx, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValue, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_Ind);
+ void sqlParamData(Ctx& ctx, SQLPOINTER* value);
+ void sqlPutData(Ctx& ctx, SQLPOINTER data, SQLINTEGER strlen_or_Ind);
+private:
+ void parse(Ctx& ctx);
+ void analyze(Ctx& ctx);
+ void describe(Ctx& ctx);
+ void codegen(Ctx& ctx);
+ void alloc(Ctx& ctx);
+ void freePlan(Ctx& ctx);
+ void freeExec(Ctx& ctx);
+ StmtArea& m_stmtArea;
+};
+
+inline
+CodeGen::CodeGen(StmtArea& stmtArea) :
+ m_stmtArea(stmtArea)
+{
+}
+
+inline
+CodeGen::~CodeGen()
+{
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_base.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_base.cpp
new file mode 100644
index 00000000000..dc02e071156
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_base.cpp
@@ -0,0 +1,167 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include "Code_base.hpp"
+#include "Code_root.hpp"
+
+// Plan_base
+
+Plan_base::~Plan_base()
+{
+}
+
+StmtArea&
+Plan_base::stmtArea() const
+{
+ ctx_assert(m_root != 0);
+ return m_root->m_stmtArea;
+}
+
+DescArea&
+Plan_base::descArea(DescUsage u) const
+{
+ return stmtArea().descArea(u);
+}
+
+ConnArea&
+Plan_base::connArea() const
+{
+ return stmtArea().connArea();
+}
+
+DictCatalog&
+Plan_base::dictCatalog() const
+{
+ return connArea().dictCatalog();
+}
+
+DictSchema&
+Plan_base::dictSchema() const
+{
+ return connArea().dictSchema();
+}
+
+Ndb*
+Plan_base::ndbObject() const
+{
+ Ndb* ndb = connArea().ndbObject();
+ ctx_assert(ndb != 0);
+ return ndb;
+}
+
+NdbSchemaCon*
+Plan_base::ndbSchemaCon() const
+{
+ NdbSchemaCon* ndbSchemaCon = connArea().ndbSchemaCon();
+ ctx_assert(ndbSchemaCon != 0);
+ return ndbSchemaCon;
+}
+
+NdbConnection*
+Plan_base::ndbConnection() const
+{
+ NdbConnection* ndbConnection = connArea().ndbConnection();
+ ctx_assert(ndbConnection != 0);
+ return ndbConnection;
+}
+
+void
+Plan_base::printList(Ctx& ctx, Plan_base* a[], unsigned n)
+{
+ for (unsigned i = 0; i < n; i++) {
+ if (a[i] == 0)
+ ctx.print(" -");
+ else
+ a[i]->print(ctx);
+ }
+}
+
+// Exec_base
+
+Exec_base::Code::~Code()
+{
+}
+
+Exec_base::Data::~Data()
+{
+}
+
+Exec_base::~Exec_base()
+{
+ delete m_code; // remove when code becomes shared
+ m_code = 0;
+ delete m_data;
+ m_data = 0;
+}
+
+StmtArea&
+Exec_base::stmtArea() const
+{
+ ctx_assert(m_root != 0);
+ return m_root->m_stmtArea;
+}
+
+DescArea&
+Exec_base::descArea(DescUsage u) const
+{
+ return stmtArea().descArea(u);
+}
+
+ConnArea&
+Exec_base::connArea() const
+{
+ return stmtArea().connArea();
+}
+
+DictSchema&
+Exec_base::dictSchema() const
+{
+ return connArea().dictSchema();
+}
+
+Ndb*
+Exec_base::ndbObject() const
+{
+ Ndb* ndb = connArea().ndbObject();
+ ctx_assert(ndb != 0);
+ return ndb;
+}
+
+NdbSchemaCon*
+Exec_base::ndbSchemaCon() const
+{
+ NdbSchemaCon* ndbSchemaCon = connArea().ndbSchemaCon();
+ ctx_assert(ndbSchemaCon != 0);
+ return ndbSchemaCon;
+}
+
+NdbConnection*
+Exec_base::ndbConnection() const
+{
+ NdbConnection* ndbConnection = connArea().ndbConnection();
+ ctx_assert(ndbConnection != 0);
+ return ndbConnection;
+}
+
+void
+Exec_base::printList(Ctx& ctx, Exec_base* a[], unsigned n)
+{
+ for (unsigned i = 0; i < n; i++) {
+ ctx_assert(a[i] != 0);
+ a[i]->print(ctx);
+ }
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_base.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_base.hpp
new file mode 100644
index 00000000000..c67c0ca7adb
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_base.hpp
@@ -0,0 +1,237 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_base_hpp
+#define ODBC_CODEGEN_Code_base_hpp
+
+#include <set>
+#include <list>
+#include <vector>
+#include <common/common.hpp>
+#include <common/CodeTree.hpp>
+#include <common/DescArea.hpp>
+
+class Ctx;
+class ConnArea;
+class StmtArea;
+class DescArea;
+class DictCatalog;
+class DictSchema;
+class ResultArea;
+class ResultSet;
+class SpecRow;
+class Ndb;
+class NdbSchemaCon;
+class NdbConnection;
+class NdbOperation;
+class NdbScanFilter;
+
+class Plan_root;
+class Plan_table;
+class Plan_column;
+class Plan_expr;
+class Plan_expr_param;
+class Plan_pred;
+class Plan_dml_row;
+class Plan_dml_column;
+class Plan_ddl_column;
+class Plan_ddl_constr;
+class Plan_idx_column;
+class Exec_root;
+class Exec_base;
+class Exec_query;
+class Exec_expr;
+class Exec_expr_row;
+class Exec_expr_param;
+
+/**
+ * @class Plan_base
+ * @brief Base class for plan trees
+ */
+class Plan_base : public PlanTree {
+public:
+ Plan_base(Plan_root* root);
+ virtual ~Plan_base() = 0;
+ // get references to StmtArea via Plan_root
+ StmtArea& stmtArea() const;
+ DescArea& descArea(DescUsage u) const;
+ ConnArea& connArea() const;
+ // catalogs
+ DictCatalog& dictCatalog() const;
+ DictSchema& dictSchema() const;
+ // ndb
+ Ndb* ndbObject() const;
+ NdbSchemaCon* ndbSchemaCon() const;
+ NdbConnection* ndbConnection() const;
+ // containers for Plan classes
+ typedef std::vector<Plan_table*> TableVector;
+ typedef std::vector<Plan_column*> ColumnVector;
+ typedef std::vector<Plan_dml_column*> DmlColumnVector;
+ typedef std::vector<Plan_ddl_column*> DdlColumnVector;
+ typedef std::vector<Plan_ddl_constr*> DdlConstrVector;
+ typedef std::vector<Plan_idx_column*> IdxColumnVector;
+ typedef std::vector<Plan_expr*> ExprVector;
+ typedef std::list<Plan_expr*> ExprList;
+ typedef std::vector<ExprList> ExprListVector;
+ typedef std::list<Plan_pred*> PredList;
+ typedef std::set<Plan_table*> TableSet;
+ typedef std::vector<Plan_expr_param*> ParamVector;
+ // control area on the stack XXX needs to be designed
+ struct Ctl {
+ Ctl(Ctl* up);
+ Ctl* m_up; // up the stack
+ // analyze
+ TableVector m_tableList; // resolve column names
+ bool m_topand; // in top-level where clause
+ bool m_extra; // anything but single pk=expr
+ bool m_aggrok; // aggregate allowed
+ bool m_aggrin; // within aggregate args
+ bool m_const; // only constants in set clause
+ PredList m_topcomp; // top level comparisons
+ Plan_dml_row *m_dmlRow; // row type to convert to
+ Plan_table* m_topTable; // top level table for interpreted progs
+ bool m_having; // in having-predicate
+ // codegen
+ Exec_root* m_execRoot; // root of Exec tree
+ const Exec_query* m_execQuery; // pass to column
+ };
+ // semantic analysis and optimization
+ virtual Plan_base* analyze(Ctx& ctx, Ctl& ctl) = 0;
+ // generate "executable" code
+ virtual Exec_base* codegen(Ctx& ctx, Ctl& ctl) = 0;
+ // misc
+ virtual void print(Ctx& ctx) = 0;
+protected:
+ Plan_root* m_root;
+ void printList(Ctx& ctx, Plan_base* a[], unsigned n);
+};
+
+inline
+Plan_base::Plan_base(Plan_root* root) :
+ m_root(root)
+{
+ ctx_assert(m_root != 0);
+}
+
+inline
+Plan_base::Ctl::Ctl(Ctl* up) :
+ m_up(up),
+ m_tableList(1), // 1-based
+ m_topand(false),
+ m_extra(false),
+ m_aggrok(false),
+ m_aggrin(false),
+ m_dmlRow(0),
+ m_topTable(0),
+ m_having(false),
+ m_execRoot(0),
+ m_execQuery(0)
+{
+}
+
+/**
+ * @class Exec_base
+ * @brief Base class for exec trees
+ */
+class Exec_base : public ExecTree {
+public:
+ class Code : public ExecTree::Code {
+ public:
+ virtual ~Code() = 0;
+ };
+ class Data : public ExecTree::Data {
+ public:
+ virtual ~Data() = 0;
+ };
+ Exec_base(Exec_root* root);
+ virtual ~Exec_base() = 0;
+ // get references to StmtArea via Exec_root
+ virtual StmtArea& stmtArea() const;
+ DescArea& descArea(DescUsage u) const;
+ ConnArea& connArea() const;
+ // catalogs
+ DictSchema& dictSchema() const;
+ // ndb
+ Ndb* ndbObject() const;
+ NdbSchemaCon* ndbSchemaCon() const;
+ NdbConnection* ndbConnection() const;
+ // containers for Exec classes
+ typedef std::vector<Exec_expr*> ExprVector;
+ typedef std::vector<Exec_expr_param*> ParamVector;
+ // control area on the stack
+ struct Ctl {
+ Ctl(Ctl* up);
+ Ctl* m_up; // up the stack
+ const Exec_query* m_query; // pass Data
+ ExprVector m_exprList; // pass Data
+ NdbOperation* m_scanOp; // scan operation
+ bool m_postEval; // for rownum
+ unsigned m_groupIndex; // for group by
+ bool m_groupInit; // first in group
+ Exec_expr_row* m_sortRow; // from sort to group by
+ NdbScanFilter* m_scanFilter; // scan filter
+ };
+ // allocate and deallocate Data instances
+ virtual void alloc(Ctx& ctx, Ctl& ctl) = 0;
+ virtual void close(Ctx& ctx) = 0;
+ // set Code and Data
+ void setCode(const Code& code);
+ void setData(Data& data);
+ // misc
+ virtual void print(Ctx& ctx) = 0;
+protected:
+ const Code* m_code;
+ Data* m_data;
+ Exec_root* m_root;
+ void printList(Ctx& ctx, Exec_base* a[], unsigned n);
+};
+
+inline
+Exec_base::Exec_base(Exec_root* root) :
+ m_code(0),
+ m_data(0),
+ m_root(root)
+{
+ ctx_assert(m_root != 0);
+}
+
+inline void
+Exec_base::setCode(const Code& code)
+{
+ ctx_assert(m_code == 0);
+ m_code = &code;
+}
+
+inline void
+Exec_base::setData(Data& data)
+{
+ ctx_assert(m_data == 0);
+ m_data = &data;
+}
+
+inline
+Exec_base::Ctl::Ctl(Ctl* up) :
+ m_up(up),
+ m_scanOp(0),
+ m_postEval(false),
+ m_groupIndex(0),
+ m_groupInit(false),
+ m_sortRow(0),
+ m_scanFilter(0)
+{
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_column.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_column.cpp
new file mode 100644
index 00000000000..c4c0480a5e7
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_column.cpp
@@ -0,0 +1,72 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NdbApi.hpp>
+#include <common/StmtArea.hpp>
+#include <dictionary/DictSchema.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_column.hpp"
+#include "Code_table_list.hpp"
+#include "Code_table.hpp"
+
+// Plan_column
+
+Plan_column::~Plan_column()
+{
+}
+
+void
+Plan_column::analyzeColumn(Ctx& ctx, Plan_base::Ctl& ctl)
+{
+ if (m_resTable != 0) // done on previous pass
+ return;
+ if (! (ctl.m_tableList.size() > 1)) {
+ ctx.pushStatus(Sqlstate::_42000, Error::Gen, "column %s not allowed here", getPrintName());
+ return;
+ }
+ unsigned resCount = 0;
+ for (unsigned i = 1; i < ctl.m_tableList.size(); i++) {
+ Plan_table* table = ctl.m_tableList[i];
+ ctx_assert(table != 0);
+ int ret = table->resolveColumn(ctx, this);
+ if (ret < 0)
+ return;
+ if (ret)
+ resCount++;
+ }
+ if (resCount == 0) {
+ // XXX try to strip "schema name" from table name
+ for (unsigned i = 1; i < ctl.m_tableList.size(); i++) {
+ Plan_table* table = ctl.m_tableList[i];
+ ctx_assert(table != 0);
+ int ret = table->resolveColumn(ctx, this, true);
+ if (ret < 0)
+ return;
+ if (ret)
+ resCount++;
+ }
+ }
+ if (resCount == 0) {
+ ctx.pushStatus(Sqlstate::_42S22, Error::Gen, "column %s not found", getPrintName());
+ return;
+ }
+ if (resCount > 1) {
+ ctx.pushStatus(Error::Gen, "column %s is ambiguous", getPrintName());
+ return;
+ }
+ // copy SQL type
+ m_sqlType = dictColumn().sqlType();
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_column.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_column.hpp
new file mode 100644
index 00000000000..af0dcea690d
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_column.hpp
@@ -0,0 +1,122 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_column_hpp
+#define ODBC_CODEGEN_Code_column_hpp
+
+#include <common/common.hpp>
+#include <common/DataType.hpp>
+#include "Code_base.hpp"
+
+class DictColumn;
+class Plan_table;
+
+/**
+ * @class Plan_column
+ * @brief Abstract base class for columns
+ */
+class Plan_column {
+public:
+ enum Type {
+ Type_expr = 1,
+ Type_dml = 2,
+ Type_ddl = 3, // new columns in create table
+ Type_idx = 4 // old columns in create index
+ };
+ Plan_column(Type type, const BaseString& name);
+ virtual ~Plan_column() = 0;
+ void analyzeColumn(Ctx& ctx, Plan_base::Ctl& ctl);
+ // attributes
+ const BaseString& getName() const;
+ const BaseString& getCname() const;
+ const char* getPrintName() const;
+ void setCname(const BaseString& cname);
+ const DictColumn& dictColumn() const;
+ const SqlType& sqlType() const;
+protected:
+ friend class Plan_table;
+ friend class Plan_comp_op;
+ Type m_type;
+ BaseString m_name;
+ BaseString m_cname;
+ BaseString m_printName;
+ DictColumn* m_dictColumn;
+ /**
+ * Resolve to table and operational position (for example
+ * column number in scan query).
+ */
+ Plan_table* m_resTable;
+ unsigned m_resPos;
+ SqlType m_sqlType;
+};
+
+inline
+Plan_column::Plan_column(Type type, const BaseString& name) :
+ m_type(type),
+ m_name(name),
+ m_printName(name),
+ m_dictColumn(0),
+ m_resTable(0),
+ m_resPos(0)
+{
+}
+
+inline const BaseString&
+Plan_column::getName() const
+{
+ return m_name;
+}
+
+inline const BaseString&
+Plan_column::getCname() const
+{
+ return m_cname;
+}
+
+inline const char*
+Plan_column::getPrintName() const
+{
+ return m_printName.c_str();
+}
+
+inline void
+Plan_column::setCname(const BaseString& cname)
+{
+ m_cname.assign(cname);
+ if (m_cname.empty())
+ m_printName.assign(m_name);
+ else {
+ m_printName.assign(m_cname);
+ m_printName.append(".");
+ m_printName.append(m_name);
+ }
+}
+
+inline const DictColumn&
+Plan_column::dictColumn() const
+{
+ ctx_assert(m_dictColumn != 0);
+ return *m_dictColumn;
+}
+
+inline const SqlType&
+Plan_column::sqlType() const
+{
+ ctx_assert(m_sqlType.type() != SqlType::Undef);
+ return m_sqlType;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_comp_op.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_comp_op.cpp
new file mode 100644
index 00000000000..7782ed1ea2a
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_comp_op.cpp
@@ -0,0 +1,485 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <dictionary/DictColumn.hpp>
+#include "Code_pred.hpp"
+#include "Code_comp_op.hpp"
+#include "Code_expr_conv.hpp"
+#include "Code_expr_column.hpp"
+#include "Code_table.hpp"
+#include "Code_root.hpp"
+
+// Comp_op
+
+const char*
+Comp_op::name() const
+{
+ switch (m_opcode) {
+ case Eq:
+ return "=";
+ case Noteq:
+ return "!=";
+ case Lt:
+ return "<";
+ case Lteq:
+ return "<=";
+ case Gt:
+ return ">";
+ case Gteq:
+ return ">=";
+ case Like:
+ return "like";
+ case Notlike:
+ return "not like";
+ case Isnull:
+ return "is null";
+ case Isnotnull:
+ return "is not null";
+ }
+ ctx_assert(false);
+ return "";
+}
+
+unsigned
+Comp_op::arity() const
+{
+ switch (m_opcode) {
+ case Eq:
+ case Noteq:
+ case Lt:
+ case Lteq:
+ case Gt:
+ case Gteq:
+ case Like:
+ case Notlike:
+ return 2;
+ case Isnull:
+ case Isnotnull:
+ return 1;
+ }
+ ctx_assert(false);
+ return 0;
+}
+
+// Plan_comp_op
+
+Plan_comp_op::~Plan_comp_op()
+{
+}
+
+Plan_base*
+Plan_comp_op::analyze(Ctx& ctx, Ctl& ctl)
+{
+ m_exec = 0;
+ const unsigned arity = m_op.arity();
+ // analyze operands
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_expr[i] != 0);
+ m_expr[i]->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ }
+ // for each operand, find type to convert to
+ SqlType con[1 + 2];
+ if (arity == 1) {
+ const SqlType& t1 = m_expr[1]->sqlType();
+ switch (t1.type()) {
+ case SqlType::Char:
+ case SqlType::Varchar:
+ case SqlType::Smallint:
+ case SqlType::Integer:
+ case SqlType::Bigint:
+ case SqlType::Real:
+ case SqlType::Double:
+ case SqlType::Datetime:
+ case SqlType::Null:
+ case SqlType::Unbound:
+ con[1] = t1;
+ break;
+ default:
+ break;
+ }
+ if (con[1].type() == SqlType::Undef) {
+ char b1[40];
+ t1.print(b1, sizeof(b1));
+ ctx.pushStatus(Error::Gen, "type mismatch in comparison: %s %s", b1, m_op.name());
+ return 0;
+ }
+ } else if (arity == 2) {
+ const SqlType& t1 = m_expr[1]->sqlType();
+ const SqlType& t2 = m_expr[2]->sqlType();
+ switch (t1.type()) {
+ case SqlType::Char:
+ switch (t2.type()) {
+ case SqlType::Char:
+ case SqlType::Varchar:
+ case SqlType::Null:
+ con[1] = t1;
+ con[2] = t2;
+ break;
+ case SqlType::Unbound:
+ con[1] = con[2] = t2;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SqlType::Varchar:
+ switch (t2.type()) {
+ case SqlType::Char:
+ case SqlType::Varchar:
+ case SqlType::Null:
+ con[1] = t1;
+ con[2] = t2;
+ break;
+ case SqlType::Unbound:
+ con[1] = con[2] = t2;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SqlType::Smallint:
+ case SqlType::Integer:
+ case SqlType::Bigint:
+ switch (t2.type()) {
+ case SqlType::Smallint:
+ case SqlType::Integer:
+ case SqlType::Bigint:
+ // conversion would mask primary key optimization
+ con[1] = t1;
+ con[2] = t2;
+ break;
+ case SqlType::Real:
+ case SqlType::Double:
+ con[1].setType(ctx, SqlType::Double);
+ con[2] = con[1];
+ break;
+ case SqlType::Null:
+ con[1] = t1;
+ con[2] = t2;
+ break;
+ case SqlType::Unbound:
+ con[1] = con[2] = t2;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SqlType::Real:
+ case SqlType::Double:
+ switch (t2.type()) {
+ case SqlType::Smallint:
+ case SqlType::Integer:
+ case SqlType::Bigint:
+ case SqlType::Real:
+ case SqlType::Double:
+ con[1].setType(ctx, SqlType::Double);
+ con[2] = con[1];
+ break;
+ case SqlType::Null:
+ con[1] = t1;
+ con[2] = t2;
+ break;
+ case SqlType::Unbound:
+ con[1] = con[2] = t2;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SqlType::Datetime:
+ switch (t2.type()) {
+ case SqlType::Datetime:
+ con[1] = t1;
+ con[2] = t2;
+ break;
+ case SqlType::Unbound:
+ con[1] = con[2] = t2;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SqlType::Null:
+ switch (t2.type()) {
+ case SqlType::Char:
+ case SqlType::Varchar:
+ case SqlType::Smallint:
+ case SqlType::Integer:
+ case SqlType::Bigint:
+ case SqlType::Real:
+ case SqlType::Double:
+ case SqlType::Datetime:
+ con[1] = t1;
+ con[2] = t2;
+ break;
+ case SqlType::Unbound:
+ con[1] = con[2] = t2;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SqlType::Unbound:
+ con[1] = con[2] = t1;
+ break;
+ default:
+ break;
+ }
+ if (con[1].type() == SqlType::Undef || con[2].type() == SqlType::Undef) {
+ char b1[40], b2[40];
+ t1.print(b1, sizeof(b1));
+ t2.print(b2, sizeof(b2));
+ ctx.pushStatus(Error::Gen, "type mismatch in comparison: %s %s %s", b1, m_op.name(), b2);
+ return 0;
+ }
+ } else {
+ ctx_assert(false);
+ return 0;
+ }
+ if (! ctx.ok())
+ return 0;
+ // insert required conversions
+ for (unsigned i = 1; i <= arity; i++) {
+ if (con[i].type() == SqlType::Unbound) {
+ continue;
+ }
+ Plan_expr_conv* exprConv = new Plan_expr_conv(m_root, con[i]);
+ m_root->saveNode(exprConv);
+ exprConv->setExpr(m_expr[i]);
+ m_expr[i] = static_cast<Plan_expr*>(exprConv->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_expr[i] != 0);
+ }
+ // look for column=expr
+ if (ctl.m_topand && m_op.m_opcode == Comp_op::Eq) {
+ ctx_assert(arity == 2);
+ for (unsigned i = 1, j = 2; i <= 2; i++, j--) {
+ if (m_expr[i]->type() != Plan_expr::TypeColumn)
+ continue;
+ Plan_expr_column* column = static_cast<Plan_expr_column*>(m_expr[i]);
+ if (! column->resolveEq(ctx, m_expr[j]))
+ ctl.m_extra = true;
+ }
+ } else {
+ ctl.m_extra = true;
+ }
+ // save top level comparison on list
+ if (ctl.m_topand) {
+ ctl.m_topcomp.push_back(this);
+ }
+ // table dependencies are union from operands
+ m_tableSet.clear();
+ for (unsigned i = 1; i <= arity; i++) {
+ const TableSet& ts = m_expr[i]->tableSet();
+ m_tableSet.insert(ts.begin(), ts.end());
+ }
+ // set of tables for which interpreter cannot be used
+ m_noInterp.clear();
+ // convenient
+#undef ustype
+#define ustype(b, n) (((b) ? 1 : 0) * 100 + (n))
+ if (arity == 1) {
+ for (unsigned i = 1; i <= 1; i++) {
+ const SqlType t1 = m_expr[i]->sqlType();
+ switch (m_op.m_opcode) {
+ case Comp_op::Isnull:
+ case Comp_op::Isnotnull:
+ if (m_expr[i]->type() == Plan_expr::TypeColumn) {
+ switch (ustype(t1.unSigned(), t1.type())) {
+ // all types accepted now
+ default:
+ {
+ Plan_expr_column* column = static_cast<Plan_expr_column*>(m_expr[i]);
+ ctx_assert(column->m_resTable != 0);
+ m_interpColumn[i] = column;
+ continue; // ok
+ }
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ const TableSet& ts = m_expr[i]->tableSet();
+ m_noInterp.insert(ts.begin(), ts.end());
+ }
+ } else if (arity == 2) {
+ for (unsigned i = 1, j = 2; i <= 2; i++, j--) {
+ const SqlType t1 = m_expr[i]->sqlType();
+ switch (m_op.m_opcode) {
+ case Comp_op::Like:
+ case Comp_op::Notlike:
+ if (i == 2) // col like val but not val like col
+ break;
+ /*FALLTHRU*/
+ case Comp_op::Eq:
+ case Comp_op::Noteq:
+ case Comp_op::Lt:
+ case Comp_op::Lteq:
+ case Comp_op::Gt:
+ case Comp_op::Gteq:
+ if (m_expr[i]->type() == Plan_expr::TypeColumn) {
+ switch (ustype(t1.unSigned(), t1.type())) {
+ case ustype(false, SqlType::Char):
+ case ustype(false, SqlType::Varchar):
+ case ustype(true, SqlType::Smallint):
+ case ustype(true, SqlType::Integer):
+ case ustype(true, SqlType::Bigint):
+ {
+ Plan_expr_column* column = static_cast<Plan_expr_column*>(m_expr[i]);
+ ctx_assert(column->m_resTable != 0);
+ const TableSet& ts = m_expr[j]->tableSet();
+ if (ts.find(column->m_resTable) == ts.end()) {
+ // candidate for column=const
+ m_interpColumn[i] = column;
+ continue; // ok
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ const TableSet& ts = m_expr[i]->tableSet();
+ m_noInterp.insert(ts.begin(), ts.end());
+ }
+ } else {
+ ctx_assert(false);
+ return 0;
+ }
+#undef ustype
+ return this;
+}
+
+Exec_base*
+Plan_comp_op::codegen(Ctx& ctx, Ctl& ctl)
+{
+ if (m_exec != 0)
+ return m_exec;
+ const unsigned arity = m_op.arity();
+ Exec_comp_op* exec = new Exec_comp_op(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ // create code for operands
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_expr[i] != 0);
+ Exec_expr* execExpr = static_cast<Exec_expr*>(m_expr[i]->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execExpr != 0);
+ exec->setExpr(i, execExpr);
+ }
+ // create the code
+ Exec_comp_op::Code& code = *new Exec_comp_op::Code(m_op);
+ // interpreted column=const
+ if (! ctl.m_having) {
+ ctx_assert(ctl.m_topTable != 0);
+ for (unsigned i = 1; i <= arity; i++) {
+ Plan_expr_column* column = m_interpColumn[i];
+ if (column == 0)
+ continue;
+ ctx_assert(column->m_resTable != 0);
+ if (column->m_resTable != ctl.m_topTable)
+ continue;
+ ctx_assert(code.m_interpColumn == 0);
+ code.m_interpColumn = i;
+ code.m_interpAttrId = column->dictColumn().getAttrId();
+ ctx_log2(("can use interpreter on %s", column->getPrintName()));
+ }
+ }
+ exec->setCode(code);
+ m_exec = exec;
+ return exec;
+}
+
+void
+Plan_comp_op::print(Ctx& ctx)
+{
+ ctx.print(" [%s", m_op.name());
+ Plan_base* a[] = { m_expr[1], m_expr[2] };
+ printList(ctx, a, m_op.arity());
+ ctx.print("]");
+}
+
+bool
+Plan_comp_op::isGroupBy(const Plan_expr_row* row) const
+{
+ const unsigned arity = m_op.arity();
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_expr[i] != 0);
+ if (! m_expr[i]->isGroupBy(row))
+ return false;
+ }
+ return true;
+}
+
+// Code_comp_op
+
+Exec_comp_op::Code::~Code()
+{
+}
+
+Exec_comp_op::Data::~Data()
+{
+}
+
+Exec_comp_op::~Exec_comp_op()
+{
+}
+
+void
+Exec_comp_op::alloc(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ // allocate subexpressions
+ unsigned arity = code.m_op.arity();
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_expr[i] != 0);
+ m_expr[i]->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ }
+ Data& data = *new Data;
+ setData(data);
+}
+
+void
+Exec_comp_op::close(Ctx& ctx)
+{
+ const Code& code = getCode();
+ unsigned arity = code.m_op.arity();
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_expr[i] != 0);
+ m_expr[i]->close(ctx);
+ }
+}
+
+void
+Exec_comp_op::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [%s", code.m_op.name());
+ Exec_base* a[] = { m_expr[1], m_expr[2] };
+ printList(ctx, a, code.m_op.arity());
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_comp_op.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_comp_op.hpp
new file mode 100644
index 00000000000..0585ab1dabf
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_comp_op.hpp
@@ -0,0 +1,172 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_comp_op_hpp
+#define ODBC_CODEGEN_Code_comp_op_hpp
+
+#include <common/common.hpp>
+#include <common/DataField.hpp>
+#include "Code_pred.hpp"
+#include "Code_expr.hpp"
+#include "Code_expr_column.hpp"
+
+/**
+ * @class Comp_op
+ * @brief Comparison operations
+ */
+struct Comp_op {
+ enum Opcode {
+ Eq = 1, // binary
+ Noteq,
+ Lt,
+ Lteq,
+ Gt,
+ Gteq,
+ Like,
+ Notlike,
+ Isnull, // unary
+ Isnotnull
+ };
+ Comp_op(Opcode opcode);
+ const char* name() const;
+ unsigned arity() const;
+ Opcode m_opcode;
+};
+
+inline
+Comp_op::Comp_op(Opcode opcode) :
+ m_opcode(opcode)
+{
+}
+
+/**
+ * @class Plan_comp_op
+ * @brief Comparison operator node in PlanTree
+ */
+class Plan_comp_op : public Plan_pred {
+public:
+ Plan_comp_op(Plan_root* root, Comp_op op);
+ virtual ~Plan_comp_op();
+ void setExpr(unsigned i, Plan_expr* expr);
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ virtual bool isGroupBy(const Plan_expr_row* row) const;
+protected:
+ Comp_op m_op;
+ Plan_expr* m_expr[1 + 2];
+ Plan_expr_column* m_interpColumn[1 + 2]; // candidates
+};
+
+inline
+Plan_comp_op::Plan_comp_op(Plan_root* root, Comp_op op) :
+ Plan_pred(root, TypeComp),
+ m_op(op)
+{
+ m_expr[0] = m_expr[1] = m_expr[2] = 0;
+ m_interpColumn[0] = m_interpColumn[1] = m_interpColumn[2] = 0;
+}
+
+inline void
+Plan_comp_op::setExpr(unsigned i, Plan_expr* expr)
+{
+ ctx_assert(1 <= i && i <= 2);
+ m_expr[i] = expr;
+}
+
+/**
+ * @class Exec_comp_op
+ * @brief Comparison operator node in ExecTree
+ */
+class Exec_comp_op : public Exec_pred {
+public:
+ class Code : public Exec_pred::Code {
+ public:
+ Code(Comp_op op);
+ virtual ~Code();
+ protected:
+ friend class Plan_comp_op;
+ friend class Exec_comp_op;
+ Comp_op m_op;
+ unsigned m_interpColumn; // 1 or 2 if interpreted column, 0 if both constant
+ NdbAttrId m_interpAttrId;
+ };
+ class Data : public Exec_pred::Data {
+ public:
+ Data();
+ virtual ~Data();
+ protected:
+ friend class Exec_comp_op;
+ };
+ Exec_comp_op(Exec_root* root);
+ virtual ~Exec_comp_op();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execInterp(Ctx& ctx, Ctl& ctl);
+ void evaluate(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setExpr(unsigned i, Exec_expr* expr);
+protected:
+ Exec_expr* m_expr[1 + 2];
+};
+
+inline
+Exec_comp_op::Code::Code(Comp_op op) :
+ m_op(op),
+ m_interpColumn(0),
+ m_interpAttrId((NdbAttrId)-1)
+{
+}
+
+inline
+Exec_comp_op::Data::Data()
+{
+}
+
+inline
+Exec_comp_op::Exec_comp_op(Exec_root* root) :
+ Exec_pred(root)
+{
+ m_expr[0] = m_expr[1] = m_expr[2] = 0;
+}
+
+// children
+
+inline const Exec_comp_op::Code&
+Exec_comp_op::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_comp_op::Data&
+Exec_comp_op::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_comp_op::setExpr(unsigned i, Exec_expr* expr)
+{
+ ctx_assert(1 <= i && i <= 2 && m_expr[i] == 0);
+ m_expr[i] = expr;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_create_index.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_create_index.cpp
new file mode 100644
index 00000000000..84f319338a4
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_create_index.cpp
@@ -0,0 +1,124 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include "Code_create_index.hpp"
+#include "Code_root.hpp"
+
+// Plan_create_index
+
+Plan_create_index::~Plan_create_index()
+{
+}
+
+Plan_base*
+Plan_create_index::analyze(Ctx& ctx, Ctl& ctl)
+{
+ stmtArea().stmtInfo().setName(Stmt_name_create_index);
+ // analyze the table
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ // analyze the columns
+ ctl.m_tableList.resize(1 + 1); // indexed from 1
+ ctl.m_tableList[1] = m_table;
+ for (unsigned i = 1, n = countColumn(); i <= n; i++) {
+ Plan_idx_column* column = getColumn(i);
+ column->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ }
+ return this;
+}
+
+void
+Plan_create_index::describe(Ctx& ctx)
+{
+ stmtArea().setFunction(ctx, "CREATE INDEX", SQL_DIAG_CREATE_INDEX);
+}
+
+Exec_base*
+Plan_create_index::codegen(Ctx& ctx, Ctl& ctl)
+{
+ Exec_create_index* exec = new Exec_create_index(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ const unsigned count = countColumn();
+ const char** attrList = new const char* [1 + count];
+ attrList[0] = 0; // unused
+ for (unsigned i = 1; i <= count; i++) {
+ Plan_idx_column* column = getColumn(i);
+ const char* cname = column->getName().c_str();
+ attrList[i] = strcpy(new char[strlen(cname) + 1], cname);
+ }
+ Exec_create_index::Code& code = *new Exec_create_index::Code(m_name, m_table->getName(), m_type, count, attrList);
+ exec->setCode(code);
+ code.m_fragmentType = m_fragmentType;
+ code.m_logging = m_logging;
+ return exec;
+}
+
+void
+Plan_create_index::print(Ctx& ctx)
+{
+ ctx.print(" [create_index name=%s table=%s type=%d", m_name.c_str(), m_table->getName().c_str(), (int)m_type);
+ ctx.print(" [");
+ for (unsigned i = 1; i <= countColumn(); i++) {
+ Plan_idx_column* column = getColumn(i);
+ if (i > 1)
+ ctx.print(" ");
+ column->print(ctx);
+ }
+ ctx.print("]");
+}
+
+// Exec_create_index
+
+Exec_create_index::Code::~Code()
+{
+ for (unsigned i = 1; i <= m_attrCount; i++) {
+ delete[] m_attrList[i];
+ m_attrList[i] = 0;
+ }
+ delete[] m_attrList;
+}
+
+Exec_create_index::Data::~Data()
+{
+}
+
+Exec_create_index::~Exec_create_index()
+{
+}
+
+void
+Exec_create_index::alloc(Ctx& ctx, Ctl& ctl)
+{
+ Data& data = *new Data;
+ setData(data);
+}
+
+void
+Exec_create_index::close(Ctx& ctx)
+{
+}
+
+void
+Exec_create_index::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [create_index %s]", code.m_tableName.c_str());
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_create_index.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_create_index.hpp
new file mode 100644
index 00000000000..ebd757e1118
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_create_index.hpp
@@ -0,0 +1,203 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_create_index_hpp
+#define ODBC_CODEGEN_Code_create_index_hpp
+
+#include <vector>
+#include <NdbApi.hpp>
+#include <common/common.hpp>
+#include "Code_ddl.hpp"
+#include "Code_table.hpp"
+#include "Code_idx_column.hpp"
+
+class DictTable;
+class DictColumn;
+
+/**
+ * @class Plan_create_index
+ * @brief Create table in PlanTree
+ */
+class Plan_create_index : public Plan_ddl {
+public:
+ Plan_create_index(Plan_root* root, const BaseString& name);
+ virtual ~Plan_create_index();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx & ctx);
+ void print(Ctx& ctx);
+ // attributes
+ const BaseString& getName() const;
+ // children
+ void setType(NdbDictionary::Object::Type type);
+ void setTable(Plan_table* table);
+ unsigned countColumn() const;
+ void addColumn(Plan_idx_column* column);
+ Plan_idx_column* getColumn(unsigned i) const;
+ void setFragmentType(NdbDictionary::Object::FragmentType fragmentType);
+ void setLogging(bool logging);
+protected:
+ BaseString m_name;
+ NdbDictionary::Object::Type m_type;
+ Plan_table* m_table;
+ IdxColumnVector m_columnList;
+ NdbDictionary::Object::FragmentType m_fragmentType;
+ bool m_logging;
+};
+
+inline
+Plan_create_index::Plan_create_index(Plan_root* root, const BaseString& name) :
+ Plan_ddl(root),
+ m_name(name),
+ m_type(NdbDictionary::Object::TypeUndefined),
+ m_columnList(1),
+ m_fragmentType(NdbDictionary::Object::FragUndefined),
+ m_logging(true)
+{
+}
+
+inline const BaseString&
+Plan_create_index::getName() const
+{
+ return m_name;
+}
+
+// children
+
+inline void
+Plan_create_index::setType(NdbDictionary::Object::Type type)
+{
+ m_type = type;
+}
+
+inline void
+Plan_create_index::setTable(Plan_table* table)
+{
+ ctx_assert(table != 0);
+ m_table = table;
+}
+
+inline unsigned
+Plan_create_index::countColumn() const
+{
+ return m_columnList.size() - 1;
+}
+
+inline void
+Plan_create_index::addColumn(Plan_idx_column* column)
+{
+ ctx_assert(column != 0);
+ m_columnList.push_back(column);
+}
+
+inline Plan_idx_column*
+Plan_create_index::getColumn(unsigned i) const
+{
+ ctx_assert(1 <= i && i <= countColumn() && m_columnList[i] != 0);
+ return m_columnList[i];
+}
+
+inline void
+Plan_create_index::setFragmentType(NdbDictionary::Object::FragmentType fragmentType)
+{
+ m_fragmentType = fragmentType;
+}
+
+inline void
+Plan_create_index::setLogging(bool logging)
+{
+ m_logging = logging;
+}
+
+/**
+ * @class Exec_create_index
+ * @brief Create table in ExecTree
+ */
+class Exec_create_index : public Exec_ddl {
+public:
+ class Code : public Exec_ddl::Code {
+ public:
+ Code(const BaseString& indexName, const BaseString& tableName, NdbDictionary::Object::Type type, unsigned attrCount, const char** attrList);
+ virtual ~Code();
+ protected:
+ friend class Plan_create_index;
+ friend class Exec_create_index;
+ const BaseString m_indexName;
+ const BaseString m_tableName;
+ NdbDictionary::Object::Type m_type;
+ const unsigned m_attrCount;
+ const char** m_attrList;
+ NdbDictionary::Object::FragmentType m_fragmentType;
+ bool m_logging;
+ };
+ class Data : public Exec_ddl::Data {
+ public:
+ Data();
+ virtual ~Data();
+ protected:
+ friend class Exec_create_index;
+ };
+ Exec_create_index(Exec_root* root);
+ virtual ~Exec_create_index();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execute(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+};
+
+inline
+Exec_create_index::Code::Code(const BaseString& indexName, const BaseString& tableName, NdbDictionary::Object::Type type, unsigned attrCount, const char** attrList) :
+ m_indexName(indexName),
+ m_tableName(tableName),
+ m_type(type),
+ m_attrCount(attrCount),
+ m_attrList(attrList),
+ m_fragmentType(NdbDictionary::Object::FragUndefined),
+ m_logging(true)
+{
+}
+
+inline
+Exec_create_index::Data::Data()
+{
+}
+
+inline
+Exec_create_index::Exec_create_index(Exec_root* root) :
+ Exec_ddl(root)
+{
+}
+
+// children
+
+inline const Exec_create_index::Code&
+Exec_create_index::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_create_index::Data&
+Exec_create_index::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_create_row.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_create_row.cpp
new file mode 100644
index 00000000000..5b90b658ed7
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_create_row.cpp
@@ -0,0 +1,162 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_create_row.hpp"
+#include "Code_root.hpp"
+
+Plan_create_row::~Plan_create_row()
+{
+}
+
+Plan_base*
+Plan_create_row::analyze(Ctx& ctx, Ctl& ctl)
+{
+ // check for duplicate column name
+ for (unsigned i = 1, n = countColumn(); i < n; i++) {
+ const BaseString& a = getColumn(i)->getName();
+ for (unsigned i2 = i + 1; i2 <= n; i2++) {
+ const BaseString& a2 = getColumn(i2)->getName();
+ if (strcmp(a.c_str(), a2.c_str()) == 0) {
+ ctx.pushStatus(Error::Gen, "duplicate column %s", a.c_str());
+ return 0;
+ }
+ }
+ }
+ // move single-column primary key constraint to constraint list
+ for (unsigned i = 1, n = countColumn(); i <= n; i++) {
+ Plan_ddl_column* column = getColumn(i);
+ if (column->m_primaryKey) {
+ Plan_ddl_row* ddlRow = new Plan_ddl_row(m_root);
+ m_root->saveNode(ddlRow);
+ ddlRow->addColumn(column);
+ Plan_ddl_constr* constr = new Plan_ddl_constr(m_root);
+ m_root->saveNode(constr);
+ constr->setRow(ddlRow);
+ addConstr(constr);
+ column->m_primaryKey = false; // will be set again
+ }
+ }
+ // check primary key constraints
+ if (countConstr() < 1) {
+ ctx.pushStatus(Error::Gen, "table must have a primary key");
+ return 0;
+ }
+ if (countConstr() > 1) {
+ ctx.pushStatus(Error::Gen, "table can have only one primary key");
+ return 0;
+ }
+ Plan_ddl_row* ddlRow = getConstr(1)->getRow();
+ for (unsigned i = 1, n = ddlRow->countColumn(); i <= n; i++) {
+ Plan_ddl_column* column = ddlRow->getColumn(i);
+ const BaseString& a = column->getName();
+ bool found = false;
+ for (unsigned i2 = 1, n2 = countColumn(); i2 <= n2; i2++) {
+ Plan_ddl_column* column2 = getColumn(i2);
+ const BaseString& a2 = column2->getName();
+ if (strcmp(a.c_str(), a2.c_str()) != 0)
+ continue;
+ if (column2->getPrimaryKey()) {
+ ctx.pushStatus(Error::Gen, "duplicate primary key constraint on %s", a.c_str());
+ return 0;
+ }
+ column2->setPrimaryKey();
+ found = true;
+ break;
+ }
+ if (! found) {
+ ctx.pushStatus(Error::Gen, "undefined primary key column %s", a.c_str());
+ return 0;
+ }
+ }
+ // analyze column types
+ for (unsigned i = 1, n = countColumn(); i <= n; i++) {
+ getColumn(i)->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ }
+ // check TupleId
+ unsigned tupleId = 0;
+ for (unsigned i = 1, n = countColumn(); i <= n; i++) {
+ Plan_ddl_column* column = getColumn(i);
+ if (! column->getTupleId())
+ continue;
+ if (i != 1) {
+ ctx.pushStatus(Error::Gen, "tuple id column %u is not first column", i);
+ return 0;
+ }
+ if (tupleId != 0) { // cannot happen now since attr name is fixed
+ ctx.pushStatus(Error::Gen, "duplicate tuple id column %u", i);
+ return 0;
+ }
+ tupleId = i;
+ }
+ if (tupleId != 0) {
+ for (unsigned i = 1, n = countColumn(); i <= n; i++) {
+ Plan_ddl_column* column = getColumn(i);
+ if (i == tupleId)
+ continue;
+ if (! column->getPrimaryKey())
+ continue;
+ ctx.pushStatus(Error::Gen, "cannot have both tuple id and other primary key column %u", i);
+ return 0;
+ }
+ }
+ // check auto-increment
+ unsigned autoIncrement = 0;
+ for (unsigned i = 1, n = countColumn(); i <= n; i++) {
+ Plan_ddl_column* column = getColumn(i);
+ if (! column->getAutoIncrement())
+ continue;
+ if (autoIncrement != 0) {
+ ctx.pushStatus(Error::Gen, "duplicate auto-increment column %u", i);
+ return 0;
+ }
+ autoIncrement = i;
+ }
+ if (autoIncrement != 0) {
+ for (unsigned i = 1, n = countColumn(); i <= n; i++) {
+ Plan_ddl_column* column = getColumn(i);
+ if (i == autoIncrement)
+ continue;
+ if (! column->getPrimaryKey())
+ continue;
+ ctx.pushStatus(Error::Gen, "cannot have both auto-increment column and other primary key column %u", i);
+ return 0;
+ }
+ }
+ return this;
+}
+
+Exec_base*
+Plan_create_row::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_create_row::print(Ctx& ctx)
+{
+ ctx.print(" [create_row");
+ for (unsigned i = 1; i <= countColumn(); i++) {
+ Plan_base* a = m_columnList[i];
+ printList(ctx, &a, 1);
+ }
+ for (unsigned i = 1; i <= countConstr(); i++) {
+ Plan_base* a = m_constrList[i];
+ printList(ctx, &a, 1);
+ }
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_create_row.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_create_row.hpp
new file mode 100644
index 00000000000..f03455ff28e
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_create_row.hpp
@@ -0,0 +1,99 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_create_row_hpp
+#define ODBC_CODEGEN_Code_create_row_hpp
+
+#include <vector>
+#include <common/common.hpp>
+#include "Code_base.hpp"
+#include "Code_ddl_column.hpp"
+#include "Code_ddl_constr.hpp"
+
+/**
+ * @class Plan_create_row
+ * @brief Row of columns and constraints in create statement
+ */
+class Plan_create_row : public Plan_base {
+public:
+ Plan_create_row(Plan_root* root);
+ virtual ~Plan_create_row();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ unsigned countColumn() const;
+ void addColumn(Plan_ddl_column* column);
+ Plan_ddl_column* getColumn(unsigned i) const;
+ unsigned countConstr() const;
+ void addConstr(Plan_ddl_constr* constr);
+ Plan_ddl_constr* getConstr(unsigned i) const;
+protected:
+ DdlColumnVector m_columnList;
+ DdlConstrVector m_constrList;
+};
+
+inline
+Plan_create_row::Plan_create_row(Plan_root* root) :
+ Plan_base(root),
+ m_columnList(1),
+ m_constrList(1)
+{
+}
+
+// children
+
+inline unsigned
+Plan_create_row::countColumn() const
+{
+ return m_columnList.size() - 1;
+}
+
+inline void
+Plan_create_row::addColumn(Plan_ddl_column* column)
+{
+ ctx_assert(column != 0);
+ m_columnList.push_back(column);
+}
+
+inline Plan_ddl_column*
+Plan_create_row::getColumn(unsigned i) const
+{
+ ctx_assert(1 <= i && i <= m_columnList.size() && m_columnList[i] != 0);
+ return m_columnList[i];
+}
+
+inline unsigned
+Plan_create_row::countConstr() const
+{
+ return m_constrList.size() - 1;
+}
+
+inline void
+Plan_create_row::addConstr(Plan_ddl_constr* constr)
+{
+ ctx_assert(constr != 0);
+ m_constrList.push_back(constr);
+}
+
+inline Plan_ddl_constr*
+Plan_create_row::getConstr(unsigned i) const
+{
+ ctx_assert(1 <= i && i <= m_constrList.size() && m_constrList[i] != 0);
+ return m_constrList[i];
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_create_table.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_create_table.cpp
new file mode 100644
index 00000000000..14e4abbd7fe
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_create_table.cpp
@@ -0,0 +1,137 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include "Code_create_table.hpp"
+#include "Code_root.hpp"
+
+// Plan_create_table
+
+Plan_create_table::~Plan_create_table()
+{
+}
+
+Plan_base*
+Plan_create_table::analyze(Ctx& ctx, Ctl& ctl)
+{
+ stmtArea().stmtInfo().setName(Stmt_name_create_table);
+ // analyze the create row
+ ctx_assert(m_createRow != 0);
+ m_createRow->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+void
+Plan_create_table::describe(Ctx& ctx)
+{
+ stmtArea().setFunction(ctx, "CREATE TABLE", SQL_DIAG_CREATE_TABLE);
+}
+
+Exec_base*
+Plan_create_table::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_createRow != 0);
+ Exec_create_table* exec = new Exec_create_table(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ const unsigned count = m_createRow->countColumn();
+ Exec_create_table::Code::Attr* attrList = new Exec_create_table::Code::Attr[1 + count];
+ unsigned tupleId = 0;
+ unsigned autoIncrement = 0;
+ for (unsigned i = 1; i <= count; i++) {
+ Plan_ddl_column* column = m_createRow->getColumn(i);
+ Exec_create_table::Code::Attr& attr = attrList[i];
+ attr.m_attrName.assign(column->getName());
+ attr.m_sqlType = column->sqlType();
+ attr.m_tupleKey = column->getPrimaryKey();
+ attr.m_tupleId = column->getTupleId();
+ attr.m_autoIncrement = column->getAutoIncrement();
+ if (attr.m_tupleId)
+ tupleId = i;
+ if (attr.m_autoIncrement)
+ autoIncrement = i;
+ attr.m_defaultValue = 0;
+ Plan_expr* expr;
+ if ((expr = column->getDefaultValue()) != 0) {
+ Exec_expr* execExpr = static_cast<Exec_expr*>(expr->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execExpr != 0);
+ attr.m_defaultValue = execExpr;
+ }
+ }
+ Exec_create_table::Code& code = *new Exec_create_table::Code(m_name, count, attrList, tupleId, autoIncrement);
+ exec->setCode(code);
+ code.m_fragmentType = m_fragmentType;
+ code.m_logging = m_logging;
+ return exec;
+}
+
+void
+Plan_create_table::print(Ctx& ctx)
+{
+ ctx.print(" [create_table '%s'", m_name.c_str());
+ Plan_base* a[] = { m_createRow };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
+
+// Exec_create_table
+
+Exec_create_table::Code::~Code()
+{
+ delete[] m_attrList;
+}
+
+Exec_create_table::Data::~Data()
+{
+}
+
+Exec_create_table::~Exec_create_table()
+{
+}
+
+void
+Exec_create_table::alloc(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ for (unsigned i = 1; i <= code.m_attrCount; i++) {
+ const Code::Attr& attr = code.m_attrList[i];
+ if (attr.m_defaultValue != 0)
+ attr.m_defaultValue->alloc(ctx, ctl);
+ }
+ Data& data = *new Data;
+ setData(data);
+}
+
+void
+Exec_create_table::close(Ctx& ctx)
+{
+ const Code& code = getCode();
+ for (unsigned i = 1; i <= code.m_attrCount; i++) {
+ const Code::Attr& attr = code.m_attrList[i];
+ if (attr.m_defaultValue != 0)
+ attr.m_defaultValue->close(ctx);
+ }
+}
+
+void
+Exec_create_table::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [create_table %s]", code.m_tableName.c_str());
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_create_table.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_create_table.hpp
new file mode 100644
index 00000000000..cbb2189d8ce
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_create_table.hpp
@@ -0,0 +1,178 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_create_table_hpp
+#define ODBC_CODEGEN_Code_create_table_hpp
+
+#include <vector>
+#include <common/common.hpp>
+#include "Code_ddl.hpp"
+#include "Code_ddl_row.hpp"
+#include "Code_create_row.hpp"
+
+class DictTable;
+class DictColumn;
+
+/**
+ * @class Plan_create_table
+ * @brief Create table in PlanTree
+ */
+class Plan_create_table : public Plan_ddl {
+public:
+ Plan_create_table(Plan_root* root, const BaseString& name);
+ virtual ~Plan_create_table();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx & ctx);
+ void print(Ctx& ctx);
+ // attributes
+ const BaseString& getName() const;
+ // children
+ void setCreateRow(Plan_create_row* createRow);
+ void setFragmentType(NdbDictionary::Object::FragmentType fragmentType);
+ void setLogging(bool logging);
+protected:
+ BaseString m_name;
+ Plan_create_row* m_createRow;
+ NdbDictionary::Object::FragmentType m_fragmentType;
+ bool m_logging;
+};
+
+inline
+Plan_create_table::Plan_create_table(Plan_root* root, const BaseString& name) :
+ Plan_ddl(root),
+ m_name(name),
+ m_createRow(0),
+ m_fragmentType(NdbDictionary::Object::FragUndefined),
+ m_logging(true)
+{
+}
+
+inline const BaseString&
+Plan_create_table::getName() const
+{
+ return m_name;
+}
+
+// children
+
+inline void
+Plan_create_table::setCreateRow(Plan_create_row* createRow)
+{
+ ctx_assert(createRow != 0);
+ m_createRow = createRow;
+}
+
+inline void
+Plan_create_table::setFragmentType(NdbDictionary::Object::FragmentType fragmentType)
+{
+ m_fragmentType = fragmentType;
+}
+
+inline void
+Plan_create_table::setLogging(bool logging)
+{
+ m_logging = logging;
+}
+
+/**
+ * @class Exec_create_table
+ * @brief Create table in ExecTree
+ */
+class Exec_create_table : public Exec_ddl {
+public:
+ class Code : public Exec_ddl::Code {
+ public:
+ struct Attr {
+ Attr() : m_defaultValue(0) {}
+ BaseString m_attrName;
+ SqlType m_sqlType;
+ bool m_tupleKey;
+ bool m_tupleId;
+ bool m_autoIncrement;
+ Exec_expr* m_defaultValue;
+ };
+ Code(const BaseString& tableName, unsigned attrCount, const Attr* attrList, unsigned tupleId, unsigned autoIncrement);
+ virtual ~Code();
+ protected:
+ friend class Plan_create_table;
+ friend class Exec_create_table;
+ const BaseString m_tableName;
+ const unsigned m_attrCount;
+ const Attr* const m_attrList;
+ unsigned m_tupleId;
+ unsigned m_autoIncrement;
+ NdbDictionary::Object::FragmentType m_fragmentType;
+ bool m_logging;
+ };
+ class Data : public Exec_ddl::Data {
+ public:
+ Data();
+ virtual ~Data();
+ protected:
+ friend class Exec_create_table;
+ };
+ Exec_create_table(Exec_root* root);
+ virtual ~Exec_create_table();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execute(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+};
+
+inline
+Exec_create_table::Code::Code(const BaseString& tableName, unsigned attrCount, const Attr* attrList, unsigned tupleId, unsigned autoIncrement) :
+ m_tableName(tableName),
+ m_attrCount(attrCount),
+ m_attrList(attrList),
+ m_tupleId(tupleId),
+ m_autoIncrement(autoIncrement),
+ m_fragmentType(NdbDictionary::Object::FragUndefined),
+ m_logging(true)
+{
+}
+
+inline
+Exec_create_table::Data::Data()
+{
+}
+
+inline
+Exec_create_table::Exec_create_table(Exec_root* root) :
+ Exec_ddl(root)
+{
+}
+
+// children
+
+inline const Exec_create_table::Code&
+Exec_create_table::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_create_table::Data&
+Exec_create_table::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_data_type.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_data_type.cpp
new file mode 100644
index 00000000000..1ff0fcebcbe
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_data_type.cpp
@@ -0,0 +1,44 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NdbApi.hpp>
+#include <common/StmtArea.hpp>
+#include "Code_data_type.hpp"
+
+// Plan_data_type
+
+Plan_data_type::~Plan_data_type()
+{
+}
+
+Plan_base*
+Plan_data_type::analyze(Ctx& ctx, Ctl& ctl)
+{
+ return this;
+}
+
+Exec_base*
+Plan_data_type::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_data_type::print(Ctx& ctx)
+{
+ ctx.print(" [data_type]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_data_type.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_data_type.hpp
new file mode 100644
index 00000000000..735dc05014f
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_data_type.hpp
@@ -0,0 +1,49 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_data_type_hpp
+#define ODBC_CODEGEN_Code_data_type_hpp
+
+#include <common/common.hpp>
+#include <common/DataType.hpp>
+#include "Code_base.hpp"
+
+/**
+ * @class Plan_data_type
+ * @brief Data type in DDL statement
+ *
+ * This is pure plan node.
+ */
+class Plan_data_type : public Plan_base {
+public:
+ Plan_data_type(Plan_root* root, const SqlType& sqlType);
+ virtual ~Plan_data_type();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+private:
+ friend class Plan_ddl_column;
+ SqlType m_sqlType;
+};
+
+inline
+Plan_data_type::Plan_data_type(Plan_root* root, const SqlType& sqlType) :
+ Plan_base(root),
+ m_sqlType(sqlType)
+{
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl.cpp
new file mode 100644
index 00000000000..2ba4291a0e8
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl.cpp
@@ -0,0 +1,37 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_ddl.hpp"
+
+// Plan_ddl
+
+Plan_ddl::~Plan_ddl()
+{
+}
+
+// Exec_ddl
+
+Exec_ddl::Code::~Code()
+{
+}
+
+Exec_ddl::Data::~Data()
+{
+}
+
+Exec_ddl::~Exec_ddl()
+{
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl.hpp
new file mode 100644
index 00000000000..1ceca62d55d
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl.hpp
@@ -0,0 +1,63 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_ddl_hpp
+#define ODBC_CODEGEN_Code_ddl_hpp
+
+#include <common/common.hpp>
+#include "Code_stmt.hpp"
+
+/**
+ * @class Plan_ddl
+ * @brief Base class for DDL statements in PlanTree
+ */
+class Plan_ddl : public Plan_stmt {
+public:
+ Plan_ddl(Plan_root* root);
+ virtual ~Plan_ddl() = 0;
+};
+
+inline
+Plan_ddl::Plan_ddl(Plan_root* root) :
+ Plan_stmt(root)
+{
+}
+
+/**
+ * @class Exec_ddl
+ * @brief Base class for DDL statements in ExecTree
+ */
+class Exec_ddl : public Exec_stmt {
+public:
+ class Code : public Exec_stmt::Code {
+ public:
+ virtual ~Code() = 0;
+ };
+ class Data : public Exec_stmt::Data {
+ public:
+ virtual ~Data() = 0;
+ };
+ Exec_ddl(Exec_root* root);
+ virtual ~Exec_ddl() = 0;
+};
+
+inline
+Exec_ddl::Exec_ddl(Exec_root* root) :
+ Exec_stmt(root)
+{
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_column.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_column.cpp
new file mode 100644
index 00000000000..ee037e54c1f
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_column.cpp
@@ -0,0 +1,104 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NdbApi.hpp>
+#include <common/StmtArea.hpp>
+#include "Code_ddl_column.hpp"
+#include "Code_expr_conv.hpp"
+#include "Code_root.hpp"
+
+// Plan_ddl_column
+
+Plan_ddl_column::~Plan_ddl_column()
+{
+}
+
+Plan_base*
+Plan_ddl_column::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_type != 0);
+ if (! m_type->m_sqlType.nullable()) {
+ m_nullable = false;
+ }
+ m_sqlType = m_type->m_sqlType;
+ m_sqlType.nullable(m_nullable);
+ const BaseString& name = getName();
+ if (m_unSigned) {
+ switch (m_sqlType.type()) {
+ case SqlType::Smallint:
+ case SqlType::Integer:
+ case SqlType::Bigint:
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, "invalid unsigned qualifier on column %s", name.c_str());
+ return 0;
+ }
+ m_sqlType.unSigned(true);
+ }
+ if (strcmp(name.c_str(), "NDB$TID") == 0) {
+ if (! m_primaryKey) {
+ ctx.pushStatus(Error::Gen, "column %s must be a primary key", name.c_str());
+ return 0;
+ }
+ if (sqlType().type() != SqlType::Bigint || ! sqlType().unSigned()) {
+ ctx.pushStatus(Error::Gen, "tuple id %s must have type BIGINT UNSIGNED", name.c_str());
+ return 0;
+ }
+ setTupleId();
+ }
+ if (m_autoIncrement) {
+ if (! m_primaryKey) {
+ ctx.pushStatus(Error::Gen, "auto-increment column %s must be a primary key", name.c_str());
+ return 0;
+ }
+ if (sqlType().type() != SqlType::Smallint && sqlType().type() != SqlType::Integer && sqlType().type() != SqlType::Bigint) {
+ ctx.pushStatus(Error::Gen, "auto-increment column %s must have an integral type", name.c_str());
+ return 0;
+ }
+ }
+ if (m_defaultValue != 0) {
+ if (m_primaryKey) {
+ ctx.pushStatus(Sqlstate::_42000, Error::Gen, "default value not allowed on primary key column %s", name.c_str());
+ return 0;
+ }
+ m_defaultValue->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ // insert conversion node
+ Plan_expr_conv* exprConv = new Plan_expr_conv(m_root, sqlType());
+ m_root->saveNode(exprConv);
+ exprConv->setExpr(m_defaultValue);
+ Plan_expr* expr = static_cast<Plan_expr*>(exprConv->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(expr != 0);
+ m_defaultValue = expr;
+ }
+ return this;
+}
+
+Exec_base*
+Plan_ddl_column::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_ddl_column::print(Ctx& ctx)
+{
+ ctx.print(" [ddl_column %s key=%d id=%d]", getPrintName(), m_primaryKey, m_tupleId);
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_column.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_column.hpp
new file mode 100644
index 00000000000..7d089d37440
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_column.hpp
@@ -0,0 +1,150 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_ddl_column_hpp
+#define ODBC_CODEGEN_Code_ddl_column_hpp
+
+#include <common/common.hpp>
+#include "Code_column.hpp"
+#include "Code_data_type.hpp"
+#include "Code_expr.hpp"
+
+class DictColumn;
+class Plan_table;
+
+/**
+ * @class Plan_ddl_column
+ * @brief Column in DDL statement
+ */
+class Plan_ddl_column : public Plan_base, public Plan_column {
+public:
+ Plan_ddl_column(Plan_root* root, const BaseString& name);
+ virtual ~Plan_ddl_column();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // attributes
+ void setNotNull();
+ void setUnSigned();
+ void setPrimaryKey();
+ bool getPrimaryKey() const;
+ void setTupleId();
+ bool getTupleId() const;
+ void setAutoIncrement();
+ bool getAutoIncrement() const;
+ // children
+ void setType(Plan_data_type* type);
+ void setDefaultValue(Plan_expr* defaultValue);
+ Plan_expr* getDefaultValue() const;
+protected:
+ friend class Plan_create_row;
+ Plan_data_type* m_type;
+ Plan_expr* m_defaultValue;
+ bool m_nullable;
+ bool m_unSigned;
+ bool m_primaryKey;
+ bool m_tupleId;
+ bool m_autoIncrement;
+};
+
+inline
+Plan_ddl_column::Plan_ddl_column(Plan_root* root, const BaseString& name) :
+ Plan_base(root),
+ Plan_column(Type_ddl, name),
+ m_type(0),
+ m_defaultValue(0),
+ m_nullable(true),
+ m_unSigned(false),
+ m_primaryKey(false),
+ m_tupleId(false),
+ m_autoIncrement(false)
+{
+}
+
+inline void
+Plan_ddl_column::setNotNull()
+{
+ m_nullable = false;
+}
+
+inline void
+Plan_ddl_column::setUnSigned()
+{
+ m_unSigned = true;
+}
+
+inline void
+Plan_ddl_column::setPrimaryKey()
+{
+ m_nullable = false;
+ m_primaryKey = true;
+}
+
+inline bool
+Plan_ddl_column::getPrimaryKey() const
+{
+ return m_primaryKey;
+}
+
+inline void
+Plan_ddl_column::setTupleId()
+{
+ m_nullable = false;
+ m_tupleId = true;
+}
+
+inline bool
+Plan_ddl_column::getTupleId() const
+{
+ return m_tupleId;
+}
+
+inline void
+Plan_ddl_column::setAutoIncrement()
+{
+ m_nullable = false;
+ m_autoIncrement = true;
+}
+
+inline bool
+Plan_ddl_column::getAutoIncrement() const
+{
+ return m_autoIncrement;
+}
+
+// children
+
+inline void
+Plan_ddl_column::setType(Plan_data_type* type)
+{
+ ctx_assert(type != 0);
+ m_type = type;
+}
+
+inline void
+Plan_ddl_column::setDefaultValue(Plan_expr* defaultValue)
+{
+ ctx_assert(defaultValue != 0);
+ m_defaultValue = defaultValue;
+}
+
+inline Plan_expr*
+Plan_ddl_column::getDefaultValue() const
+{
+ return m_defaultValue;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.cpp
new file mode 100644
index 00000000000..78c23e38d97
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.cpp
@@ -0,0 +1,51 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NdbApi.hpp>
+#include <common/StmtArea.hpp>
+#include "Code_ddl_constr.hpp"
+
+// Plan_ddl_constr
+
+Plan_ddl_constr::~Plan_ddl_constr()
+{
+}
+
+Plan_base*
+Plan_ddl_constr::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_ddlRow != 0);
+ m_ddlRow->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+Exec_base*
+Plan_ddl_constr::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_ddl_constr::print(Ctx& ctx)
+{
+ ctx.print(" [ddl_constr");
+ Plan_base* a[] = { m_ddlRow };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.hpp
new file mode 100644
index 00000000000..ea7808b37cb
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_constr.hpp
@@ -0,0 +1,65 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_ddl_constr_hpp
+#define ODBC_CODEGEN_Code_ddl_constr_hpp
+
+#include <common/common.hpp>
+#include "Code_ddl_row.hpp"
+
+/**
+ * @class Plan_ddl_constr
+ * @brief Constraint in DDL statement
+ *
+ * Only unnamed primary key constraint exists.
+ */
+class Plan_ddl_constr : public Plan_base {
+public:
+ Plan_ddl_constr(Plan_root* root);
+ virtual ~Plan_ddl_constr();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setRow(Plan_ddl_row* ddlRow);
+ Plan_ddl_row* getRow() const;
+protected:
+ Plan_ddl_row* m_ddlRow;
+};
+
+inline
+Plan_ddl_constr::Plan_ddl_constr(Plan_root* root) :
+ Plan_base(root)
+{
+}
+
+// children
+
+inline void
+Plan_ddl_constr::setRow(Plan_ddl_row* ddlRow)
+{
+ ctx_assert(ddlRow != 0);
+ m_ddlRow = ddlRow;
+}
+
+inline Plan_ddl_row*
+Plan_ddl_constr::getRow() const
+{
+ ctx_assert(m_ddlRow != 0);
+ return m_ddlRow;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_row.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_row.cpp
new file mode 100644
index 00000000000..87589ebbaa0
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_row.cpp
@@ -0,0 +1,54 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_ddl_row.hpp"
+#include "Code_ddl_column.hpp"
+#include "Code_ddl_constr.hpp"
+
+Plan_ddl_row::~Plan_ddl_row()
+{
+}
+
+Plan_base*
+Plan_ddl_row::analyze(Ctx& ctx, Ctl& ctl)
+{
+ // analyze the columns
+ for (unsigned i = 1, n = countColumn(); i <= n; i++) {
+ Plan_ddl_column* column = getColumn(i);
+ column->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ }
+ // node was not replaced
+ return this;
+}
+
+Exec_base*
+Plan_ddl_row::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_ddl_row::print(Ctx& ctx)
+{
+ ctx.print(" [ddl_row");
+ for (unsigned i = 1, n = countColumn(); i <= n; i++) {
+ Plan_base* a = m_columnList[i];
+ printList(ctx, &a, 1);
+ }
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_row.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_row.hpp
new file mode 100644
index 00000000000..ac3eded1b2e
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_ddl_row.hpp
@@ -0,0 +1,72 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_ddl_row_hpp
+#define ODBC_CODEGEN_Code_ddl_row_hpp
+
+#include <common/common.hpp>
+#include "Code_base.hpp"
+#include "Code_ddl_column.hpp"
+
+/**
+ * @class Plan_ddl_row
+ * @brief Row of columns in create statement
+ */
+class Plan_ddl_row : public Plan_base {
+public:
+ Plan_ddl_row(Plan_root* root);
+ virtual ~Plan_ddl_row();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ unsigned countColumn() const;
+ void addColumn(Plan_ddl_column* column);
+ Plan_ddl_column* getColumn(unsigned i) const;
+protected:
+ DdlColumnVector m_columnList;
+};
+
+inline
+Plan_ddl_row::Plan_ddl_row(Plan_root* root) :
+ Plan_base(root),
+ m_columnList(1)
+{
+}
+
+// children
+
+inline unsigned
+Plan_ddl_row::countColumn() const
+{
+ return m_columnList.size() - 1;
+}
+
+inline void
+Plan_ddl_row::addColumn(Plan_ddl_column* column)
+{
+ ctx_assert(column != 0);
+ m_columnList.push_back(column);
+}
+
+inline Plan_ddl_column*
+Plan_ddl_row::getColumn(unsigned i) const
+{
+ ctx_assert(1 <= i && i <= countColumn() && m_columnList[i] != 0);
+ return m_columnList[i];
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_delete.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete.cpp
new file mode 100644
index 00000000000..35b3daa1aca
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete.cpp
@@ -0,0 +1,205 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include "Code_delete.hpp"
+#include "Code_delete_lookup.hpp"
+#include "Code_delete_index.hpp"
+#include "Code_delete_scan.hpp"
+#include "Code_query_filter.hpp"
+#include "Code_query_lookup.hpp"
+#include "Code_query_index.hpp"
+#include "Code_query_scan.hpp"
+#include "Code_query_range.hpp"
+#include "Code_query_repeat.hpp"
+#include "Code_table.hpp"
+#include "Code_root.hpp"
+
+Plan_delete::~Plan_delete()
+{
+}
+
+Plan_base*
+Plan_delete::analyze(Ctx& ctx, Ctl& ctl)
+{
+ stmtArea().stmtInfo().setName(Stmt_name_delete);
+ // analyze the table
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ // set name resolution scope
+ ctl.m_tableList.resize(1 + 1); // indexed from 1
+ ctl.m_tableList[1] = m_table;
+ Plan_dml* stmt = 0;
+ if (m_pred != 0) {
+ // analyze the predicate
+ ctl.m_topand = true;
+ ctl.m_extra = false;
+ m_pred = static_cast<Plan_pred*>(m_pred->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_pred != 0);
+ // check for key match
+ Plan_table::Index* indexBest = 0;
+ for (unsigned i = 0; i <= m_table->indexCount(); i++) {
+ Plan_table::Index& index = m_table->m_indexList[i];
+ TableSet tsDone;
+ m_table->resolveSet(ctx, index, tsDone);
+ if (! ctx.ok())
+ return 0;
+ if (! index.m_keyFound)
+ continue;
+ // prefer smaller rank, less unused keys
+ int k;
+ (k = (indexBest == 0)) ||
+ (k = (indexBest->m_rank - index.m_rank)) ||
+ (k = (indexBest->m_keyCountUnused - index.m_keyCountUnused));
+ if (k > 0)
+ indexBest = &index;
+ }
+ if (indexBest != 0) {
+ const bool exactKey = indexBest->m_rank <= 1 ? m_table->exactKey(ctx, indexBest) : false;
+ const bool direct = ! ctl.m_extra && exactKey;
+ ctx_log3(("delete direct=%d: extra=%d exact=%d", direct, ctl.m_extra, exactKey));
+ if (indexBest->m_rank == 0) {
+ // primary key
+ Plan_delete_lookup* deleteLookup = new Plan_delete_lookup(m_root);
+ m_root->saveNode(deleteLookup);
+ deleteLookup->setTable(m_table);
+ if (direct) {
+ // key match with no extra conditions
+ Plan_query_repeat* queryRepeat = new Plan_query_repeat(m_root, 1);
+ m_root->saveNode(queryRepeat);
+ deleteLookup->setQuery(queryRepeat);
+ } else {
+ // key match with extra conditions
+ Plan_query_lookup* queryLookup = new Plan_query_lookup(m_root);
+ m_root->saveNode(queryLookup);
+ Plan_query_filter* queryFilter = new Plan_query_filter(m_root);
+ m_root->saveNode(queryFilter);
+ queryLookup->setTable(m_table);
+ queryFilter->setQuery(queryLookup);
+ queryFilter->setPred(m_pred);
+ queryFilter->m_topTable = m_table;
+ deleteLookup->setQuery(queryFilter);
+ }
+ stmt = deleteLookup;
+ } else if (indexBest->m_rank == 1) {
+ // hash index
+ Plan_delete_index* deleteIndex = new Plan_delete_index(m_root);
+ m_root->saveNode(deleteIndex);
+ deleteIndex->setTable(m_table, indexBest);
+ if (direct) {
+ // key match with no extra conditions
+ Plan_query_repeat* queryRepeat = new Plan_query_repeat(m_root, 1);
+ m_root->saveNode(queryRepeat);
+ deleteIndex->setQuery(queryRepeat);
+ } else {
+ // key match with extra conditions
+ Plan_query_index* queryIndex = new Plan_query_index(m_root);
+ m_root->saveNode(queryIndex);
+ Plan_query_filter* queryFilter = new Plan_query_filter(m_root);
+ m_root->saveNode(queryFilter);
+ queryIndex->setTable(m_table, indexBest);
+ queryFilter->setQuery(queryIndex);
+ queryFilter->setPred(m_pred);
+ queryFilter->m_topTable = m_table;
+ deleteIndex->setQuery(queryFilter);
+ }
+ stmt = deleteIndex;
+ } else if (indexBest->m_rank == 2) {
+ // ordered index
+ Plan_delete_scan* deleteScan = new Plan_delete_scan(m_root);
+ m_root->saveNode(deleteScan);
+ Plan_query_filter* queryFilter = new Plan_query_filter(m_root);
+ m_root->saveNode(queryFilter);
+ Plan_query_range* queryRange = new Plan_query_range(m_root);
+ m_root->saveNode(queryRange);
+ queryRange->setTable(m_table, indexBest);
+ queryRange->setExclusive();
+ queryFilter->setQuery(queryRange);
+ queryFilter->setPred(m_pred);
+ queryFilter->m_topTable = m_table;
+ const TableSet& ts2 = m_pred->noInterp();
+ ctx_assert(ts2.size() <= 1);
+ if (ts2.size() == 0) {
+ queryRange->setInterp(m_pred);
+ }
+ deleteScan->setQuery(queryFilter);
+ stmt = deleteScan;
+ } else {
+ ctx_assert(false);
+ }
+ } else {
+ // scan delete with filter
+ Plan_delete_scan* deleteScan = new Plan_delete_scan(m_root);
+ m_root->saveNode(deleteScan);
+ Plan_query_filter* queryFilter = new Plan_query_filter(m_root);
+ m_root->saveNode(queryFilter);
+ Plan_query_scan* queryScan = new Plan_query_scan(m_root);
+ m_root->saveNode(queryScan);
+ queryScan->setTable(m_table);
+ queryScan->setExclusive();
+ queryFilter->setQuery(queryScan);
+ queryFilter->setPred(m_pred);
+ queryFilter->m_topTable = m_table;
+ // interpeter
+ const TableSet& ts2 = m_pred->noInterp();
+ ctx_assert(ts2.size() <= 1);
+ if (ts2.size() == 0) {
+ queryScan->setInterp(m_pred);
+ }
+ deleteScan->setQuery(queryFilter);
+ stmt = deleteScan;
+ }
+ } else {
+ // scan delete without filter
+ Plan_delete_scan* deleteScan = new Plan_delete_scan(m_root);
+ m_root->saveNode(deleteScan);
+ Plan_query_scan* queryScan = new Plan_query_scan(m_root);
+ m_root->saveNode(queryScan);
+ queryScan->setTable(m_table);
+ queryScan->setExclusive();
+ deleteScan->setQuery(queryScan);
+ stmt = deleteScan;
+ }
+ // set base for column position offsets
+ m_table->m_resOff = 1;
+ return stmt;
+}
+
+void
+Plan_delete::describe(Ctx& ctx)
+{
+ stmtArea().setFunction(ctx, "DELETE WHERE", SQL_DIAG_DELETE_WHERE);
+}
+
+Exec_base*
+Plan_delete::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_delete::print(Ctx& ctx)
+{
+ ctx.print(" [delete");
+ Plan_base* a[] = { m_table, m_pred };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_delete.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete.hpp
new file mode 100644
index 00000000000..c7fa245497b
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete.hpp
@@ -0,0 +1,69 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_delete_hpp
+#define ODBC_CODEGEN_Code_delete_hpp
+
+#include <common/common.hpp>
+#include "Code_base.hpp"
+#include "Code_dml.hpp"
+#include "Code_table.hpp"
+#include "Code_query.hpp"
+#include "Code_pred.hpp"
+
+/**
+ * @class Plan_delete
+ * @brief Delete in PlanTree
+ */
+class Plan_delete : public Plan_dml {
+public:
+ Plan_delete(Plan_root* root);
+ virtual ~Plan_delete();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx& ctx);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setTable(Plan_table* table);
+ void setPred(Plan_pred* pred);
+protected:
+ Plan_table* m_table;
+ Plan_pred* m_pred;
+};
+
+inline
+Plan_delete::Plan_delete(Plan_root* root) :
+ Plan_dml(root),
+ m_table(0),
+ m_pred(0)
+{
+}
+
+inline void
+Plan_delete::setTable(Plan_table* table)
+{
+ ctx_assert(table != 0);
+ m_table = table;
+}
+
+inline void
+Plan_delete::setPred(Plan_pred* pred)
+{
+ ctx_assert(pred != 0);
+ m_pred = pred;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_index.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_index.cpp
new file mode 100644
index 00000000000..8f2c3be2848
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_index.cpp
@@ -0,0 +1,164 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include "Code_expr.hpp"
+#include "Code_delete_index.hpp"
+#include "Code_table.hpp"
+#include "Code_root.hpp"
+
+Plan_delete_index::~Plan_delete_index()
+{
+}
+
+Plan_base*
+Plan_delete_index::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_query != 0);
+ m_query->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+void
+Plan_delete_index::describe(Ctx& ctx)
+{
+ stmtArea().setFunction(ctx, "DELETE WHERE", SQL_DIAG_DELETE_WHERE);
+}
+
+Exec_base*
+Plan_delete_index::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // create code for the query
+ ctx_assert(m_query != 0);
+ Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execQuery != 0);
+ // set up
+ ctx_assert(m_table != 0 && m_index != 0);
+ const BaseString& tableName = m_table->getName();
+ ctx_assert(m_index->m_dictIndex != 0);
+ const DictIndex& dictIndex = *m_index->m_dictIndex;
+ const BaseString& indexName = dictIndex.getName();
+ const unsigned keyCount = m_index->m_keyCount;
+ // create the code
+ Exec_delete_index::Code& code = *new Exec_delete_index::Code(keyCount);
+ code.m_tableName = strcpy(new char[tableName.length() + 1], tableName.c_str());
+ code.m_indexName = strcpy(new char[indexName.length() + 1], indexName.c_str());
+ // key attributes
+ code.m_keyId = new NdbAttrId[1 + keyCount];
+ code.m_keyId[0] = (NdbAttrId)-1;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ const DictColumn* keyColumn = dictIndex.getColumn(k);
+ const SqlType& sqlType = keyColumn->sqlType();
+ SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
+ code.m_keySpecs.setEntry(k, sqlSpec);
+ code.m_keyId[k] = k - 1; // index column order
+ }
+ // matching expressions
+ ctx_assert(m_index->m_keyFound);
+ const ExprVector& keyEq = m_index->m_keyEq;
+ ctx_assert(keyEq.size() == 1 + keyCount);
+ code.m_keyMatch = new Exec_expr* [1 + keyCount];
+ code.m_keyMatch[0] = 0;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ Plan_expr* expr = keyEq[k];
+ Exec_expr* execExpr = static_cast<Exec_expr*>(expr->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execExpr != 0);
+ code.m_keyMatch[k] = execExpr;
+ }
+ // create the exec
+ Exec_delete_index* exec = new Exec_delete_index(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ exec->setCode(code);
+ exec->setQuery(execQuery);
+ return exec;
+}
+
+void
+Plan_delete_index::print(Ctx& ctx)
+{
+ ctx.print(" [delete_index");
+ Plan_base* a[] = { m_query, m_table };
+ printList(ctx, a, 2);
+ ctx.print("]");
+}
+
+// Exec_delete_index
+
+Exec_delete_index::Code::~Code()
+{
+ delete[] m_tableName;
+ delete[] m_keyId;
+ delete[] m_keyMatch;
+}
+
+Exec_delete_index::Data::~Data()
+{
+}
+
+Exec_delete_index::~Exec_delete_index()
+{
+}
+
+void
+Exec_delete_index::alloc(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ // allocate the subquery
+ ctx_assert(m_query != 0);
+ m_query->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // allocate matching expressions
+ for (unsigned k = 1; k <= code.m_keyCount; k++) {
+ Exec_expr* expr = code.m_keyMatch[k];
+ ctx_assert(expr != 0);
+ expr->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ }
+ // create data
+ Data& data = *new Data;
+ setData(data);
+}
+
+void
+Exec_delete_index::close(Ctx& ctx)
+{
+ ctx_assert(m_query != 0);
+ m_query->close(ctx);
+}
+
+void
+Exec_delete_index::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [delete_index");
+ Exec_base* a[] = { m_query };
+ printList(ctx, a, 1);
+ printList(ctx, (Exec_base**)&code.m_keyMatch[1], code.m_keyCount);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_index.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_index.hpp
new file mode 100644
index 00000000000..1aaaa18abcb
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_index.hpp
@@ -0,0 +1,156 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_delete_index_hpp
+#define ODBC_CODEGEN_Code_delete_index_hpp
+
+#include <common/common.hpp>
+#include "Code_dml.hpp"
+#include "Code_query.hpp"
+#include "Code_table.hpp"
+
+/**
+ * @class Plan_delete_index
+ * @brief Delete by primary key
+ */
+class Plan_delete_index : public Plan_dml {
+public:
+ Plan_delete_index(Plan_root* root);
+ virtual ~Plan_delete_index();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx& ctx);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setQuery(Plan_query* query);
+ void setTable(Plan_table* table, Plan_table::Index* index);
+protected:
+ Plan_query* m_query;
+ Plan_table* m_table;
+ Plan_table::Index* m_index;
+};
+
+inline
+Plan_delete_index::Plan_delete_index(Plan_root* root) :
+ Plan_dml(root),
+ m_query(0),
+ m_table(0)
+{
+}
+
+inline void
+Plan_delete_index::setQuery(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+inline void
+Plan_delete_index::setTable(Plan_table* table, Plan_table::Index* index)
+{
+ ctx_assert(table != 0 && index != 0 && index == &table->m_indexList[index->m_pos] && index->m_pos != 0);
+ m_table = table;
+ m_index = index;
+}
+
+/**
+ * @class Exec_delete_index
+ * @brief Delete by primary key
+ */
+class Exec_delete_index : public Exec_dml {
+public:
+ class Code : public Exec_dml::Code {
+ public:
+ Code(unsigned keyCount);
+ virtual ~Code();
+ protected:
+ friend class Plan_delete_index;
+ friend class Exec_delete_index;
+ const char* m_tableName;
+ const char* m_indexName;
+ unsigned m_keyCount;
+ SqlSpecs m_keySpecs; // key types
+ NdbAttrId* m_keyId;
+ Exec_expr** m_keyMatch; // XXX pointers for now
+ };
+ class Data : public Exec_dml::Data {
+ public:
+ Data();
+ virtual ~Data();
+ protected:
+ friend class Exec_delete_index;
+ };
+ Exec_delete_index(Exec_root* root);
+ virtual ~Exec_delete_index();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setQuery(Exec_query* query);
+protected:
+ Exec_query* m_query;
+};
+
+inline
+Exec_delete_index::Code::Code(unsigned keyCount) :
+ m_tableName(0),
+ m_indexName(0),
+ m_keyCount(keyCount),
+ m_keySpecs(keyCount),
+ m_keyId(0),
+ m_keyMatch(0)
+{
+}
+
+inline
+Exec_delete_index::Data::Data()
+{
+}
+
+inline
+Exec_delete_index::Exec_delete_index(Exec_root* root) :
+ Exec_dml(root),
+ m_query(0)
+{
+}
+
+// children
+
+inline const Exec_delete_index::Code&
+Exec_delete_index::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_delete_index::Data&
+Exec_delete_index::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_delete_index::setQuery(Exec_query* query)
+{
+ ctx_assert(query != 0 && m_query == 0);
+ m_query = query;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.cpp
new file mode 100644
index 00000000000..4a6dec64654
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.cpp
@@ -0,0 +1,162 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include "Code_expr.hpp"
+#include "Code_delete_lookup.hpp"
+#include "Code_table.hpp"
+#include "Code_root.hpp"
+
+Plan_delete_lookup::~Plan_delete_lookup()
+{
+}
+
+Plan_base*
+Plan_delete_lookup::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_query != 0);
+ m_query->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+void
+Plan_delete_lookup::describe(Ctx& ctx)
+{
+ stmtArea().setFunction(ctx, "DELETE WHERE", SQL_DIAG_DELETE_WHERE);
+}
+
+Exec_base*
+Plan_delete_lookup::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // create code for the query
+ ctx_assert(m_query != 0);
+ Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execQuery != 0);
+ // set up
+ ctx_assert(m_table != 0);
+ const BaseString& tableName = m_table->getName();
+ const DictTable& dictTable = m_table->dictTable();
+ const unsigned keyCount = dictTable.keyCount();
+ // create the code
+ Exec_delete_lookup::Code& code = *new Exec_delete_lookup::Code(keyCount);
+ code.m_tableName = strcpy(new char[tableName.length() + 1], tableName.c_str());
+ // key attributes
+ code.m_keyId = new NdbAttrId[1 + keyCount];
+ code.m_keyId[0] = (NdbAttrId)-1;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ const DictColumn* keyColumn = dictTable.getKey(k);
+ const SqlType& sqlType = keyColumn->sqlType();
+ SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
+ code.m_keySpecs.setEntry(k, sqlSpec);
+ code.m_keyId[k] = keyColumn->getAttrId();
+ }
+ // matching expressions
+ const Plan_table::Index& index = m_table->m_indexList[0];
+ ctx_assert(index.m_keyFound);
+ const ExprVector& keyEq = index.m_keyEq;
+ ctx_assert(keyEq.size() == 1 + keyCount);
+ code.m_keyMatch = new Exec_expr* [1 + keyCount];
+ code.m_keyMatch[0] = 0;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ Plan_expr* expr = keyEq[k];
+ Exec_expr* execExpr = static_cast<Exec_expr*>(expr->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execExpr != 0);
+ code.m_keyMatch[k] = execExpr;
+ }
+ // create the exec
+ Exec_delete_lookup* exec = new Exec_delete_lookup(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ exec->setCode(code);
+ exec->setQuery(execQuery);
+ return exec;
+}
+
+void
+Plan_delete_lookup::print(Ctx& ctx)
+{
+ ctx.print(" [delete_lookup");
+ Plan_base* a[] = { m_query, m_table };
+ printList(ctx, a, 2);
+ ctx.print("]");
+}
+
+// Exec_delete_lookup
+
+Exec_delete_lookup::Code::~Code()
+{
+ delete[] m_tableName;
+ delete[] m_keyId;
+ delete[] m_keyMatch;
+}
+
+Exec_delete_lookup::Data::~Data()
+{
+}
+
+Exec_delete_lookup::~Exec_delete_lookup()
+{
+}
+
+void
+Exec_delete_lookup::alloc(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ // allocate the subquery
+ ctx_assert(m_query != 0);
+ m_query->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // allocate matching expressions
+ for (unsigned k = 1; k <= code.m_keyCount; k++) {
+ Exec_expr* expr = code.m_keyMatch[k];
+ ctx_assert(expr != 0);
+ expr->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ }
+ // create data
+ Data& data = *new Data;
+ setData(data);
+}
+
+void
+Exec_delete_lookup::close(Ctx& ctx)
+{
+ ctx_assert(m_query != 0);
+ m_query->close(ctx);
+}
+
+void
+Exec_delete_lookup::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [delete_lookup");
+ Exec_base* a[] = { m_query };
+ printList(ctx, a, 1);
+ printList(ctx, (Exec_base**)&code.m_keyMatch[1], code.m_keyCount);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.hpp
new file mode 100644
index 00000000000..4138baefa4c
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_lookup.hpp
@@ -0,0 +1,152 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_delete_lookup_hpp
+#define ODBC_CODEGEN_Code_delete_lookup_hpp
+
+#include <common/common.hpp>
+#include "Code_dml.hpp"
+#include "Code_query.hpp"
+#include "Code_table.hpp"
+
+/**
+ * @class Plan_delete_lookup
+ * @brief Delete by primary key
+ */
+class Plan_delete_lookup : public Plan_dml {
+public:
+ Plan_delete_lookup(Plan_root* root);
+ virtual ~Plan_delete_lookup();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx& ctx);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setQuery(Plan_query* query);
+ void setTable(Plan_table* table);
+protected:
+ Plan_query* m_query;
+ Plan_table* m_table;
+};
+
+inline
+Plan_delete_lookup::Plan_delete_lookup(Plan_root* root) :
+ Plan_dml(root),
+ m_query(0),
+ m_table(0)
+{
+}
+
+inline void
+Plan_delete_lookup::setQuery(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+inline void
+Plan_delete_lookup::setTable(Plan_table* table)
+{
+ ctx_assert(table != 0);
+ m_table = table;
+}
+
+/**
+ * @class Exec_delete_lookup
+ * @brief Delete by primary key
+ */
+class Exec_delete_lookup : public Exec_dml {
+public:
+ class Code : public Exec_dml::Code {
+ public:
+ Code(unsigned keyCount);
+ virtual ~Code();
+ protected:
+ friend class Plan_delete_lookup;
+ friend class Exec_delete_lookup;
+ char* m_tableName;
+ unsigned m_keyCount;
+ SqlSpecs m_keySpecs; // key types
+ NdbAttrId* m_keyId;
+ Exec_expr** m_keyMatch; // XXX pointers for now
+ };
+ class Data : public Exec_dml::Data {
+ public:
+ Data();
+ virtual ~Data();
+ protected:
+ friend class Exec_delete_lookup;
+ };
+ Exec_delete_lookup(Exec_root* root);
+ virtual ~Exec_delete_lookup();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setQuery(Exec_query* query);
+protected:
+ Exec_query* m_query;
+};
+
+inline
+Exec_delete_lookup::Code::Code(unsigned keyCount) :
+ m_tableName(0),
+ m_keyCount(keyCount),
+ m_keySpecs(keyCount),
+ m_keyId(0),
+ m_keyMatch(0)
+{
+}
+
+inline
+Exec_delete_lookup::Data::Data()
+{
+}
+
+inline
+Exec_delete_lookup::Exec_delete_lookup(Exec_root* root) :
+ Exec_dml(root),
+ m_query(0)
+{
+}
+
+// children
+
+inline const Exec_delete_lookup::Code&
+Exec_delete_lookup::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_delete_lookup::Data&
+Exec_delete_lookup::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_delete_lookup::setQuery(Exec_query* query)
+{
+ ctx_assert(query != 0 && m_query == 0);
+ m_query = query;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_scan.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_scan.cpp
new file mode 100644
index 00000000000..fed7244a026
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_scan.cpp
@@ -0,0 +1,110 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include "Code_delete_scan.hpp"
+#include "Code_root.hpp"
+
+Plan_delete_scan::~Plan_delete_scan()
+{
+}
+
+Plan_base*
+Plan_delete_scan::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_query != 0);
+ m_query->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+void
+Plan_delete_scan::describe(Ctx& ctx)
+{
+ stmtArea().setFunction(ctx, "DELETE WHERE", SQL_DIAG_DELETE_WHERE);
+}
+
+Exec_base*
+Plan_delete_scan::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // create code for the subquery
+ ctx_assert(m_query != 0);
+ Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execQuery != 0);
+ // create the code
+ Exec_delete_scan* exec = new Exec_delete_scan(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ Exec_delete_scan::Code& code = *new Exec_delete_scan::Code;
+ exec->setCode(code);
+ exec->setQuery(execQuery);
+ return exec;
+}
+
+void
+Plan_delete_scan::print(Ctx& ctx)
+{
+ ctx.print(" [delete_scan");
+ Plan_base* a[] = { m_query };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
+
+// Exec_delete_scan
+
+Exec_delete_scan::Code::~Code()
+{
+}
+
+Exec_delete_scan::Data::~Data()
+{
+}
+
+Exec_delete_scan::~Exec_delete_scan()
+{
+}
+
+void
+Exec_delete_scan::alloc(Ctx& ctx, Ctl& ctl)
+{
+ // allocate the subquery
+ ctx_assert(m_query != 0);
+ m_query->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // create data
+ Data& data = *new Data;
+ setData(data);
+}
+
+void
+Exec_delete_scan::close(Ctx& ctx)
+{
+ ctx_assert(m_query != 0);
+ m_query->close(ctx);
+}
+
+void
+Exec_delete_scan::print(Ctx& ctx)
+{
+ ctx.print(" [delete_scan");
+ Exec_base* a[] = { m_query };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
+
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_scan.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_scan.hpp
new file mode 100644
index 00000000000..eb013a8257e
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_delete_scan.hpp
@@ -0,0 +1,130 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_delete_scan_hpp
+#define ODBC_CODEGEN_Code_delete_scan_hpp
+
+#include <common/common.hpp>
+#include "Code_dml.hpp"
+#include "Code_query.hpp"
+
+/**
+ * @class Plan_delete_scan
+ * @brief Scan delete
+ */
+class Plan_delete_scan : public Plan_dml {
+public:
+ Plan_delete_scan(Plan_root* root);
+ virtual ~Plan_delete_scan();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx& ctx);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setQuery(Plan_query* query);
+protected:
+ Plan_query* m_query;
+};
+
+inline
+Plan_delete_scan::Plan_delete_scan(Plan_root* root) :
+ Plan_dml(root),
+ m_query(0)
+{
+}
+
+inline void
+Plan_delete_scan::setQuery(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+/**
+ * @class Exec_delete_scan
+ * @brief Scan delete
+ */
+class Exec_delete_scan : public Exec_dml {
+public:
+ class Code : public Exec_dml::Code {
+ public:
+ Code();
+ virtual ~Code();
+ protected:
+ friend class Exec_delete_scan;
+ };
+ class Data : public Exec_dml::Data {
+ public:
+ Data();
+ virtual ~Data();
+ protected:
+ friend class Exec_delete_scan;
+ };
+ Exec_delete_scan(Exec_root* root);
+ virtual ~Exec_delete_scan();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setQuery(Exec_query* query);
+protected:
+ Exec_query* m_query;
+};
+
+inline
+Exec_delete_scan::Code::Code()
+{
+}
+
+inline
+Exec_delete_scan::Data::Data()
+{
+}
+
+inline
+Exec_delete_scan::Exec_delete_scan(Exec_root* root) :
+ Exec_dml(root),
+ m_query(0)
+{
+}
+
+// children
+
+inline const Exec_delete_scan::Code&
+Exec_delete_scan::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_delete_scan::Data&
+Exec_delete_scan::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_delete_scan::setQuery(Exec_query* query)
+{
+ ctx_assert(query != 0 && m_query == 0);
+ m_query = query;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_dml.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_dml.cpp
new file mode 100644
index 00000000000..44fd4478646
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_dml.cpp
@@ -0,0 +1,51 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include "Code_dml.hpp"
+
+// Plan_dml
+
+Plan_dml::~Plan_dml()
+{
+}
+
+// Exec_dml
+
+Exec_dml::Code::~Code()
+{
+}
+
+Exec_dml::Data::~Data()
+{
+}
+
+Exec_dml::~Exec_dml()
+{
+}
+
+void
+Exec_dml::execute(Ctx& ctx, Ctl& ctl)
+{
+ execImpl(ctx, ctl);
+ if (m_topLevel) {
+ if (ctx.ok()) {
+ if (stmtArea().getRowCount() == 0) {
+ ctx.setCode(SQL_NO_DATA);
+ }
+ }
+ }
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_dml.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_dml.hpp
new file mode 100644
index 00000000000..0618f583984
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_dml.hpp
@@ -0,0 +1,67 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_dml_hpp
+#define ODBC_CODEGEN_Code_dml_hpp
+
+#include <common/common.hpp>
+#include <common/ResultArea.hpp>
+#include "Code_stmt.hpp"
+
+/**
+ * @class Plan_dml
+ * @brief Base class for DML statements in PlanTree
+ */
+class Plan_dml : public Plan_stmt {
+public:
+ Plan_dml(Plan_root* root);
+ virtual ~Plan_dml() = 0;
+};
+
+inline
+Plan_dml::Plan_dml(Plan_root* root) :
+ Plan_stmt(root)
+{
+}
+
+/**
+ * @class Exec_dml
+ * @brief Base class for DML statements in ExecTree
+ */
+class Exec_dml : public Exec_stmt {
+public:
+ class Code : public Exec_stmt::Code {
+ public:
+ virtual ~Code() = 0;
+ };
+ class Data : public Exec_stmt::Data, public ResultArea {
+ public:
+ virtual ~Data() = 0;
+ };
+ Exec_dml(Exec_root* root);
+ virtual ~Exec_dml() = 0;
+ void execute(Ctx& ctx, Ctl& ctl);
+protected:
+ virtual void execImpl(Ctx& ctx, Ctl& ctl) = 0;
+};
+
+inline
+Exec_dml::Exec_dml(Exec_root* root) :
+ Exec_stmt(root)
+{
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_dml_column.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_dml_column.cpp
new file mode 100644
index 00000000000..808e2ac8c4b
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_dml_column.cpp
@@ -0,0 +1,47 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NdbApi.hpp>
+#include <common/StmtArea.hpp>
+#include "Code_dml_column.hpp"
+
+// Plan_dml_column
+
+Plan_dml_column::~Plan_dml_column()
+{
+}
+
+Plan_base*
+Plan_dml_column::analyze(Ctx& ctx, Ctl& ctl)
+{
+ analyzeColumn(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+Exec_base*
+Plan_dml_column::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_dml_column::print(Ctx& ctx)
+{
+ ctx.print(" [dml_column %s]", getPrintName());
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_dml_column.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_dml_column.hpp
new file mode 100644
index 00000000000..0fb33944a3a
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_dml_column.hpp
@@ -0,0 +1,46 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_dml_column_hpp
+#define ODBC_CODEGEN_Code_dml_column_hpp
+
+#include <common/common.hpp>
+#include "Code_column.hpp"
+
+class DictColumn;
+class Plan_table;
+
+/**
+ * @class Plan_dml_column
+ * @brief Column in query expression
+ */
+class Plan_dml_column : public Plan_base, public Plan_column {
+public:
+ Plan_dml_column(Plan_root* root, const BaseString& name);
+ virtual ~Plan_dml_column();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+};
+
+inline
+Plan_dml_column::Plan_dml_column(Plan_root* root, const BaseString& name) :
+ Plan_base(root),
+ Plan_column(Type_dml, name)
+{
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_dml_row.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_dml_row.cpp
new file mode 100644
index 00000000000..ceb63a9f7b9
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_dml_row.cpp
@@ -0,0 +1,56 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_dml_row.hpp"
+#include "Code_dml_column.hpp"
+
+Plan_dml_row::~Plan_dml_row()
+{
+}
+
+Plan_base*
+Plan_dml_row::analyze(Ctx& ctx, Ctl& ctl)
+{
+ unsigned size = getSize();
+ // analyze the columns
+ for (unsigned i = 1; i <= size; i++) {
+ Plan_dml_column* column = getColumn(i);
+ column->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ }
+ // node was not replaced
+ return this;
+}
+
+Exec_base*
+Plan_dml_row::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_dml_row::print(Ctx& ctx)
+{
+ unsigned size = getSize();
+ ctx.print(" [dml_row");
+ for (unsigned i = 1; i <= size; i++) {
+ Plan_base* a = m_columnList[i];
+ a == 0 ? ctx.print(" -") : a->print(ctx);
+ }
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_dml_row.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_dml_row.hpp
new file mode 100644
index 00000000000..6c7e46ba9af
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_dml_row.hpp
@@ -0,0 +1,76 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_dml_row_hpp
+#define ODBC_CODEGEN_Code_dml_row_hpp
+
+#include <vector>
+#include <common/common.hpp>
+#include <common/DataRow.hpp>
+#include "Code_base.hpp"
+#include "Code_dml_column.hpp"
+
+class Plan_dml_column;
+
+/**
+ * @class Plan_dml_row
+ * @brief Row of lvalue columns in insert or update
+ */
+class Plan_dml_row : public Plan_base {
+public:
+ Plan_dml_row(Plan_root* root);
+ virtual ~Plan_dml_row();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ unsigned getSize() const;
+ void addColumn(Plan_dml_column* column);
+ Plan_dml_column* getColumn(unsigned i) const;
+protected:
+ DmlColumnVector m_columnList;
+};
+
+inline
+Plan_dml_row::Plan_dml_row(Plan_root* root) :
+ Plan_base(root),
+ m_columnList(1)
+{
+}
+
+// children
+
+inline unsigned
+Plan_dml_row::getSize() const
+{
+ return m_columnList.size() - 1;
+}
+
+inline void
+Plan_dml_row::addColumn(Plan_dml_column* column)
+{
+ ctx_assert(column != 0);
+ m_columnList.push_back(column);
+}
+
+inline Plan_dml_column*
+Plan_dml_row::getColumn(unsigned i) const
+{
+ ctx_assert(1 <= i && i <= m_columnList.size() && m_columnList[i] != 0);
+ return m_columnList[i];
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_drop_index.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_drop_index.cpp
new file mode 100644
index 00000000000..b6bae88e270
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_drop_index.cpp
@@ -0,0 +1,87 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include "Code_drop_index.hpp"
+#include "Code_root.hpp"
+
+// Plan_drop_index
+
+Plan_drop_index::~Plan_drop_index()
+{
+}
+
+Plan_base*
+Plan_drop_index::analyze(Ctx& ctx, Ctl& ctl)
+{
+ stmtArea().stmtInfo().setName(Stmt_name_drop_index);
+ return this;
+}
+
+void
+Plan_drop_index::describe(Ctx& ctx)
+{
+ stmtArea().setFunction(ctx, "DROP INDEX", SQL_DIAG_DROP_INDEX);
+}
+
+Exec_base*
+Plan_drop_index::codegen(Ctx& ctx, Ctl& ctl)
+{
+ Exec_drop_index* exec = new Exec_drop_index(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ Exec_drop_index::Code& code = *new Exec_drop_index::Code(m_name, m_tableName);
+ exec->setCode(code);
+ return exec;
+}
+
+void
+Plan_drop_index::print(Ctx& ctx)
+{
+ ctx.print(" [drop_index %s]", m_name.c_str());
+}
+
+// Exec_drop_index
+
+Exec_drop_index::Code::~Code()
+{
+}
+
+Exec_drop_index::Data::~Data()
+{
+}
+
+Exec_drop_index::~Exec_drop_index()
+{
+}
+
+void
+Exec_drop_index::alloc(Ctx& ctx, Ctl& ctl)
+{
+ Data& data = *new Data;
+ setData(data);
+}
+
+void
+Exec_drop_index::close(Ctx& ctx)
+{
+}
+
+void
+Exec_drop_index::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [drop_index %s]", code.m_indexName.c_str());
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_drop_index.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_drop_index.hpp
new file mode 100644
index 00000000000..99891c9a52f
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_drop_index.hpp
@@ -0,0 +1,136 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_drop_index_hpp
+#define ODBC_CODEGEN_Code_drop_index_hpp
+
+#include <vector>
+#include <NdbApi.hpp>
+#include <common/common.hpp>
+#include "Code_ddl.hpp"
+
+class DictTable;
+class DictColumn;
+
+/**
+ * @class Plan_drop_index
+ * @brief Drop index in PlanTree
+ */
+class Plan_drop_index : public Plan_ddl {
+public:
+ Plan_drop_index(Plan_root* root, const BaseString& name);
+ Plan_drop_index(Plan_root* root, const BaseString& name, const BaseString& tableName);
+ virtual ~Plan_drop_index();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx & ctx);
+ void print(Ctx& ctx);
+ // attributes
+ const BaseString& getName() const;
+protected:
+ BaseString m_name;
+ BaseString m_tableName;
+};
+
+inline
+Plan_drop_index::Plan_drop_index(Plan_root* root, const BaseString& name) :
+ Plan_ddl(root),
+ m_name(name)
+{
+}
+
+inline
+Plan_drop_index::Plan_drop_index(Plan_root* root, const BaseString& name, const BaseString& tableName) :
+ Plan_ddl(root),
+ m_name(name),
+ m_tableName(tableName)
+{
+}
+
+inline const BaseString&
+Plan_drop_index::getName() const
+{
+ return m_name;
+}
+
+/**
+ * @class Exec_drop_index
+ * @brief Drop index in ExecTree
+ */
+class Exec_drop_index : public Exec_ddl {
+public:
+ class Code : public Exec_ddl::Code {
+ public:
+ Code(const BaseString& indexName, const BaseString& tableName);
+ virtual ~Code();
+ protected:
+ friend class Exec_drop_index;
+ const BaseString m_indexName;
+ const BaseString m_tableName;
+ };
+ class Data : public Exec_ddl::Data {
+ public:
+ Data();
+ virtual ~Data();
+ protected:
+ friend class Exec_drop_index;
+ };
+ Exec_drop_index(Exec_root* root);
+ virtual ~Exec_drop_index();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execute(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+};
+
+inline
+Exec_drop_index::Code::Code(const BaseString& indexName, const BaseString& tableName) :
+ m_indexName(indexName),
+ m_tableName(tableName)
+{
+}
+
+inline
+Exec_drop_index::Data::Data()
+{
+}
+
+inline
+Exec_drop_index::Exec_drop_index(Exec_root* root) :
+ Exec_ddl(root)
+{
+}
+
+// children
+
+inline const Exec_drop_index::Code&
+Exec_drop_index::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_drop_index::Data&
+Exec_drop_index::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_drop_table.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_drop_table.cpp
new file mode 100644
index 00000000000..f20bf9fdae0
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_drop_table.cpp
@@ -0,0 +1,87 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include "Code_drop_table.hpp"
+#include "Code_root.hpp"
+
+// Plan_drop_table
+
+Plan_drop_table::~Plan_drop_table()
+{
+}
+
+Plan_base*
+Plan_drop_table::analyze(Ctx& ctx, Ctl& ctl)
+{
+ stmtArea().stmtInfo().setName(Stmt_name_drop_table);
+ return this;
+}
+
+void
+Plan_drop_table::describe(Ctx& ctx)
+{
+ stmtArea().setFunction(ctx, "DROP TABLE", SQL_DIAG_DROP_TABLE);
+}
+
+Exec_base*
+Plan_drop_table::codegen(Ctx& ctx, Ctl& ctl)
+{
+ Exec_drop_table* exec = new Exec_drop_table(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ Exec_drop_table::Code& code = *new Exec_drop_table::Code(m_name);
+ exec->setCode(code);
+ return exec;
+}
+
+void
+Plan_drop_table::print(Ctx& ctx)
+{
+ ctx.print(" [drop_table %s]", m_name.c_str());
+}
+
+// Exec_drop_table
+
+Exec_drop_table::Code::~Code()
+{
+}
+
+Exec_drop_table::Data::~Data()
+{
+}
+
+Exec_drop_table::~Exec_drop_table()
+{
+}
+
+void
+Exec_drop_table::alloc(Ctx& ctx, Ctl& ctl)
+{
+ Data& data = *new Data;
+ setData(data);
+}
+
+void
+Exec_drop_table::close(Ctx& ctx)
+{
+}
+
+void
+Exec_drop_table::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [drop_table %s]", code.m_tableName.c_str());
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_drop_table.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_drop_table.hpp
new file mode 100644
index 00000000000..849a472ed94
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_drop_table.hpp
@@ -0,0 +1,124 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_drop_table_hpp
+#define ODBC_CODEGEN_Code_drop_table_hpp
+
+#include <vector>
+#include <NdbApi.hpp>
+#include <common/common.hpp>
+#include "Code_ddl.hpp"
+
+class DictTable;
+class DictColumn;
+
+/**
+ * @class Plan_drop_table
+ * @brief Drop table in PlanTree
+ */
+class Plan_drop_table : public Plan_ddl {
+public:
+ Plan_drop_table(Plan_root* root, const BaseString& name);
+ virtual ~Plan_drop_table();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx & ctx);
+ void print(Ctx& ctx);
+ // attributes
+ const BaseString& getName() const;
+protected:
+ BaseString m_name;
+};
+
+inline
+Plan_drop_table::Plan_drop_table(Plan_root* root, const BaseString& name) :
+ Plan_ddl(root),
+ m_name(name)
+{
+}
+
+inline const BaseString&
+Plan_drop_table::getName() const
+{
+ return m_name;
+}
+
+/**
+ * @class Exec_drop_table
+ * @brief Drop table in ExecTree
+ */
+class Exec_drop_table : public Exec_ddl {
+public:
+ class Code : public Exec_ddl::Code {
+ public:
+ Code(const BaseString& tableName);
+ virtual ~Code();
+ protected:
+ friend class Exec_drop_table;
+ const BaseString m_tableName;
+ };
+ class Data : public Exec_ddl::Data {
+ public:
+ Data();
+ virtual ~Data();
+ protected:
+ friend class Exec_drop_table;
+ };
+ Exec_drop_table(Exec_root* root);
+ virtual ~Exec_drop_table();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execute(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+};
+
+inline
+Exec_drop_table::Code::Code(const BaseString& tableName) :
+ m_tableName(tableName)
+{
+}
+
+inline
+Exec_drop_table::Data::Data()
+{
+}
+
+inline
+Exec_drop_table::Exec_drop_table(Exec_root* root) :
+ Exec_ddl(root)
+{
+}
+
+// children
+
+inline const Exec_drop_table::Code&
+Exec_drop_table::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_drop_table::Data&
+Exec_drop_table::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr.cpp
new file mode 100644
index 00000000000..4afa75986a0
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr.cpp
@@ -0,0 +1,79 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_expr.hpp"
+#include "Code_expr_row.hpp"
+
+// Plan_expr
+
+Plan_expr::~Plan_expr()
+{
+}
+
+bool
+Plan_expr::isEqual(const Plan_expr* expr) const
+{
+ return false;
+}
+
+bool
+Plan_expr::isAnyEqual(const Plan_expr_row* row) const
+{
+ ctx_assert(row != 0);
+ const unsigned size = row->getSize();
+ for (unsigned i = 1; i <= size; i++) {
+ if (isEqual(row->getExpr(i)))
+ return true;
+ }
+ return false;
+}
+
+bool
+Plan_expr::isGroupBy(const Plan_expr_row* row) const
+{
+ return false;
+}
+
+// Exec_expr
+
+Exec_expr::Code::~Code()
+{
+}
+
+Exec_expr::Data::~Data()
+{
+}
+
+Exec_expr::~Exec_expr()
+{
+}
+
+SqlField&
+Exec_expr::Data::groupField(const SqlType& sqlType, unsigned i, bool initFlag)
+{
+ if (m_groupField.size() == 0) {
+ m_groupField.resize(1);
+ }
+ if (initFlag) {
+ //unsigned i2 = m_groupField.size();
+ //ctx_assert(i == i2);
+ const SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
+ const SqlField sqlField(sqlSpec);
+ m_groupField.push_back(sqlField);
+ }
+ ctx_assert(i != 0 && i < m_groupField.size());
+ return m_groupField[i];
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr.hpp
new file mode 100644
index 00000000000..b6f07471b4d
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr.hpp
@@ -0,0 +1,219 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_expr_hpp
+#define ODBC_CODEGEN_Code_expr_hpp
+
+#include <common/common.hpp>
+#include <common/DataField.hpp>
+#include "Code_base.hpp"
+
+class Ctx;
+class Plan_expr_row;
+class Exec_expr;
+
+/**
+ * @class Plan_expr
+ * @brief Base class for expressions in PlanTree
+ */
+class Plan_expr : public Plan_base {
+public:
+ // type is convenient since RTTI cannot be used
+ enum Type {
+ TypeUndefined = 0,
+ TypeColumn,
+ TypeConst,
+ TypeConv,
+ TypeFunc,
+ TypeOp,
+ TypeParam,
+ TypeValue
+ };
+ Plan_expr(Plan_root* root, Type type);
+ virtual ~Plan_expr() = 0;
+ Type type() const;
+ const SqlType& sqlType() const; // data type set by analyze
+ const TableSet& tableSet() const;
+ const BaseString& getAlias() const;
+ bool isAggr() const;
+ bool isBound() const;
+ bool isAnyEqual(const Plan_expr_row* row) const;
+ virtual bool isEqual(const Plan_expr* expr) const;
+ virtual bool isGroupBy(const Plan_expr_row* row) const;
+protected:
+ friend class Plan_expr_row;
+ friend class Plan_expr_op;
+ friend class Plan_expr_func;
+ friend class Plan_comp_op;
+ const Type m_type;
+ SqlType m_sqlType; // subclass must set
+ BaseString m_alias; // for row expression alias
+ TableSet m_tableSet; // depends on these tables
+ bool m_isAggr; // contains an aggregate expression
+ bool m_isBound; // only constants and aggregates
+ Exec_expr* m_exec; // XXX wrong move
+};
+
+inline
+Plan_expr::Plan_expr(Plan_root* root, Type type) :
+ Plan_base(root),
+ m_type(type),
+ m_isAggr(false),
+ m_isBound(false),
+ m_exec(0)
+{
+}
+
+inline Plan_expr::Type
+Plan_expr::type() const
+{
+ return m_type;
+}
+
+inline const SqlType&
+Plan_expr::sqlType() const
+{
+ ctx_assert(m_sqlType.type() != SqlType::Undef);
+ return m_sqlType;
+}
+
+inline const Plan_base::TableSet&
+Plan_expr::tableSet() const
+{
+ return m_tableSet;
+}
+
+inline const BaseString&
+Plan_expr::getAlias() const
+{
+ return m_alias;
+}
+
+inline bool
+Plan_expr::isAggr() const
+{
+ return m_isAggr;
+}
+
+inline bool
+Plan_expr::isBound() const
+{
+ return m_isBound;
+}
+
+/**
+ * @class Exec_expr
+ * @brief Base class for expressions in ExecTree
+ */
+class Exec_expr : public Exec_base {
+public:
+ /**
+ * Exec_expr::Code includes reference to SqlSpec which
+ * specifies data type and access method.
+ */
+ class Code : public Exec_base::Code {
+ public:
+ Code(const SqlSpec& sqlSpec);
+ virtual ~Code() = 0;
+ const SqlSpec& sqlSpec() const;
+ protected:
+ friend class Exec_expr;
+ const SqlSpec& m_sqlSpec; // subclass must contain
+ };
+ /**
+ * Exec_expr::Data includes reference to SqlField which
+ * contains specification and data address.
+ */
+ class Data : public Exec_base::Data {
+ public:
+ Data(const SqlField& sqlField);
+ virtual ~Data() = 0;
+ const SqlField& sqlField() const;
+ const SqlField& groupField(unsigned i) const;
+ protected:
+ friend class Exec_expr;
+ const SqlField& m_sqlField; // subclass must contain
+ // group-by data
+ typedef std::vector<SqlField> GroupField;
+ GroupField m_groupField;
+ SqlField& groupField(const SqlType& sqlType, unsigned i, bool initFlag);
+ };
+ Exec_expr(Exec_root* root);
+ virtual ~Exec_expr() = 0;
+ /**
+ * Evaluate the expression. Must be implemented by all
+ * subclasses. Check ctx.ok() for errors.
+ */
+ virtual void evaluate(Ctx& ctx, Ctl& ctl) = 0;
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+};
+
+inline
+Exec_expr::Code::Code(const SqlSpec& sqlSpec) :
+ m_sqlSpec(sqlSpec)
+{
+}
+
+inline const SqlSpec&
+Exec_expr::Code::sqlSpec() const {
+ return m_sqlSpec;
+}
+
+inline
+Exec_expr::Data::Data(const SqlField& sqlField) :
+ m_sqlField(sqlField)
+{
+}
+
+inline const SqlField&
+Exec_expr::Data::sqlField() const
+{
+ return m_sqlField;
+}
+
+inline const SqlField&
+Exec_expr::Data::groupField(unsigned i) const
+{
+ ctx_assert(i != 0 && i < m_groupField.size());
+ return m_groupField[i];
+}
+
+inline
+Exec_expr::Exec_expr(Exec_root* root) :
+ Exec_base(root)
+{
+}
+
+// children
+
+inline const Exec_expr::Code&
+Exec_expr::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_expr::Data&
+Exec_expr::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_column.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_column.cpp
new file mode 100644
index 00000000000..17a9a502d4c
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_column.cpp
@@ -0,0 +1,160 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NdbApi.hpp>
+#include <common/StmtArea.hpp>
+#include <dictionary/DictSchema.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_query.hpp"
+#include "Code_table.hpp"
+#include "Code_expr_column.hpp"
+#include "Code_root.hpp"
+
+// Plan_expr_column
+
+Plan_expr_column::~Plan_expr_column()
+{
+}
+
+Plan_base*
+Plan_expr_column::analyze(Ctx& ctx, Ctl& ctl)
+{
+ m_exec = 0;
+ analyzeColumn(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ Plan_expr::m_sqlType = Plan_column::m_sqlType;
+ // depends on one table
+ m_tableSet.insert(m_resTable);
+ // not constant as set-value
+ ctl.m_const = false;
+ // set alias name
+ m_alias = m_name;
+ return this;
+}
+
+Exec_base*
+Plan_expr_column::codegen(Ctx& ctx, Ctl& ctl)
+{
+ if (m_exec != 0)
+ return m_exec;
+ // connect column to query column
+ const Exec_query* execQuery = ctl.m_execQuery;
+ ctx_assert(execQuery != 0);
+ const Exec_query::Code& codeQuery = execQuery->getCode();
+ const SqlSpec sqlSpec(Plan_expr::m_sqlType, SqlSpec::Reference);
+ // offset in final output row
+ ctx_assert(m_resTable != 0 && m_resTable->m_resOff != 0 && m_resPos != 0);
+ unsigned resOff = m_resTable->m_resOff + (m_resPos - 1);
+ // create the code
+ Exec_expr_column* exec = new Exec_expr_column(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ Exec_expr_column::Code& code = *new Exec_expr_column::Code(sqlSpec, resOff);
+ exec->setCode(code);
+ m_exec = exec;
+ return exec;
+}
+
+bool
+Plan_expr_column::resolveEq(Ctx& ctx, Plan_expr* expr)
+{
+ ctx_assert(m_resTable != 0 && expr != 0);
+ return m_resTable->resolveEq(ctx, this, expr);
+}
+
+void
+Plan_expr_column::print(Ctx& ctx)
+{
+ ctx.print(" [expr_column %s]", getPrintName());
+}
+
+bool
+Plan_expr_column::isEqual(const Plan_expr* expr) const
+{
+ ctx_assert(expr != 0);
+ if (expr->type() != Plan_expr::TypeColumn)
+ return false;
+ const Plan_expr_column* expr2 = static_cast<const Plan_expr_column*>(expr);
+ ctx_assert(m_resTable != 0 && expr2->m_resTable != 0);
+ if (m_resTable != expr2->m_resTable)
+ return false;
+ ctx_assert(m_dictColumn != 0 && expr2->m_dictColumn != 0);
+ if (m_dictColumn != expr2->m_dictColumn)
+ return false;
+ return true;
+}
+
+bool
+Plan_expr_column::isGroupBy(const Plan_expr_row* row) const
+{
+ if (isAnyEqual(row))
+ return true;
+ return false;
+}
+
+// Exec_expr_column
+
+Exec_expr_column::Code::~Code()
+{
+}
+
+Exec_expr_column::Data::~Data()
+{
+}
+
+Exec_expr_column::~Exec_expr_column()
+{
+}
+
+void
+Exec_expr_column::alloc(Ctx& ctx, Ctl& ctl)
+{
+ if (m_data != 0)
+ return;
+ const Code& code = getCode();
+ // connect column to query column
+ ctx_assert(ctl.m_query != 0);
+ const SqlRow& sqlRow = ctl.m_query->getData().sqlRow();
+ SqlField& sqlField = sqlRow.getEntry(code.m_resOff);
+ // create the data
+ Data& data = *new Data(sqlField);
+ setData(data);
+}
+
+void
+Exec_expr_column::evaluate(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ Data& data = getData();
+ if (ctl.m_groupIndex != 0) {
+ SqlField& out = data.groupField(code.sqlSpec().sqlType(), ctl.m_groupIndex, ctl.m_groupInit);
+ data.sqlField().copy(ctx, out);
+ }
+}
+
+void
+Exec_expr_column::close(Ctx& ctx)
+{
+ Data& data = getData();
+ data.m_groupField.clear();
+}
+
+void
+Exec_expr_column::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [column %d]", code.m_resOff);
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_column.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_column.hpp
new file mode 100644
index 00000000000..2ce7c441e45
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_column.hpp
@@ -0,0 +1,120 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_expr_column_hpp
+#define ODBC_CODEGEN_Code_expr_column_hpp
+
+#include <common/common.hpp>
+#include "Code_column.hpp"
+#include "Code_expr.hpp"
+
+class DictColumn;
+class Plan_table;
+
+/**
+ * @class Plan_expr_column
+ * @brief Column in query expression
+ */
+class Plan_expr_column : public Plan_expr, public Plan_column {
+public:
+ Plan_expr_column(Plan_root* root, const BaseString& name);
+ virtual ~Plan_expr_column();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ bool resolveEq(Ctx& ctx, Plan_expr* expr);
+ void print(Ctx& ctx);
+ bool isEqual(const Plan_expr* expr) const;
+ bool isGroupBy(const Plan_expr_row* row) const;
+};
+
+inline
+Plan_expr_column::Plan_expr_column(Plan_root* root, const BaseString& name) :
+ Plan_expr(root, TypeColumn),
+ Plan_column(Type_expr, name)
+{
+}
+
+/**
+ * @class Exec_expr_column
+ * @brief Column in query expression
+ */
+class Exec_expr_column : public Exec_expr {
+public:
+ class Code : public Exec_expr::Code {
+ public:
+ Code(const SqlSpec& sqlSpec, unsigned resOff);
+ virtual ~Code();
+ protected:
+ friend class Exec_expr_column;
+ SqlSpec m_sqlSpec;
+ unsigned m_resOff;
+ };
+ class Data : public Exec_expr::Data {
+ public:
+ Data(SqlField& sqlField);
+ virtual ~Data();
+ protected:
+ friend class Exec_expr_column;
+ // set reference to SqlField in query
+ };
+ Exec_expr_column(Exec_root* root);
+ virtual ~Exec_expr_column();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void evaluate(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+};
+
+inline
+Exec_expr_column::Code::Code(const SqlSpec& sqlSpec, unsigned resOff) :
+ Exec_expr::Code(m_sqlSpec),
+ m_sqlSpec(sqlSpec),
+ m_resOff(resOff)
+{
+}
+
+inline
+Exec_expr_column::Data::Data(SqlField& sqlField) :
+ Exec_expr::Data(sqlField)
+{
+}
+
+inline
+Exec_expr_column::Exec_expr_column(Exec_root* root) :
+ Exec_expr(root)
+{
+}
+
+// children
+
+inline const Exec_expr_column::Code&
+Exec_expr_column::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_expr_column::Data&
+Exec_expr_column::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_const.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_const.cpp
new file mode 100644
index 00000000000..564d307a4f8
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_const.cpp
@@ -0,0 +1,138 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_expr_const.hpp"
+#include "Code_root.hpp"
+
+// Plan_expr_const
+
+Plan_expr_const::~Plan_expr_const()
+{
+}
+
+Plan_base*
+Plan_expr_const::analyze(Ctx& ctx, Ctl& ctl)
+{
+ m_exec = 0;
+ // convert data type
+ m_lexType.convert(ctx, m_sqlType, m_string.length());
+ if (! ctx.ok())
+ return 0;
+ // depends on no tables
+ // set alias name
+ m_alias = m_string;
+ // node was not changed
+ return this;
+}
+
+Exec_base*
+Plan_expr_const::codegen(Ctx& ctx, Ctl& ctl)
+{
+ if (m_exec != 0)
+ return m_exec;
+ // convert data
+ SqlSpec sqlSpec(m_sqlType, SqlSpec::Physical);
+ SqlField sqlField(sqlSpec);
+ LexSpec lexSpec(m_lexType);
+ lexSpec.convert(ctx, m_string, sqlField);
+ if (! ctx.ok())
+ return 0;
+ // create code
+ Exec_expr_const* exec = new Exec_expr_const(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ Exec_expr_const::Code& code = *new Exec_expr_const::Code(sqlField);
+ exec->setCode(code);
+ m_exec = exec;
+ return exec;
+}
+
+void
+Plan_expr_const::print(Ctx& ctx)
+{
+ ctx.print(" [const %s]", m_string.c_str());
+}
+
+bool
+Plan_expr_const::isEqual(const Plan_expr* expr) const
+{
+ ctx_assert(expr != 0);
+ if (expr->type() != Plan_expr::TypeConst)
+ return false;
+ const Plan_expr_const* expr2 = static_cast<const Plan_expr_const*>(expr);
+ if (strcmp(m_string.c_str(), expr2->m_string.c_str()) != 0)
+ return false;
+ return true;
+}
+
+bool
+Plan_expr_const::isGroupBy(const Plan_expr_row* row) const
+{
+ return true;
+}
+
+// Exec_expr_const
+
+Exec_expr_const::Code::~Code()
+{
+}
+
+Exec_expr_const::Data::~Data()
+{
+}
+
+Exec_expr_const::~Exec_expr_const()
+{
+}
+
+void
+Exec_expr_const::alloc(Ctx& ctx, Ctl& ctl)
+{
+ if (m_data != 0)
+ return;
+ // copy the value for const correctness reasons
+ SqlField sqlField(getCode().m_sqlField);
+ Data& data = *new Data(sqlField);
+ setData(data);
+}
+
+void
+Exec_expr_const::evaluate(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ Data& data = getData();
+ if (ctl.m_groupIndex != 0) {
+ SqlField& out = data.groupField(code.sqlSpec().sqlType(), ctl.m_groupIndex, ctl.m_groupInit);
+ data.sqlField().copy(ctx, out);
+ }
+}
+
+void
+Exec_expr_const::close(Ctx& ctx)
+{
+ Data& data = getData();
+ data.m_groupField.clear();
+}
+
+void
+Exec_expr_const::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [");
+ char buf[500];
+ code.m_sqlField.print(buf, sizeof(buf));
+ ctx.print("%s", buf);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_const.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_const.hpp
new file mode 100644
index 00000000000..2e26c637a23
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_const.hpp
@@ -0,0 +1,120 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_expr_const_hpp
+#define ODBC_CODEGEN_Code_expr_const_hpp
+
+#include <common/common.hpp>
+#include <common/DataField.hpp>
+#include "Code_expr.hpp"
+
+/**
+ * @class Plan_expr_const
+ * @brief Constant expression value in PlanTree
+ */
+class Plan_expr_const : public Plan_expr {
+public:
+ Plan_expr_const(Plan_root* root, LexType lexType, const char* value);
+ virtual ~Plan_expr_const();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ bool isEqual(const Plan_expr* expr) const;
+ bool isGroupBy(const Plan_expr_row* row) const;
+protected:
+ // lexical type and token set by the parser
+ LexType m_lexType;
+ BaseString m_string;
+};
+
+inline
+Plan_expr_const::Plan_expr_const(Plan_root* root, LexType lexType, const char* value) :
+ Plan_expr(root, TypeConst),
+ m_lexType(lexType),
+ m_string(value)
+{
+}
+
+/**
+ * @class Exec_expr_const
+ * @brief Constant expression value in ExecTree
+ */
+class Exec_expr_const : public Exec_expr {
+public:
+ class Code : public Exec_expr::Code {
+ public:
+ Code(const SqlField& sqlField);
+ virtual ~Code();
+ protected:
+ friend class Exec_expr_const;
+ const SqlField m_sqlField;
+ };
+ class Data : public Exec_expr::Data {
+ public:
+ Data(SqlField& sqlField);
+ virtual ~Data();
+ protected:
+ friend class Exec_expr_const;
+ SqlField m_sqlField;
+ };
+ Exec_expr_const(Exec_root* root);
+ virtual ~Exec_expr_const();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void evaluate(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+};
+
+inline
+Exec_expr_const::Code::Code(const SqlField& sqlField) :
+ Exec_expr::Code(m_sqlField.sqlSpec()),
+ m_sqlField(sqlField)
+{
+}
+
+inline
+Exec_expr_const::Data::Data(SqlField& sqlField) :
+ Exec_expr::Data(m_sqlField),
+ m_sqlField(sqlField)
+{
+}
+
+inline
+Exec_expr_const::Exec_expr_const(Exec_root* root) :
+ Exec_expr(root)
+{
+}
+
+// children
+
+inline const Exec_expr_const::Code&
+Exec_expr_const::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_expr_const::Data&
+Exec_expr_const::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_conv.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_conv.cpp
new file mode 100644
index 00000000000..bc89482fedc
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_conv.cpp
@@ -0,0 +1,273 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_expr.hpp"
+#include "Code_expr_conv.hpp"
+#include "Code_root.hpp"
+
+// Plan_expr_conv
+
+Plan_expr_conv::~Plan_expr_conv()
+{
+}
+
+Plan_base*
+Plan_expr_conv::analyze(Ctx& ctx, Ctl& ctl)
+{
+ m_exec = 0;
+ const SqlType& t1 = sqlType();
+ ctx_assert(m_expr != 0);
+ m_expr->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ const SqlType& t2 = m_expr->sqlType();
+ if (t2.type() == SqlType::Unbound) {
+ return m_expr;
+ }
+ if (t1.equal(t2)) {
+ return m_expr;
+ }
+ // XXX move to runtime or make table-driven
+ bool ok = false;
+ if (t2.type() == SqlType::Null) {
+ ok = true;
+ } else if (t1.type() == SqlType::Char) {
+ if (t2.type() == SqlType::Char) {
+ ok = true;
+ } else if (t2.type() == SqlType::Varchar) {
+ ok = true;
+ } else if (t2.type() == SqlType::Binary) {
+ ok = true;
+ } else if (t2.type() == SqlType::Varbinary) {
+ ok = true;
+ }
+ } else if (t1.type() == SqlType::Varchar) {
+ if (t2.type() == SqlType::Char) {
+ ok = true;
+ } else if (t2.type() == SqlType::Varchar) {
+ ok = true;
+ } else if (t2.type() == SqlType::Binary) {
+ ok = true;
+ } else if (t2.type() == SqlType::Varbinary) {
+ ok = true;
+ }
+ } else if (t1.type() == SqlType::Binary) {
+ if (t2.type() == SqlType::Char) {
+ ok = true;
+ } else if (t2.type() == SqlType::Varchar) {
+ ok = true;
+ } else if (t2.type() == SqlType::Binary) {
+ ok = true;
+ } else if (t2.type() == SqlType::Varbinary) {
+ ok = true;
+ }
+ } else if (t1.type() == SqlType::Varbinary) {
+ if (t2.type() == SqlType::Char) {
+ ok = true;
+ } else if (t2.type() == SqlType::Varchar) {
+ ok = true;
+ } else if (t2.type() == SqlType::Binary) {
+ ok = true;
+ } else if (t2.type() == SqlType::Varbinary) {
+ ok = true;
+ }
+ } else if (t1.type() == SqlType::Smallint) {
+ if (t2.type() == SqlType::Smallint) {
+ ok = true;
+ } else if (t2.type() == SqlType::Integer) {
+ ok = true;
+ } else if (t2.type() == SqlType::Bigint) {
+ ok = true;
+ } else if (t2.type() == SqlType::Real) {
+ ok = true;
+ } else if (t2.type() == SqlType::Double) {
+ ok = true;
+ }
+ } else if (t1.type() == SqlType::Integer) {
+ if (t2.type() == SqlType::Smallint) {
+ ok = true;
+ } else if (t2.type() == SqlType::Integer) {
+ ok = true;
+ } else if (t2.type() == SqlType::Bigint) {
+ ok = true;
+ } else if (t2.type() == SqlType::Real) {
+ ok = true;
+ } else if (t2.type() == SqlType::Double) {
+ ok = true;
+ }
+ } else if (t1.type() == SqlType::Bigint) {
+ if (t2.type() == SqlType::Smallint) {
+ ok = true;
+ } else if (t2.type() == SqlType::Integer) {
+ ok = true;
+ } else if (t2.type() == SqlType::Bigint) {
+ ok = true;
+ } else if (t2.type() == SqlType::Real) {
+ ok = true;
+ } else if (t2.type() == SqlType::Double) {
+ ok = true;
+ }
+ } else if (t1.type() == SqlType::Real) {
+ if (t2.type() == SqlType::Smallint) {
+ ok = true;
+ } else if (t2.type() == SqlType::Integer) {
+ ok = true;
+ } else if (t2.type() == SqlType::Bigint) {
+ ok = true;
+ } else if (t2.type() == SqlType::Real) {
+ ok = true;
+ } else if (t2.type() == SqlType::Double) {
+ ok = true;
+ }
+ } else if (t1.type() == SqlType::Double) {
+ if (t2.type() == SqlType::Smallint) {
+ ok = true;
+ } else if (t2.type() == SqlType::Integer) {
+ ok = true;
+ } else if (t2.type() == SqlType::Bigint) {
+ ok = true;
+ } else if (t2.type() == SqlType::Real) {
+ ok = true;
+ } else if (t2.type() == SqlType::Double) {
+ ok = true;
+ }
+ } else if (t1.type() == SqlType::Datetime) {
+ if (t2.type() == SqlType::Datetime) {
+ ok = true;
+ }
+ }
+ if (! ok) {
+ char b1[40], b2[40];
+ t1.print(b1, sizeof(b1));
+ t2.print(b2, sizeof(b2));
+ ctx.pushStatus(Error::Gen, "cannot convert %s to %s", b2, b1);
+ return 0;
+ }
+ // depend on same tables
+ const TableSet& ts = m_expr->tableSet();
+ m_tableSet.insert(ts.begin(), ts.end());
+ // set alias
+ m_alias = m_expr->getAlias();
+ return this;
+}
+
+Exec_base*
+Plan_expr_conv::codegen(Ctx& ctx, Ctl& ctl)
+{
+ if (m_exec != 0)
+ return m_exec;
+ Exec_expr_conv* exec = new Exec_expr_conv(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ // create code for subexpression
+ ctx_assert(m_expr != 0);
+ Exec_expr* execExpr = static_cast<Exec_expr*>(m_expr->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ exec->setExpr(execExpr);
+ // create the code
+ SqlSpec sqlSpec(sqlType(), SqlSpec::Physical);
+ Exec_expr_conv::Code& code = *new Exec_expr_conv::Code(sqlSpec);
+ exec->setCode(code);
+ m_exec = exec;
+ return exec;
+}
+
+void
+Plan_expr_conv::print(Ctx& ctx)
+{
+ ctx.print(" [expr_conv ");
+ char buf[100];
+ m_sqlType.print(buf, sizeof(buf));
+ ctx.print("%s", buf);
+ Plan_base* a[] = { m_expr };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
+
+bool
+Plan_expr_conv::isEqual(const Plan_expr* expr) const
+{
+ ctx_assert(expr != 0);
+ if (expr->type() != Plan_expr::TypeConv)
+ return false;
+ const Plan_expr_conv* expr2 = static_cast<const Plan_expr_conv*>(expr);
+ if (! m_sqlType.equal(expr2->m_sqlType))
+ return false;
+ ctx_assert(m_expr != 0 && expr2->m_expr != 0);
+ if (! m_expr->isEqual(expr2->m_expr))
+ return false;
+ return true;
+}
+
+bool
+Plan_expr_conv::isGroupBy(const Plan_expr_row* row) const
+{
+ if (isAnyEqual(row))
+ return true;
+ ctx_assert(m_expr != 0);
+ if (m_expr->isGroupBy(row))
+ return true;
+ return false;
+}
+
+// Code_expr_conv
+
+Exec_expr_conv::Code::~Code()
+{
+}
+
+Exec_expr_conv::Data::~Data()
+{
+}
+
+Exec_expr_conv::~Exec_expr_conv()
+{
+}
+
+void
+Exec_expr_conv::alloc(Ctx& ctx, Ctl& ctl)
+{
+ if (m_data != 0)
+ return;
+ const Code& code = getCode();
+ // allocate subexpression
+ ctx_assert(m_expr != 0);
+ m_expr->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ SqlField sqlField(code.m_sqlSpec);
+ Data& data = *new Data(sqlField);
+ setData(data);
+}
+
+void
+Exec_expr_conv::close(Ctx& ctx)
+{
+ ctx_assert(m_expr != 0);
+ m_expr->close(ctx);
+ Data& data = getData();
+ data.m_groupField.clear();
+}
+
+void
+Exec_expr_conv::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [expr_conv");
+ Exec_base* a[] = { m_expr };
+ printList(ctx, a, sizeof(a)/sizeof(a[0]));
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_conv.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_conv.hpp
new file mode 100644
index 00000000000..3294960c7b3
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_conv.hpp
@@ -0,0 +1,141 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_expr_conv_hpp
+#define ODBC_CODEGEN_Code_expr_conv_hpp
+
+#include <common/common.hpp>
+#include <common/DataField.hpp>
+#include "Code_expr.hpp"
+
+/**
+ * @class Plan_expr_conv
+ * @brief Data type conversion in PlanTree
+ *
+ * Inserted to convert value to another compatible type.
+ */
+class Plan_expr_conv : public Plan_expr {
+public:
+ Plan_expr_conv(Plan_root* root, const SqlType& sqlType);
+ virtual ~Plan_expr_conv();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ bool isEqual(const Plan_expr* expr) const;
+ bool isGroupBy(const Plan_expr_row* row) const;
+ // children
+ void setExpr(Plan_expr* expr);
+protected:
+ Plan_expr* m_expr;
+};
+
+inline
+Plan_expr_conv::Plan_expr_conv(Plan_root* root, const SqlType& sqlType) :
+ Plan_expr(root, TypeConv),
+ m_expr(0)
+{
+ ctx_assert(sqlType.type() != SqlType::Undef);
+ m_sqlType = sqlType;
+}
+
+inline void
+Plan_expr_conv::setExpr(Plan_expr* expr)
+{
+ ctx_assert(expr != 0);
+ m_expr = expr;
+}
+
+/**
+ * @class Exec_expr_conv
+ * @brief Data type conversion in ExecTree
+ */
+class Exec_expr_conv : public Exec_expr {
+public:
+ class Code : public Exec_expr::Code {
+ public:
+ Code(const SqlSpec& spec);
+ virtual ~Code();
+ protected:
+ friend class Exec_expr_conv;
+ const SqlSpec m_sqlSpec;
+ };
+ class Data : public Exec_expr::Data {
+ public:
+ Data(const SqlField& sqlField);
+ virtual ~Data();
+ protected:
+ friend class Exec_expr_conv;
+ SqlField m_sqlField;
+ };
+ Exec_expr_conv(Exec_root* root);
+ virtual ~Exec_expr_conv();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void evaluate(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setExpr(Exec_expr* expr);
+protected:
+ Exec_expr* m_expr;
+};
+
+inline
+Exec_expr_conv::Code::Code(const SqlSpec& sqlSpec) :
+ Exec_expr::Code(m_sqlSpec),
+ m_sqlSpec(sqlSpec)
+{
+}
+
+inline
+Exec_expr_conv::Data::Data(const SqlField& sqlField) :
+ Exec_expr::Data(m_sqlField),
+ m_sqlField(sqlField)
+{
+}
+
+inline
+Exec_expr_conv::Exec_expr_conv(Exec_root* root) :
+ Exec_expr(root),
+ m_expr(0)
+{
+}
+
+// children
+
+inline const Exec_expr_conv::Code&
+Exec_expr_conv::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_expr_conv::Data&
+Exec_expr_conv::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_expr_conv::setExpr(Exec_expr* expr)
+{
+ ctx_assert(m_expr == 0 && expr != 0);
+ m_expr = expr;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_func.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_func.cpp
new file mode 100644
index 00000000000..96b461a72d9
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_func.cpp
@@ -0,0 +1,401 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_expr.hpp"
+#include "Code_expr_func.hpp"
+#include "Code_expr_conv.hpp"
+#include "Code_root.hpp"
+#include "PortDefs.h"
+
+
+// Expr_func
+
+static const struct { const char* alias; const char* name; }
+expr_func_alias[] = {
+ { "SUBSTRING", "SUBSTR" },
+ { 0, 0 }
+};
+
+static const Expr_func
+expr_func[] = {
+ Expr_func(Expr_func::Substr, "SUBSTR", false ),
+ Expr_func(Expr_func::Left, "LEFT", false ),
+ Expr_func(Expr_func::Right, "RIGHT", false ),
+ Expr_func(Expr_func::Count, "COUNT", true ),
+ Expr_func(Expr_func::Max, "MAX", true ),
+ Expr_func(Expr_func::Min, "MIN", true ),
+ Expr_func(Expr_func::Sum, "SUM", true ),
+ Expr_func(Expr_func::Avg, "AVG", true ),
+ Expr_func(Expr_func::Rownum, "ROWNUM", false ),
+ Expr_func(Expr_func::Sysdate, "SYSDATE", false ),
+ Expr_func(Expr_func::Undef, 0, false )
+};
+
+const Expr_func&
+Expr_func::find(const char* name)
+{
+ for (unsigned i = 0; expr_func_alias[i].alias != 0; i++) {
+ if (strcasecmp(expr_func_alias[i].alias, name) == 0) {
+ name = expr_func_alias[i].name;
+ break;
+ }
+ }
+ const Expr_func* p;
+ for (p = expr_func; p->m_name != 0; p++) {
+ if (strcasecmp(p->m_name, name) == 0)
+ break;
+ }
+ return *p;
+}
+
+// Plan_expr_func
+
+Plan_expr_func::~Plan_expr_func()
+{
+ delete[] m_conv;
+ m_conv = 0;
+}
+
+Plan_base*
+Plan_expr_func::analyze(Ctx& ctx, Ctl& ctl)
+{
+ m_exec = 0;
+ ctx_assert(m_narg == 0 || m_args != 0);
+ // aggregate check
+ if (m_func.m_aggr) {
+ if (! ctl.m_aggrok) {
+ ctx.pushStatus(Error::Gen, "%s: invalid use of aggregate function", m_func.m_name);
+ return 0;
+ }
+ if (ctl.m_aggrin) {
+ // XXX actually possible with group-by but too hard
+ ctx.pushStatus(Error::Gen, "%s: nested aggregate function", m_func.m_name);
+ return 0;
+ }
+ ctl.m_aggrin = true;
+ m_isAggr = true;
+ m_isBound = true;
+ }
+ // analyze argument expressions
+ if (m_func.m_code != Expr_func::Rownum)
+ m_isBound = true;
+ for (unsigned i = 1; i <= m_narg; i++) {
+ Plan_expr* expr = m_args->getExpr(i);
+ expr = static_cast<Plan_expr*>(expr->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(expr != 0);
+ if (expr->m_isAggr)
+ m_isAggr = true;
+ if (! m_func.m_aggr && ! expr->m_isBound)
+ m_isBound = false;
+ }
+ if (m_func.m_aggr)
+ ctl.m_aggrin = false;
+ // find result type and conversion types
+ SqlType res;
+ const Expr_func::Code fc = m_func.m_code;
+ const char* const invalidArgCount = "%s: argument count %u is invalid";
+ const char* const invalidArgType = "%s: argument %u has invalid type";
+ if (fc == Expr_func::Substr || fc == Expr_func::Left || fc == Expr_func::Right) {
+ if ((m_narg != (unsigned)2) && (m_narg != (unsigned)(fc == Expr_func::Substr ? 3 : 2))) {
+ ctx.pushStatus(Error::Gen, invalidArgCount, m_func.m_name, m_narg);
+ return 0;
+ }
+ const SqlType& t1 = m_args->getExpr(1)->sqlType();
+ switch (t1.type()) {
+ case SqlType::Char:
+ {
+ // XXX convert to varchar for now to get length right
+ SqlType tx(SqlType::Varchar, t1.length());
+ res = m_conv[1] = tx;
+ }
+ break;
+ case SqlType::Varchar:
+ case SqlType::Unbound:
+ res = m_conv[1] = t1;
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, invalidArgType, m_func.m_name, 1);
+ return 0;
+ }
+ for (unsigned i = 2; i <= m_narg; i++) {
+ const SqlType& t2 = m_args->getExpr(i)->sqlType();
+ switch (t2.type()) {
+ case SqlType::Smallint:
+ case SqlType::Integer:
+ case SqlType::Bigint:
+ case SqlType::Unbound:
+ m_conv[i] = t2;
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, invalidArgType, m_func.m_name, i);
+ return 0;
+ }
+ }
+ } else if (fc == Expr_func::Count) {
+ ctx_assert(m_args != 0);
+ if (m_args->getAsterisk()) {
+ ctx_assert(m_narg == 0);
+ } else {
+ if (m_narg != 1) {
+ ctx.pushStatus(Error::Gen, invalidArgCount, m_func.m_name, m_narg);
+ return 0;
+ }
+ m_conv[1] = m_args->getExpr(1)->sqlType();
+ }
+ res.setType(ctx, SqlType::Bigint);
+ } else if (fc == Expr_func::Min || fc == Expr_func::Max) {
+ if (m_narg != 1) {
+ ctx.pushStatus(Error::Gen, invalidArgCount, m_func.m_name, m_narg);
+ return 0;
+ }
+ const SqlType& t1 = m_args->getExpr(1)->sqlType();
+ res = m_conv[1] = t1;
+ } else if (fc == Expr_func::Sum) {
+ if (m_narg != 1) {
+ ctx.pushStatus(Error::Gen, invalidArgCount, m_func.m_name, m_narg);
+ return 0;
+ }
+ const SqlType& t1 = m_args->getExpr(1)->sqlType();
+ switch (t1.type()) {
+ case SqlType::Smallint:
+ case SqlType::Integer:
+ case SqlType::Bigint:
+ res.setType(ctx, SqlType::Bigint);
+ m_conv[1] = res;
+ break;
+ case SqlType::Real:
+ case SqlType::Double:
+ res.setType(ctx, SqlType::Double);
+ m_conv[1] = res;
+ break;
+ case SqlType::Unbound:
+ res = m_conv[1] = t1;
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, invalidArgType, m_func.m_name, 1);
+ return 0;
+ }
+ } else if (fc == Expr_func::Avg) {
+ if (m_narg != 1) {
+ ctx.pushStatus(Error::Gen, invalidArgCount, m_func.m_name, m_narg);
+ return 0;
+ }
+ const SqlType& t1 = m_args->getExpr(1)->sqlType();
+ switch (t1.type()) {
+ case SqlType::Smallint:
+ case SqlType::Integer:
+ case SqlType::Bigint:
+ case SqlType::Real:
+ case SqlType::Double:
+ res.setType(ctx, SqlType::Double);
+ m_conv[1] = res;
+ break;
+ case SqlType::Unbound:
+ res = m_conv[1] = t1;
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, invalidArgType, m_func.m_name, 1);
+ return 0;
+ }
+ } else if (fc == Expr_func::Rownum) {
+ ctx_assert(m_narg == 0 && m_args == 0);
+ res.setType(ctx, SqlType::Bigint);
+ } else if (fc == Expr_func::Sysdate) {
+ ctx_assert(m_narg == 0 && m_args == 0);
+ res.setType(ctx, SqlType::Datetime);
+ } else {
+ ctx_assert(false);
+ }
+ // insert required conversions
+ for (unsigned i = 1; i <= m_narg; i++) {
+ if (m_conv[i].type() == SqlType::Unbound) {
+ // parameter type not yet bound
+ continue;
+ }
+ Plan_expr_conv* exprConv = new Plan_expr_conv(m_root, m_conv[i]);
+ m_root->saveNode(exprConv);
+ exprConv->setExpr(m_args->getExpr(i));
+ Plan_expr* expr = static_cast<Plan_expr*>(exprConv->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ m_args->setExpr(i, expr);
+ }
+ // set result type
+ m_sqlType = res;
+ // set table dependencies
+ for (unsigned i = 1; i <= m_narg; i++) {
+ const TableSet& ts = m_args->getExpr(i)->tableSet();
+ m_tableSet.insert(ts.begin(), ts.end());
+ }
+ // set alias name
+ m_alias.assign(m_func.m_name);
+ if (m_narg == 0) {
+ if (fc == Expr_func::Count)
+ m_alias.append("(*)");
+ } else {
+ m_alias.append("(");
+ for (unsigned i = 1; i <= m_narg; i++) {
+ if (i > 1)
+ m_alias.append(",");
+ m_alias.append(m_args->getExpr(i)->getAlias());
+ }
+ m_alias.append(")");
+ }
+ return this;
+}
+
+Exec_base*
+Plan_expr_func::codegen(Ctx& ctx, Ctl& ctl)
+{
+ if (m_exec != 0)
+ return m_exec;
+ Exec_expr_func* exec = new Exec_expr_func(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ SqlSpec sqlSpec(sqlType(), SqlSpec::Physical);
+ Exec_expr_func::Code& code = *new Exec_expr_func::Code(m_func, sqlSpec);
+ exec->setCode(code);
+ code.m_narg = m_narg;
+ code.m_args = new Exec_expr* [1 + m_narg];
+ for (unsigned i = 0; i <= m_narg; i++)
+ code.m_args[i] = 0;
+ // create code for arguments
+ for (unsigned i = 1; i <= m_narg; i++) {
+ Plan_expr* expr = m_args->getExpr(i);
+ ctx_assert(expr != 0);
+ Exec_expr* execExpr = static_cast<Exec_expr*>(expr->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execExpr != 0);
+ code.m_args[i] = execExpr;
+ }
+ m_exec = exec;
+ return exec;
+}
+
+void
+Plan_expr_func::print(Ctx& ctx)
+{
+ ctx.print(" [%s", m_func.m_name);
+ Plan_base* a[] = { m_args };
+ printList(ctx, a, sizeof(a)/sizeof(a[1]));
+ ctx.print("]");
+}
+
+bool
+Plan_expr_func::isEqual(const Plan_expr* expr) const
+{
+ ctx_assert(expr != 0);
+ if (expr->type() != Plan_expr::TypeFunc)
+ return false;
+ const Plan_expr_func* expr2 = static_cast<const Plan_expr_func*>(expr);
+ if (m_func.m_code != expr2->m_func.m_code)
+ return false;
+ if (m_narg != expr2->m_narg)
+ return false;
+ ctx_assert(m_args != 0 && expr2->m_args != 0);
+ for (unsigned i = 1; i <= m_narg; i++) {
+ if (! m_args->getExpr(i)->isEqual(expr2->m_args->getExpr(i)))
+ return false;
+ }
+ return true;
+}
+
+bool
+Plan_expr_func::isGroupBy(const Plan_expr_row* row) const
+{
+ if (m_func.m_aggr)
+ return true;
+ switch (m_func.m_code) {
+ case Expr_func::Substr:
+ case Expr_func::Left:
+ case Expr_func::Right:
+ ctx_assert(m_narg >= 1);
+ if (m_args->getExpr(1)->isGroupBy(row))
+ return true;
+ break;
+ case Expr_func::Sysdate:
+ return true;
+ default:
+ break;
+ }
+ if (isAnyEqual(row))
+ return true;
+ return false;
+}
+
+// Exec_expr_func
+
+Exec_expr_func::Code::~Code()
+{
+ delete[] m_args;
+ m_args = 0;
+}
+
+Exec_expr_func::Data::~Data()
+{
+}
+
+Exec_expr_func::~Exec_expr_func()
+{
+}
+
+void
+Exec_expr_func::alloc(Ctx& ctx, Ctl& ctl)
+{
+ if (m_data != 0)
+ return;
+ const Code& code = getCode();
+ // allocate arguments
+ for (unsigned i = 1; i <= code.m_narg; i++) {
+ ctx_assert(code.m_args != 0 && code.m_args[i] != 0);
+ code.m_args[i]->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ }
+ SqlField sqlField(code.m_sqlSpec);
+ Data& data = *new Data(sqlField);
+ setData(data);
+ ctx_assert(ctl.m_groupIndex == 0);
+ init(ctx, ctl);
+}
+
+void
+Exec_expr_func::close(Ctx& ctx)
+{
+ const Code& code = getCode();
+ Data& data = getData();
+ for (unsigned i = 1; i <= code.m_narg; i++) {
+ ctx_assert(code.m_args != 0 && code.m_args[i] != 0);
+ code.m_args[i]->close(ctx);
+ }
+ data.m_groupField.clear();
+ Ctl ctl(0);
+ init(ctx, ctl);
+}
+
+void
+Exec_expr_func::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [%s", code.m_func.m_name);
+ for (unsigned i = 1; i <= code.m_narg; i++) {
+ Exec_base* a[] = { code.m_args[i] };
+ printList(ctx, a, sizeof(a)/sizeof(a[0]));
+ }
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_func.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_func.hpp
new file mode 100644
index 00000000000..856d7529875
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_func.hpp
@@ -0,0 +1,193 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_expr_func_hpp
+#define ODBC_CODEGEN_Code_expr_func_hpp
+
+#include <common/common.hpp>
+#include <common/DataField.hpp>
+#include "Code_expr.hpp"
+#include "Code_expr_row.hpp"
+
+/**
+ * @class Expr_func
+ * @brief Specifies a function
+ */
+struct Expr_func {
+ enum Code {
+ Undef = 0,
+ Substr,
+ Left,
+ Right,
+ Count,
+ Max,
+ Min,
+ Sum,
+ Avg,
+ Rownum,
+ Sysdate
+ };
+ Expr_func(Code code, const char* name, bool aggr);
+ Code m_code;
+ const char* m_name;
+ bool m_aggr;
+ static const Expr_func& find(const char* name);
+};
+
+inline
+Expr_func::Expr_func(Code code, const char* name, bool aggr) :
+ m_code(code),
+ m_name(name),
+ m_aggr(aggr)
+{
+}
+
+/**
+ * @class Plan_expr_func
+ * @brief Function node in an expression in PlanTree
+ */
+class Plan_expr_func : public Plan_expr {
+public:
+ Plan_expr_func(Plan_root* root, const Expr_func& func);
+ virtual ~Plan_expr_func();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ bool isEqual(const Plan_expr* expr) const;
+ bool isGroupBy(const Plan_expr_row* row) const;
+ // children
+ void setArgs(Plan_expr_row* args);
+protected:
+ const Expr_func& m_func;
+ Plan_expr_row* m_args;
+ unsigned m_narg;
+ SqlType* m_conv; // temp work area
+};
+
+inline
+Plan_expr_func::Plan_expr_func(Plan_root* root, const Expr_func& func) :
+ Plan_expr(root, TypeFunc),
+ m_func(func),
+ m_args(0),
+ m_narg(0),
+ m_conv(0)
+{
+}
+
+inline void
+Plan_expr_func::setArgs(Plan_expr_row* args)
+{
+ if (args == 0) {
+ m_args = 0;
+ m_narg = 0;
+ } else {
+ m_args = args;
+ m_narg = m_args->getSize();
+ delete[] m_conv;
+ m_conv = new SqlType[1 + m_narg];
+ }
+}
+
+/**
+ * @class Exec_expr_func
+ * @brief Function node in an expression in ExecTree
+ */
+class Exec_expr_func : public Exec_expr {
+public:
+ class Code : public Exec_expr::Code {
+ public:
+ Code(const Expr_func& func, const SqlSpec& spec);
+ virtual ~Code();
+ protected:
+ friend class Plan_expr_func;
+ friend class Exec_expr_func;
+ const Expr_func& m_func;
+ const SqlSpec m_sqlSpec;
+ unsigned m_narg;
+ Exec_expr** m_args; // XXX pointers for now
+ };
+ class Data : public Exec_expr::Data {
+ public:
+ Data(const SqlField& sqlField);
+ virtual ~Data();
+ protected:
+ friend class Exec_expr_func;
+ SqlField m_sqlField;
+ struct Acc { // accumulators etc
+ SqlBigint m_count; // current row count
+ union {
+ SqlBigint m_bigint;
+ SqlDouble m_double;
+ SqlDatetime m_sysdate;
+ };
+ };
+ // group-by extra accumulators (default in entry 0)
+ typedef std::vector<Acc> GroupAcc;
+ GroupAcc m_groupAcc;
+ };
+ Exec_expr_func(Exec_root* root);
+ virtual ~Exec_expr_func();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void evaluate(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+protected:
+ void init(Ctx &ctx, Ctl& ctl); // initialize values
+};
+
+inline
+Exec_expr_func::Code::Code(const Expr_func& func, const SqlSpec& sqlSpec) :
+ Exec_expr::Code(m_sqlSpec),
+ m_func(func),
+ m_sqlSpec(sqlSpec),
+ m_args(0)
+{
+}
+
+inline
+Exec_expr_func::Data::Data(const SqlField& sqlField) :
+ Exec_expr::Data(m_sqlField),
+ m_sqlField(sqlField),
+ m_groupAcc(1)
+{
+}
+
+inline
+Exec_expr_func::Exec_expr_func(Exec_root* root) :
+ Exec_expr(root)
+{
+}
+
+// children
+
+inline const Exec_expr_func::Code&
+Exec_expr_func::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_expr_func::Data&
+Exec_expr_func::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_op.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_op.cpp
new file mode 100644
index 00000000000..7e8314c1741
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_op.cpp
@@ -0,0 +1,424 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_expr.hpp"
+#include "Code_expr_op.hpp"
+#include "Code_expr_conv.hpp"
+#include "Code_root.hpp"
+
+// Expr_op
+
+const char*
+Expr_op::name() const
+{
+ switch (m_opcode) {
+ case Add:
+ return "+";
+ case Subtract:
+ return "-";
+ case Multiply:
+ return "*";
+ case Divide:
+ return "/";
+ case Plus:
+ return "+";
+ case Minus:
+ return "-";
+ }
+ ctx_assert(false);
+ return "";
+}
+
+unsigned
+Expr_op::arity() const
+{
+ switch (m_opcode) {
+ case Add:
+ case Subtract:
+ case Multiply:
+ case Divide:
+ return 2;
+ case Plus:
+ case Minus:
+ return 1;
+ }
+ ctx_assert(false);
+ return 0;
+}
+
+// Plan_expr_op
+
+Plan_expr_op::~Plan_expr_op()
+{
+}
+
+Plan_base*
+Plan_expr_op::analyze(Ctx& ctx, Ctl& ctl)
+{
+ m_exec = 0;
+ unsigned arity = m_op.arity();
+ // analyze operands
+ m_isAggr = false;
+ m_isBound = true;
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_expr[i] != 0);
+ m_expr[i]->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ if (m_expr[i]->m_isAggr)
+ m_isAggr = true;
+ if (! m_expr[i]->m_isBound)
+ m_isBound = false;
+ }
+ // find result type and conversion types (currently same)
+ SqlType res;
+ SqlType con[1 + 2];
+ if (arity == 1) {
+ const SqlType& t1 = m_expr[1]->sqlType();
+ switch (t1.type()) {
+ case SqlType::Char:
+ case SqlType::Varchar:
+ break;
+ case SqlType::Smallint:
+ case SqlType::Integer:
+ case SqlType::Bigint:
+ res.setType(ctx, SqlType::Bigint);
+ con[1] = res;
+ break;
+ case SqlType::Real:
+ case SqlType::Double:
+ res.setType(ctx, SqlType::Double);
+ con[1] = res;
+ break;
+ case SqlType::Null:
+ res.setType(ctx, SqlType::Null);
+ con[1] = res;
+ break;
+ case SqlType::Unbound:
+ res.setType(ctx, SqlType::Unbound);
+ con[1] = res;
+ default:
+ break;
+ }
+ if (con[1].type() == SqlType::Undef) {
+ char b1[40];
+ t1.print(b1, sizeof(b1));
+ ctx.pushStatus(Error::Gen, "type mismatch in operation: %s %s", m_op.name(), b1);
+ return 0;
+ }
+ } else if (arity == 2) {
+ const SqlType& t1 = m_expr[1]->sqlType();
+ const SqlType& t2 = m_expr[2]->sqlType();
+ switch (t1.type()) {
+ case SqlType::Char: // handle char types as in oracle
+ switch (t2.type()) {
+ case SqlType::Char:
+ res.setType(ctx, SqlType::Char, t1.length() + t2.length());
+ con[1] = t1;
+ con[2] = t2;
+ break;
+ case SqlType::Varchar:
+ res.setType(ctx, SqlType::Varchar, t1.length() + t2.length());
+ con[1] = t1;
+ con[2] = t2;
+ break;
+ case SqlType::Null:
+ res.setType(ctx, SqlType::Varchar, t1.length());
+ con[1] = t1;
+ con[2] = t2;
+ break;
+ case SqlType::Unbound:
+ res.setType(ctx, SqlType::Unbound);
+ con[1] = con[2] = res;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SqlType::Varchar:
+ switch (t2.type()) {
+ case SqlType::Char:
+ res.setType(ctx, SqlType::Varchar, t1.length() + t2.length());
+ con[1] = t1;
+ con[2] = t2;
+ break;
+ case SqlType::Varchar:
+ res.setType(ctx, SqlType::Varchar, t1.length() + t2.length());
+ con[1] = t1;
+ con[2] = t2;
+ break;
+ case SqlType::Null:
+ res.setType(ctx, SqlType::Varchar, t1.length());
+ con[1] = t1;
+ con[2] = t2;
+ break;
+ case SqlType::Unbound:
+ res.setType(ctx, SqlType::Unbound);
+ con[1] = con[2] = res;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SqlType::Smallint:
+ case SqlType::Integer:
+ case SqlType::Bigint:
+ switch (t2.type()) {
+ case SqlType::Smallint:
+ case SqlType::Integer:
+ case SqlType::Bigint:
+ res.setType(ctx, SqlType::Bigint);
+ con[1] = con[2] = res;
+ if (t1.unSigned() || t2.unSigned()) {
+ con[1].unSigned(true);
+ con[2].unSigned(true);
+ }
+ break;
+ case SqlType::Real:
+ case SqlType::Double:
+ res.setType(ctx, SqlType::Double);
+ con[1] = con[2] = res;
+ break;
+ case SqlType::Null:
+ res.setType(ctx, SqlType::Null);
+ con[1] = con[2] = res;
+ break;
+ case SqlType::Unbound:
+ res.setType(ctx, SqlType::Unbound);
+ con[1] = con[2] = res;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SqlType::Real:
+ case SqlType::Double:
+ switch (t2.type()) {
+ case SqlType::Smallint:
+ case SqlType::Integer:
+ case SqlType::Bigint:
+ case SqlType::Real:
+ case SqlType::Double:
+ res.setType(ctx, SqlType::Double);
+ con[1] = con[2] = res;
+ break;
+ case SqlType::Null:
+ res.setType(ctx, SqlType::Null);
+ con[1] = con[2] = res;
+ break;
+ case SqlType::Unbound:
+ res.setType(ctx, SqlType::Unbound);
+ con[1] = con[2] = res;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SqlType::Null:
+ switch (t2.type()) {
+ case SqlType::Char:
+ case SqlType::Varchar:
+ res.setType(ctx, SqlType::Varchar, t2.length());
+ con[1] = con[2] = res;
+ break;
+ case SqlType::Unbound:
+ res.setType(ctx, SqlType::Unbound);
+ con[1] = con[2] = res;
+ break;
+ default:
+ res.setType(ctx, SqlType::Null);
+ con[1] = con[2] = res;
+ break;
+ }
+ break;
+ case SqlType::Unbound:
+ res.setType(ctx, SqlType::Unbound);
+ con[1] = con[2] = res;
+ break;
+ default:
+ break;
+ }
+ if (con[1].type() == SqlType::Undef || con[2].type() == SqlType::Undef) {
+ char b1[40], b2[40];
+ t1.print(b1, sizeof(b1));
+ t2.print(b2, sizeof(b2));
+ ctx.pushStatus(Error::Gen, "type mismatch in operation: %s %s %s", b1, m_op.name(), b2);
+ return 0;
+ }
+ } else {
+ ctx_assert(false);
+ return 0;
+ }
+ if (! ctx.ok())
+ return 0;
+ // insert required conversions
+ for (unsigned i = 1; i <= arity; i++) {
+ if (con[i].type() == SqlType::Undef) {
+ ctx.pushStatus(Error::Gen, "mismatched types in operation");
+ return 0;
+ }
+ if (con[i].type() == SqlType::Unbound) {
+ // parameter type not yet bound
+ continue;
+ }
+ Plan_expr_conv* exprConv = new Plan_expr_conv(m_root, con[i]);
+ m_root->saveNode(exprConv);
+ exprConv->setExpr(m_expr[i]);
+ m_expr[i] = static_cast<Plan_expr*>(exprConv->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_expr[i] != 0);
+ }
+ // set result type
+ m_sqlType = res;
+ // table dependencies are union from operands
+ for (unsigned i = 1; i <= arity; i++) {
+ const TableSet& ts = m_expr[i]->tableSet();
+ m_tableSet.insert(ts.begin(), ts.end());
+ }
+ // set alias name XXX misses operator precedence
+ if (arity == 1) {
+ m_alias.assign(m_op.name());
+ m_alias.append(m_expr[1]->m_alias);
+ } else if (arity == 2) {
+ m_alias.assign(m_expr[1]->m_alias);
+ m_alias.append(m_op.name());
+ m_alias.append(m_expr[2]->m_alias);
+ }
+ return this;
+}
+
+Exec_base*
+Plan_expr_op::codegen(Ctx& ctx, Ctl& ctl)
+{
+ if (m_exec != 0)
+ return m_exec;
+ unsigned arity = m_op.arity();
+ Exec_expr_op* exec = new Exec_expr_op(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ // create code for operands
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_expr[i] != 0);
+ Exec_expr* execExpr = static_cast<Exec_expr*>(m_expr[i]->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execExpr != 0);
+ exec->setExpr(i, execExpr);
+ }
+ // create the code
+ SqlSpec sqlSpec(sqlType(), SqlSpec::Physical);
+ Exec_expr_op::Code& code = *new Exec_expr_op::Code(m_op, sqlSpec);
+ exec->setCode(code);
+ m_exec = exec;
+ return exec;
+}
+
+void
+Plan_expr_op::print(Ctx& ctx)
+{
+ ctx.print(" [%s", m_op.name());
+ Plan_base* a[] = { m_expr[1], m_expr[2] };
+ printList(ctx, a, m_op.arity());
+ ctx.print("]");
+}
+
+bool
+Plan_expr_op::isEqual(const Plan_expr* expr) const
+{
+ ctx_assert(expr != 0);
+ if (expr->type() != Plan_expr::TypeOp)
+ return false;
+ const Plan_expr_op* expr2 = static_cast<const Plan_expr_op*>(expr);
+ if (m_op.m_opcode != expr2->m_op.m_opcode)
+ return false;
+ const unsigned arity = m_op.arity();
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_expr[i] != 0);
+ if (! m_expr[i]->isEqual(expr2->m_expr[i]))
+ return false;
+ }
+ return true;
+}
+
+bool
+Plan_expr_op::isGroupBy(const Plan_expr_row* row) const
+{
+ if (isAnyEqual(row))
+ return true;
+ const unsigned arity = m_op.arity();
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_expr[i] != 0);
+ if (! m_expr[i]->isGroupBy(row))
+ return false;
+ }
+ return true;
+}
+
+// Code_expr_op
+
+Exec_expr_op::Code::~Code()
+{
+}
+
+Exec_expr_op::Data::~Data()
+{
+}
+
+Exec_expr_op::~Exec_expr_op()
+{
+}
+
+void
+Exec_expr_op::alloc(Ctx& ctx, Ctl& ctl)
+{
+ if (m_data != 0)
+ return;
+ const Code& code = getCode();
+ // allocate subexpressions
+ unsigned arity = code.m_op.arity();
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_expr[i] != 0);
+ m_expr[i]->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ }
+ SqlField sqlField(code.m_sqlSpec);
+ Data& data = *new Data(sqlField);
+ setData(data);
+}
+
+void
+Exec_expr_op::close(Ctx& ctx)
+{
+ const Code& code = getCode();
+ unsigned arity = code.m_op.arity();
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_expr[i] != 0);
+ m_expr[i]->close(ctx);
+ }
+ Data& data = getData();
+ data.m_groupField.clear();
+}
+
+void
+Exec_expr_op::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [%s", code.m_op.name());
+ Exec_base* a[] = { m_expr[1], m_expr[2] };
+ printList(ctx, a, code.m_op.arity());
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_op.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_op.hpp
new file mode 100644
index 00000000000..f9686cad151
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_op.hpp
@@ -0,0 +1,166 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_expr_op_hpp
+#define ODBC_CODEGEN_Code_expr_op_hpp
+
+#include <common/common.hpp>
+#include <common/DataField.hpp>
+#include "Code_expr.hpp"
+
+/**
+ * @class Expr_op
+ * @brief Arithmetic and string operators
+ */
+struct Expr_op {
+ enum Opcode {
+ Add = 1, // binary
+ Subtract,
+ Multiply,
+ Divide,
+ Plus, // unary
+ Minus
+ };
+ Expr_op(Opcode opcode);
+ const char* name() const;
+ unsigned arity() const;
+ Opcode m_opcode;
+};
+
+inline
+Expr_op::Expr_op(Opcode opcode) :
+ m_opcode(opcode)
+{
+}
+
+/**
+ * @class Plan_expr_op
+ * @brief Operator node in an expression in PlanTree
+ */
+class Plan_expr_op : public Plan_expr {
+public:
+ Plan_expr_op(Plan_root* root, Expr_op op);
+ virtual ~Plan_expr_op();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ bool isEqual(const Plan_expr* expr) const;
+ bool isGroupBy(const Plan_expr_row* row) const;
+ // children
+ void setExpr(unsigned i, Plan_expr* expr);
+protected:
+ Expr_op m_op;
+ Plan_expr* m_expr[1 + 2];
+};
+
+inline
+Plan_expr_op::Plan_expr_op(Plan_root* root, Expr_op op) :
+ Plan_expr(root, TypeOp),
+ m_op(op)
+{
+ m_expr[0] = m_expr[1] = m_expr[2] = 0;
+}
+
+inline void
+Plan_expr_op::setExpr(unsigned i, Plan_expr* expr)
+{
+ ctx_assert(1 <= i && i <= 2 && expr != 0);
+ m_expr[i] = expr;
+}
+
+/**
+ * @class Exec_expr_op
+ * @brief Operator node in an expression in ExecTree
+ */
+class Exec_expr_op : public Exec_expr {
+public:
+ class Code : public Exec_expr::Code {
+ public:
+ Code(Expr_op op, const SqlSpec& spec);
+ virtual ~Code();
+ protected:
+ friend class Exec_expr_op;
+ Expr_op m_op;
+ const SqlSpec m_sqlSpec;
+ };
+ class Data : public Exec_expr::Data {
+ public:
+ Data(const SqlField& sqlField);
+ virtual ~Data();
+ protected:
+ friend class Exec_expr_op;
+ SqlField m_sqlField;
+ };
+ Exec_expr_op(Exec_root* root);
+ virtual ~Exec_expr_op();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void evaluate(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setExpr(unsigned i, Exec_expr* expr);
+protected:
+ Exec_expr* m_expr[1 + 2];
+};
+
+inline
+Exec_expr_op::Code::Code(Expr_op op, const SqlSpec& sqlSpec) :
+ Exec_expr::Code(m_sqlSpec),
+ m_op(op),
+ m_sqlSpec(sqlSpec)
+{
+}
+
+inline
+Exec_expr_op::Data::Data(const SqlField& sqlField) :
+ Exec_expr::Data(m_sqlField),
+ m_sqlField(sqlField)
+{
+}
+
+inline
+Exec_expr_op::Exec_expr_op(Exec_root* root) :
+ Exec_expr(root)
+{
+ m_expr[0] = m_expr[1] = m_expr[2] = 0;
+}
+
+// children
+
+inline const Exec_expr_op::Code&
+Exec_expr_op::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_expr_op::Data&
+Exec_expr_op::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_expr_op::setExpr(unsigned i, Exec_expr* expr)
+{
+ ctx_assert(1 <= i && i <= 2 && m_expr[i] == 0);
+ m_expr[i] = expr;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_param.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_param.cpp
new file mode 100644
index 00000000000..93892cae5e6
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_param.cpp
@@ -0,0 +1,279 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_expr_param.hpp"
+#include "Code_root.hpp"
+
+// Plan_expr_param
+
+Plan_expr_param::~Plan_expr_param()
+{
+}
+
+Plan_base*
+Plan_expr_param::analyze(Ctx& ctx, Ctl& ctl)
+{
+ m_exec = 0;
+ ctx_assert(m_paramNumber != 0);
+ ctx_assert(m_paramNumber < m_root->m_paramList.size());
+ m_root->m_paramList[m_paramNumber] = this;
+ m_sqlType.setType(ctx, SqlType::Unbound);
+ // check if type is bound now
+ DescArea& ipd = descArea(Desc_usage_IPD);
+ if (m_paramNumber <= ipd.getCount()) {
+ DescRec& rec = ipd.getRecord(m_paramNumber);
+ OdbcData descData;
+ rec.getField(ctx, SQL_DESC_TYPE, descData);
+ if (descData.type() != OdbcData::Undef) {
+ SQLSMALLINT desc_TYPE = descData.smallint();
+ // XXX wrong but fixes sun.jdbc.odbc
+ if (desc_TYPE == SQL_CHAR)
+ desc_TYPE = SQL_VARCHAR;
+ if (desc_TYPE == SQL_CHAR) {
+ rec.getField(ctx, SQL_DESC_LENGTH, descData);
+ if (descData.type() != OdbcData::Undef) {
+ unsigned desc_LENGTH = descData.uinteger();
+ m_sqlType.setType(ctx, SqlType::Char, desc_LENGTH);
+ }
+ } else if (desc_TYPE == SQL_VARCHAR) {
+ rec.getField(ctx, SQL_DESC_LENGTH, descData);
+ if (descData.type() != OdbcData::Undef) {
+ unsigned desc_LENGTH = descData.uinteger();
+ m_sqlType.setType(ctx, SqlType::Varchar, desc_LENGTH);
+ }
+ } else if (desc_TYPE == SQL_BINARY) {
+ rec.getField(ctx, SQL_DESC_LENGTH, descData);
+ if (descData.type() != OdbcData::Undef) {
+ unsigned desc_LENGTH = descData.uinteger();
+ m_sqlType.setType(ctx, SqlType::Binary, desc_LENGTH);
+ }
+ } else if (desc_TYPE == SQL_VARBINARY) {
+ rec.getField(ctx, SQL_DESC_LENGTH, descData);
+ if (descData.type() != OdbcData::Undef) {
+ unsigned desc_LENGTH = descData.uinteger();
+ m_sqlType.setType(ctx, SqlType::Varbinary, desc_LENGTH);
+ } else {
+ // XXX BLOB hack
+ unsigned desc_LENGTH = FAKE_BLOB_SIZE;
+ m_sqlType.setType(ctx, SqlType::Varbinary, desc_LENGTH);
+ }
+ } else if (desc_TYPE == SQL_SMALLINT) {
+ m_sqlType.setType(ctx, SqlType::Smallint);
+ } else if (desc_TYPE == SQL_INTEGER) {
+ m_sqlType.setType(ctx, SqlType::Integer);
+ } else if (desc_TYPE == SQL_BIGINT) {
+ m_sqlType.setType(ctx, SqlType::Bigint);
+ } else if (desc_TYPE == SQL_REAL) {
+ m_sqlType.setType(ctx, SqlType::Real);
+ } else if (desc_TYPE == SQL_DOUBLE) {
+ m_sqlType.setType(ctx, SqlType::Double);
+ } else if (desc_TYPE == SQL_TYPE_TIMESTAMP) {
+ m_sqlType.setType(ctx, SqlType::Datetime);
+ // XXX BLOB hack
+ } else if (desc_TYPE == SQL_LONGVARBINARY) {
+ m_sqlType.setType(ctx, SqlType::Varbinary, (unsigned)FAKE_BLOB_SIZE);
+ } else {
+ ctx.pushStatus(Error::Gen, "parameter %u unsupported SQL type %d", m_paramNumber, (int)desc_TYPE);
+ return 0;
+ }
+ char buf[100];
+ m_sqlType.print(buf, sizeof(buf));
+ ctx_log2(("parameter %u SQL type bound to %s", m_paramNumber, buf));
+ }
+ }
+ return this;
+}
+
+void
+Plan_expr_param::describe(Ctx& ctx)
+{
+ DescArea& ipd = descArea(Desc_usage_IPD);
+ if (ipd.getCount() < m_paramNumber)
+ ipd.setCount(ctx, m_paramNumber);
+ // XXX describe if possible
+ DescRec& rec = ipd.getRecord(m_paramNumber);
+}
+
+Exec_base*
+Plan_expr_param::codegen(Ctx& ctx, Ctl& ctl)
+{
+ if (m_exec != 0)
+ return m_exec;
+ SqlSpec sqlSpec(m_sqlType, SqlSpec::Physical);
+ // create code
+ Exec_expr_param* exec = new Exec_expr_param(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ ctx_assert(m_paramNumber != 0);
+ Exec_expr_param::Code& code = *new Exec_expr_param::Code(sqlSpec, m_paramNumber);
+ exec->setCode(code);
+ m_exec = exec;
+ return exec;
+}
+
+void
+Plan_expr_param::print(Ctx& ctx)
+{
+ ctx.print(" [param %u]", m_paramNumber);
+}
+
+bool
+Plan_expr_param::isEqual(const Plan_expr* expr) const
+{
+ ctx_assert(expr != 0);
+ if (expr->type() != Plan_expr::TypeParam)
+ return false;
+ const Plan_expr_param* expr2 = static_cast<const Plan_expr_param*>(expr);
+ // params are not equal ever
+ return false;
+}
+
+bool
+Plan_expr_param::isGroupBy(const Plan_expr_row* row) const
+{
+ // params are constants
+ return true;
+}
+
+// Exec_expr_param
+
+Exec_expr_param::Code::~Code()
+{
+}
+
+Exec_expr_param::Data::~Data()
+{
+ delete m_extField;
+ m_extField = 0;
+}
+
+Exec_expr_param::~Exec_expr_param()
+{
+}
+
+void
+Exec_expr_param::alloc(Ctx& ctx, Ctl& ctl)
+{
+ if (m_data != 0)
+ return;
+ const Code& code = getCode();
+ SqlField sqlField(code.sqlSpec());
+ Data& data = *new Data(sqlField);
+ setData(data);
+}
+
+void
+Exec_expr_param::bind(Ctx& ctx)
+{
+ const Code& code = getCode();
+ Data& data = getData();
+ DescArea& apd = descArea(Desc_usage_APD);
+ if (apd.getCount() < code.m_paramNumber) {
+ ctx_log1(("parameter %u is not bound", code.m_paramNumber));
+ return;
+ }
+ const unsigned paramNumber = code.m_paramNumber;
+ DescRec& rec = apd.getRecord(paramNumber);
+ OdbcData descData;
+ // create type
+ rec.getField(ctx, SQL_DESC_TYPE, descData);
+ if (descData.type() == OdbcData::Undef) {
+ ctx.pushStatus(Error::Gen, "parameter %u external type not defined", paramNumber);
+ return;
+ }
+ ExtType extType;
+ SQLSMALLINT desc_TYPE = descData.smallint();
+ switch (desc_TYPE) {
+ case SQL_C_CHAR:
+ case SQL_C_SHORT: // for sun.jdbc.odbc
+ case SQL_C_SSHORT:
+ case SQL_C_USHORT:
+ case SQL_C_LONG: // for sun.jdbc.odbc
+ case SQL_C_SLONG:
+ case SQL_C_ULONG:
+ case SQL_C_SBIGINT:
+ case SQL_C_UBIGINT:
+ case SQL_C_FLOAT:
+ case SQL_C_DOUBLE:
+ case SQL_C_TYPE_TIMESTAMP:
+ case SQL_C_BINARY: // XXX BLOB hack
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, "parameter %u unsupported external type %d", paramNumber, (int)desc_TYPE);
+ return;
+ }
+ extType.setType(ctx, static_cast<ExtType::Type>(desc_TYPE));
+ ExtSpec extSpec(extType);
+ // create data field
+ rec.getField(ctx, SQL_DESC_DATA_PTR, descData);
+ if (descData.type() == OdbcData::Undef) {
+ ctx.pushStatus(Error::Gen, "parameter %u data address not defined", paramNumber);
+ return;
+ }
+ SQLPOINTER desc_DATA_PTR = descData.pointer();
+ rec.getField(ctx, SQL_DESC_OCTET_LENGTH, descData);
+ if (descData.type() == OdbcData::Undef) {
+ ctx.pushStatus(Error::Gen, "parameter %u data length not defined", paramNumber);
+ return;
+ }
+ SQLINTEGER desc_OCTET_LENGTH = descData.integer();
+ rec.getField(ctx, SQL_DESC_INDICATOR_PTR, descData);
+ if (descData.type() == OdbcData::Undef) {
+ ctx.pushStatus(Error::Gen, "parameter %u indicator address not defined", paramNumber);
+ return;
+ }
+ SQLINTEGER* desc_INDICATOR_PTR = descData.integerPtr();
+ ctx_log4(("parameter %u bind to 0x%x %d 0x%x", paramNumber, (unsigned)desc_DATA_PTR, (int)desc_OCTET_LENGTH, (unsigned)desc_INDICATOR_PTR));
+ ExtField& extField = *new ExtField(extSpec, desc_DATA_PTR, desc_OCTET_LENGTH, desc_INDICATOR_PTR, paramNumber);
+ data.m_atExec = false;
+ if (desc_INDICATOR_PTR != 0 && *desc_INDICATOR_PTR < 0) {
+ if (*desc_INDICATOR_PTR == SQL_NULL_DATA) {
+ ;
+ } else if (*desc_INDICATOR_PTR == SQL_DATA_AT_EXEC) {
+ data.m_atExec = true;
+ } else if (*desc_INDICATOR_PTR <= SQL_LEN_DATA_AT_EXEC(0)) {
+ data.m_atExec = true;
+ }
+ }
+ delete data.m_extField;
+ data.m_extField = &extField;
+}
+
+void
+Exec_expr_param::evaluate(Ctx& ctx, Ctl& ctl)
+{
+ if (ctl.m_postEval)
+ return;
+ const Code& code = getCode();
+ Data& data = getData();
+ if (data.m_atExec)
+ return;
+ ctx_assert(data.m_extField != 0);
+ data.m_sqlField.copyin(ctx, *data.m_extField);
+}
+
+void
+Exec_expr_param::close(Ctx& ctx)
+{
+ Data& data = getData();
+ data.m_extPos = -1;
+}
+
+void
+Exec_expr_param::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [param %u]", code.m_paramNumber);
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_param.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_param.hpp
new file mode 100644
index 00000000000..783e5c087b4
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_param.hpp
@@ -0,0 +1,136 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_expr_param_hpp
+#define ODBC_CODEGEN_Code_expr_param_hpp
+
+#include <common/common.hpp>
+#include <common/DataField.hpp>
+#include "Code_expr.hpp"
+
+/**
+ * @class Plan_expr_param
+ * @brief Constant expression value in PlanTree
+ */
+class Plan_expr_param : public Plan_expr {
+public:
+ Plan_expr_param(Plan_root* root, unsigned paramNumber);
+ virtual ~Plan_expr_param();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx& ctx);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ bool isEqual(const Plan_expr* expr) const;
+ bool isGroupBy(const Plan_expr_row* row) const;
+protected:
+ const unsigned m_paramNumber;
+};
+
+inline
+Plan_expr_param::Plan_expr_param(Plan_root* root, unsigned paramNumber) :
+ Plan_expr(root, TypeParam),
+ m_paramNumber(paramNumber)
+{
+}
+
+/**
+ * @class Exec_expr_param
+ * @brief Constant expression value in ExecTree
+ */
+class Exec_expr_param : public Exec_expr {
+public:
+ class Code : public Exec_expr::Code {
+ public:
+ Code(const SqlSpec& sqlSpec, unsigned paramNumber);
+ virtual ~Code();
+ protected:
+ friend class Plan_expr_param;
+ friend class Exec_expr_param;
+ const SqlSpec m_sqlSpec;
+ const unsigned m_paramNumber;
+ };
+ class Data : public Exec_expr::Data {
+ public:
+ Data(SqlField& sqlField);
+ virtual ~Data();
+ ExtField* extField() const;
+ protected:
+ friend class Exec_expr_param;
+ friend class Exec_root;
+ SqlField m_sqlField;
+ ExtField* m_extField; // input binding
+ bool m_atExec; // data at exec
+ int m_extPos; // position for SQLPutData (-1 before first call)
+ };
+ Exec_expr_param(Exec_root* root);
+ virtual ~Exec_expr_param();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void bind(Ctx& ctx);
+ void evaluate(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+};
+
+inline
+Exec_expr_param::Code::Code(const SqlSpec& sqlSpec, unsigned paramNumber) :
+ Exec_expr::Code(m_sqlSpec),
+ m_sqlSpec(sqlSpec),
+ m_paramNumber(paramNumber)
+{
+}
+
+inline
+Exec_expr_param::Data::Data(SqlField& sqlField) :
+ Exec_expr::Data(m_sqlField),
+ m_sqlField(sqlField),
+ m_extField(0),
+ m_atExec(false),
+ m_extPos(-1)
+{
+}
+
+inline ExtField*
+Exec_expr_param::Data::extField() const
+{
+ return m_extField;
+}
+
+inline
+Exec_expr_param::Exec_expr_param(Exec_root* root) :
+ Exec_expr(root)
+{
+}
+
+// children
+
+inline const Exec_expr_param::Code&
+Exec_expr_param::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_expr_param::Data&
+Exec_expr_param::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_row.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_row.cpp
new file mode 100644
index 00000000000..da1751d41d1
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_row.cpp
@@ -0,0 +1,204 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/DataType.hpp>
+#include "Code_expr_row.hpp"
+#include "Code_expr.hpp"
+#include "Code_expr_conv.hpp"
+#include "Code_dml_row.hpp"
+#include "Code_root.hpp"
+
+// Plan_expr_row
+
+Plan_expr_row::~Plan_expr_row()
+{
+}
+
+Plan_base*
+Plan_expr_row::analyze(Ctx& ctx, Ctl& ctl)
+{
+ unsigned size = getSize();
+ // analyze subexpressions
+ m_anyAggr = false;
+ m_allBound = true;
+ for (unsigned i = 1; i <= size; i++) {
+ Plan_expr* expr1 = getExpr(i);
+ Plan_expr* expr2 = static_cast<Plan_expr*>(expr1->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ setExpr(i, expr2);
+ if (expr2->isAggr())
+ m_anyAggr = true;
+ if (! expr2->isBound())
+ m_allBound = false;
+ }
+ // insert conversions if requested XXX ugly hack
+ if (ctl.m_dmlRow != 0) {
+ if (ctl.m_dmlRow->getSize() > getSize()) {
+ ctx.pushStatus(Sqlstate::_21S01, Error::Gen, "not enough values (%u > %u)", ctl.m_dmlRow->getSize(), getSize());
+ return 0;
+ }
+ if (ctl.m_dmlRow->getSize() < getSize()) {
+ ctx.pushStatus(Sqlstate::_21S01, Error::Gen, "too many values (%u < %u)", ctl.m_dmlRow->getSize(), getSize());
+ return 0;
+ }
+ for (unsigned i = 1; i <= size; i++) {
+ const SqlType& sqlType = ctl.m_dmlRow->getColumn(i)->sqlType();
+ Plan_expr_conv* exprConv = new Plan_expr_conv(m_root, sqlType);
+ m_root->saveNode(exprConv);
+ exprConv->setExpr(getExpr(i));
+ Plan_expr* expr = static_cast<Plan_expr*>(exprConv->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(expr != 0);
+ setExpr(i, expr);
+ }
+ }
+ // set aliases
+ m_aliasList.resize(1 + size);
+ for (unsigned i = 1; i <= size; i++) {
+ if (m_aliasList[i].empty()) {
+ setAlias(i, getExpr(i)->getAlias());
+ }
+ }
+ // node was not replaced
+ return this;
+}
+
+Exec_base*
+Plan_expr_row::codegen(Ctx& ctx, Ctl& ctl)
+{
+ unsigned size = getSize();
+ Exec_expr_row* exec = new Exec_expr_row(ctl.m_execRoot, size);
+ ctl.m_execRoot->saveNode(exec);
+ SqlSpecs sqlSpecs(size);
+ // create code for subexpressions
+ for (unsigned i = 1; i <= size; i++) {
+ Plan_expr* planExpr = getExpr(i);
+ Exec_expr* execExpr = static_cast<Exec_expr*>(planExpr->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execExpr != 0);
+ exec->setExpr(i, execExpr);
+ const SqlSpec sqlSpec(execExpr->getCode().sqlSpec(), SqlSpec::Reference);
+ sqlSpecs.setEntry(i, sqlSpec);
+ }
+ // create alias list
+ Exec_expr_row::Code::Alias* aliasList = new Exec_expr_row::Code::Alias[1 + size];
+ strcpy(aliasList[0], "?");
+ for (unsigned i = 1; i <= size; i++) {
+ const char* s = m_aliasList[i].c_str();
+ if (strlen(s) == 0)
+ s = getExpr(i)->getAlias().c_str();
+ unsigned n = strlen(s);
+ if (n >= sizeof(Exec_expr_row::Code::Alias))
+ n = sizeof(Exec_expr_row::Code::Alias) - 1;
+ strncpy(aliasList[i], s, n);
+ aliasList[i][n] = 0;
+ }
+ // create the code
+ Exec_expr_row::Code& code = *new Exec_expr_row::Code(sqlSpecs, aliasList);
+ exec->setCode(code);
+ return exec;
+}
+
+void
+Plan_expr_row::print(Ctx& ctx)
+{
+ const unsigned size = getSize();
+ ctx.print(" [expr_row");
+ for (unsigned i = 1; i <= size; i++) {
+ Plan_base* a = m_exprList[i];
+ a == 0 ? ctx.print(" -") : a->print(ctx);
+ }
+ ctx.print("]");
+}
+
+bool
+Plan_expr_row::isAllGroupBy(const Plan_expr_row* row) const
+{
+ const unsigned size = getSize();
+ for (unsigned i = 1; i <= size; i++) {
+ if (! getExpr(i)->isGroupBy(row))
+ return false;
+ }
+ return true;
+}
+
+// Exec_expr_row
+
+Exec_expr_row::Code::~Code()
+{
+ delete[] m_aliasList;
+}
+
+Exec_expr_row::Data::~Data()
+{
+}
+
+Exec_expr_row::~Exec_expr_row()
+{
+ delete[] m_expr;
+}
+
+void
+Exec_expr_row::alloc(Ctx& ctx, Ctl& ctl)
+{
+ // allocate subexpressions
+ for (unsigned i = 1; i <= m_size; i++) {
+ getExpr(i)->alloc(ctx, ctl);
+ }
+ // construct SqlRow of references
+ const Code& code = getCode();
+ SqlRow sqlRow(getCode().m_sqlSpecs);
+ for (unsigned i = 1; i <= m_size; i++) {
+ const Exec_expr::Data& dataExpr = getExpr(i)->getData();
+ const SqlSpec& sqlSpec = code.m_sqlSpecs.getEntry(i);
+ const SqlField sqlField(sqlSpec, &dataExpr.sqlField());
+ sqlRow.setEntry(i, sqlField);
+ }
+ // create the data
+ Data& data = *new Data(sqlRow);
+ setData(data);
+}
+
+void
+Exec_expr_row::evaluate(Ctx& ctx, Ctl& ctl)
+{
+ for (unsigned i = 1; i <= m_size; i++) {
+ getExpr(i)->evaluate(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ }
+}
+
+void
+Exec_expr_row::close(Ctx& ctx)
+{
+ for (unsigned i = 1; i <= m_size; i++) {
+ getExpr(i)->close(ctx);
+ }
+}
+
+void
+Exec_expr_row::print(Ctx& ctx)
+{
+ ctx.print(" [expr_row");
+ for (unsigned i = 1; i <= m_size; i++) {
+ getExpr(i)->print(ctx);
+ }
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_row.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_row.hpp
new file mode 100644
index 00000000000..94527931dba
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_expr_row.hpp
@@ -0,0 +1,272 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_expr_row_hpp
+#define ODBC_CODEGEN_Code_expr_row_hpp
+
+#include <vector>
+#include <common/common.hpp>
+#include <common/DataRow.hpp>
+#include "Code_base.hpp"
+#include "Code_expr.hpp"
+
+class Plan_expr;
+
+/**
+ * @class Plan_expr_row
+ * @brief Row of expressions in PlanTree
+ *
+ * Used for select, value, and order by rows.
+ */
+class Plan_expr_row : public Plan_base {
+public:
+ Plan_expr_row(Plan_root* root);
+ virtual ~Plan_expr_row();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setAsterisk();
+ bool getAsterisk() const;
+ unsigned getSize() const;
+ Plan_expr* getExpr(unsigned i) const;
+ void setExpr(unsigned i, Plan_expr* expr);
+ void addExpr(Plan_expr* expr);
+ void addExpr(Plan_expr* expr, const BaseString& alias);
+ void setAlias(unsigned i, const BaseString& alias);
+ void addExpr(Plan_expr* expr, bool asc);
+ bool anyAggr() const;
+ bool allBound() const;
+ bool isAllGroupBy(const Plan_expr_row* row) const;
+protected:
+ friend class Plan_query;
+ friend class Plan_query_sort;
+ bool m_asterisk; // early plan node type
+ ExprVector m_exprList;
+ typedef std::vector<BaseString> AliasList;
+ AliasList m_aliasList;
+ typedef std::vector<bool> AscList;
+ AscList m_ascList;
+ bool m_anyAggr; // at least one aggreate
+ bool m_allBound; // all bound
+};
+
+inline
+Plan_expr_row::Plan_expr_row(Plan_root* root) :
+ Plan_base(root),
+ m_asterisk(false),
+ m_exprList(1),
+ m_aliasList(1),
+ m_ascList(1),
+ m_anyAggr(false),
+ m_allBound(false)
+{
+}
+
+// children
+
+inline void
+Plan_expr_row::setAsterisk()
+{
+ m_asterisk = true;
+}
+
+inline bool
+Plan_expr_row::getAsterisk() const
+{
+ return m_asterisk;
+}
+
+inline unsigned
+Plan_expr_row::getSize() const
+{
+ ctx_assert(m_exprList.size() >= 1);
+ return m_exprList.size() - 1;
+}
+
+inline void
+Plan_expr_row::addExpr(Plan_expr* expr)
+{
+ ctx_assert(expr != 0);
+ addExpr(expr, expr->m_alias);
+}
+
+inline void
+Plan_expr_row::addExpr(Plan_expr* expr, const BaseString& alias)
+{
+ ctx_assert(expr != 0);
+ m_exprList.push_back(expr);
+ m_aliasList.push_back(alias);
+}
+
+inline void
+Plan_expr_row::addExpr(Plan_expr* expr, bool asc)
+{
+ ctx_assert(expr != 0);
+ m_exprList.push_back(expr);
+ m_ascList.push_back(asc);
+}
+
+inline void
+Plan_expr_row::setExpr(unsigned i, Plan_expr* expr)
+{
+ ctx_assert(1 <= i && i < m_exprList.size() && expr != 0);
+ m_exprList[i] = expr;
+}
+
+inline Plan_expr*
+Plan_expr_row::getExpr(unsigned i) const
+{
+ ctx_assert(1 <= i && i < m_exprList.size() && m_exprList[i] != 0);
+ return m_exprList[i];
+}
+
+inline void
+Plan_expr_row::setAlias(unsigned i, const BaseString& alias)
+{
+ ctx_assert(1 <= i && i < m_aliasList.size());
+ m_aliasList[i] = alias;
+}
+
+inline bool
+Plan_expr_row::anyAggr() const
+{
+ return m_anyAggr;
+}
+
+inline bool
+Plan_expr_row::allBound() const
+{
+ return m_allBound;
+}
+
+/**
+ * @class Expr_expr_row
+ * @brief Row of expressions in ExecTree
+ */
+class Exec_expr_row : public Exec_base {
+public:
+ class Code : public Exec_base::Code {
+ public:
+ typedef char Alias[40];
+ Code(const SqlSpecs& sqlSpecs, const Alias* aliasList);
+ virtual ~Code();
+ const SqlSpecs& sqlSpecs() const;
+ const char* getAlias(unsigned i) const;
+ protected:
+ friend class Exec_expr_row;
+ const SqlSpecs m_sqlSpecs;
+ const Alias* m_aliasList;
+ };
+ class Data : public Exec_base::Data {
+ public:
+ Data(const SqlRow& sqlRow);
+ virtual ~Data();
+ const SqlRow& sqlRow() const;
+ protected:
+ friend class Exec_expr_row;
+ SqlRow m_sqlRow;
+ };
+ Exec_expr_row(Exec_root* root, unsigned size);
+ virtual ~Exec_expr_row();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void evaluate(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ Exec_expr* getExpr(unsigned i) const;
+ void setExpr(unsigned i, Exec_expr* expr);
+protected:
+ Exec_expr** m_expr; // numbered from 1
+ unsigned m_size;
+};
+
+inline
+Exec_expr_row::Code::Code(const SqlSpecs& sqlSpecs, const Alias* aliasList) :
+ m_sqlSpecs(sqlSpecs),
+ m_aliasList(aliasList)
+{
+}
+
+inline const SqlSpecs&
+Exec_expr_row::Code::sqlSpecs() const
+{
+ return m_sqlSpecs;
+}
+
+inline const char*
+Exec_expr_row::Code::getAlias(unsigned i) const
+{
+ ctx_assert(1 <= i && i <= m_sqlSpecs.count() && m_aliasList != 0);
+ return m_aliasList[i];
+}
+
+inline
+Exec_expr_row::Data::Data(const SqlRow& sqlRow) :
+ m_sqlRow(sqlRow)
+{
+}
+
+inline const SqlRow&
+Exec_expr_row::Data::sqlRow() const
+{
+ return m_sqlRow;
+}
+
+inline
+Exec_expr_row::Exec_expr_row(Exec_root* root, unsigned size) :
+ Exec_base(root),
+ m_expr(new Exec_expr* [1 + size]),
+ m_size(size)
+{
+ m_expr[0] = (Exec_expr*)-1;
+ for (unsigned i = 1; i <= m_size; i++)
+ m_expr[i] = 0;
+}
+
+// children
+
+inline const Exec_expr_row::Code&
+Exec_expr_row::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_expr_row::Data&
+Exec_expr_row::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline Exec_expr*
+Exec_expr_row::getExpr(unsigned i) const
+{
+ ctx_assert(1 <= i && i <= m_size && m_expr != 0 && m_expr[i] != 0);
+ return m_expr[i];
+}
+
+inline void
+Exec_expr_row::setExpr(unsigned i, Exec_expr* expr)
+{
+ ctx_assert(1 <= i && i <= m_size && m_expr != 0 && m_expr[i] == 0);
+ m_expr[i] = expr;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_idx_column.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_idx_column.cpp
new file mode 100644
index 00000000000..584ffef3e01
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_idx_column.cpp
@@ -0,0 +1,49 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NdbApi.hpp>
+#include <common/StmtArea.hpp>
+#include "Code_idx_column.hpp"
+#include "Code_expr_conv.hpp"
+#include "Code_root.hpp"
+
+// Plan_idx_column
+
+Plan_idx_column::~Plan_idx_column()
+{
+}
+
+Plan_base*
+Plan_idx_column::analyze(Ctx& ctx, Ctl& ctl)
+{
+ analyzeColumn(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+Exec_base*
+Plan_idx_column::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_idx_column::print(Ctx& ctx)
+{
+ ctx.print(" [idx_column %s]", getPrintName());
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_idx_column.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_idx_column.hpp
new file mode 100644
index 00000000000..209ed705b48
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_idx_column.hpp
@@ -0,0 +1,50 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_idx_column_hpp
+#define ODBC_CODEGEN_Code_idx_column_hpp
+
+#include <common/common.hpp>
+#include "Code_column.hpp"
+#include "Code_data_type.hpp"
+#include "Code_expr.hpp"
+
+class DictColumn;
+class Plan_table;
+
+/**
+ * @class Plan_idx_column
+ * @brief Column in create index statement
+ */
+class Plan_idx_column : public Plan_base, public Plan_column {
+public:
+ Plan_idx_column(Plan_root* root, const BaseString& name);
+ virtual ~Plan_idx_column();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+protected:
+ friend class Plan_create_row;
+};
+
+inline
+Plan_idx_column::Plan_idx_column(Plan_root* root, const BaseString& name) :
+ Plan_base(root),
+ Plan_column(Type_idx, name)
+{
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_insert.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_insert.cpp
new file mode 100644
index 00000000000..c442186c181
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_insert.cpp
@@ -0,0 +1,253 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_insert.hpp"
+#include "Code_query_repeat.hpp"
+#include "Code_query_project.hpp"
+#include "Code_table.hpp"
+#include "Code_root.hpp"
+
+// Plan_insert
+
+Plan_insert::~Plan_insert()
+{
+}
+
+Plan_base*
+Plan_insert::analyze(Ctx& ctx, Ctl& ctl)
+{
+ stmtArea().stmtInfo().setName(Stmt_name_insert);
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ // handle MySql syntax
+ if (m_mysqlRow != 0) {
+ setDmlRow(m_mysqlRow->m_dmlRow);
+ setExprRow(m_mysqlRow->m_exprRow);
+ m_mysqlRow = 0;
+ }
+ if (m_dmlRow == 0) {
+ // construct column list
+ setDmlRow(new Plan_dml_row(m_root));
+ m_root->saveNode(m_dmlRow);
+ const DictTable& dictTable = m_table->dictTable();
+ unsigned n = dictTable.getSize();
+ for (unsigned i = 1; i <= n; i++) {
+ DictColumn* dictColumn = dictTable.getColumn(i);
+ Plan_dml_column* column = new Plan_dml_column(m_root, dictColumn->getName());
+ m_root->saveNode(column);
+ m_dmlRow->addColumn(column);
+ }
+ }
+ // set name resolution scope
+ ctl.m_tableList.resize(1 + 1); // indexed from 1
+ ctl.m_tableList[1] = m_table;
+ // analyze the dml columns
+ m_dmlRow->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctl.m_dmlRow = m_dmlRow; // row type to convert to
+ if (m_query != 0) {
+ m_query->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ } else if (m_select == 0) {
+ // analyze the expression row
+ m_exprRow->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ // transform the row into query
+ Plan_query_repeat* queryRepeat = new Plan_query_repeat(m_root, 1);
+ m_root->saveNode(queryRepeat);
+ Plan_query_project* queryProject = new Plan_query_project(m_root);
+ m_root->saveNode(queryProject);
+ queryProject->setQuery(queryRepeat);
+ queryProject->setRow(m_exprRow);
+ setQuery(queryProject);
+ } else {
+ // analyze the select into query
+ Plan_query* query = static_cast<Plan_query*>(m_select->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ setQuery(query);
+ }
+ return this;
+}
+
+void
+Plan_insert::describe(Ctx& ctx)
+{
+ stmtArea().setFunction(ctx, "INSERT", SQL_DIAG_INSERT);
+}
+
+Exec_base*
+Plan_insert::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // create code for the query
+ ctx_assert(m_query != 0);
+ Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execQuery != 0);
+ // set up
+ ctx_assert(m_table != 0);
+ const BaseString& tableName = m_table->getName();
+ const DictTable& dictTable = m_table->dictTable();
+ const ColumnVector& columns = m_table->dmlColumns();
+ ctx_assert(columns.size() > 0);
+ const unsigned attrCount = columns.size() - 1;
+ // create the code
+ Exec_insert::Code& code = *new Exec_insert::Code();
+ code.m_insertOp = m_insertOp;
+ code.m_tableName = strcpy(new char[tableName.length() + 1], tableName.c_str());
+ code.m_attrCount = attrCount;
+ code.m_attrId = new NdbAttrId[1 + attrCount];
+ code.m_isKey = new bool[1 + attrCount];
+ code.m_attrId[0] = (NdbAttrId)-1;
+ code.m_tupleId = dictTable.tupleId(); // maybe 0
+ code.m_autoIncrement = dictTable.autoIncrement(); // maybe 0
+ unsigned k;
+ if ((k = code.m_tupleId) != 0 || (k = code.m_autoIncrement) != 0) {
+ const DictColumn& dictColumn = *dictTable.getColumn(k);
+ code.m_idType = dictColumn.sqlType();
+ }
+ for (unsigned i = 1; i <= attrCount; i++) {
+ Plan_column* column = columns[i];
+ ctx_assert(column != 0);
+ const DictColumn& dictColumn = column->dictColumn();
+ code.m_attrId[i] = dictColumn.getAttrId();
+ code.m_isKey[i] = dictColumn.isKey();
+ }
+ // default values XXX a mess
+ code.m_defaultCount = 0;
+ for (unsigned j = 1; j <= dictTable.getSize(); j++) {
+ const DictColumn& dictColumn = *dictTable.getColumn(j);
+ if (dictColumn.getDefaultValue() != 0 && ! code.findAttrId(dictColumn.getAttrId()))
+ code.m_defaultCount++;
+ }
+ if (code.m_defaultCount != 0) {
+ code.m_defaultId = new NdbAttrId[1 + code.m_defaultCount];
+ for (unsigned i = 0, j = 1; j <= dictTable.getSize(); j++) {
+ const DictColumn& dictColumn = *dictTable.getColumn(j);
+ if (dictColumn.getDefaultValue() != 0 && ! code.findAttrId(dictColumn.getAttrId()))
+ code.m_defaultId[++i] = dictColumn.getAttrId();
+ }
+ SqlSpecs sqlSpecs(code.m_defaultCount);
+ for (unsigned i = 0, j = 1; j <= dictTable.getSize(); j++) {
+ const DictColumn& dictColumn = *dictTable.getColumn(j);
+ if (dictColumn.getDefaultValue() != 0 && ! code.findAttrId(dictColumn.getAttrId())) {
+ SqlSpec sqlSpec(dictColumn.sqlType(), SqlSpec::Physical);
+ sqlSpecs.setEntry(++i, sqlSpec);
+ }
+ }
+ code.m_defaultValue = new SqlRow(sqlSpecs);
+ for (unsigned i = 0, j = 1; j <= dictTable.getSize(); j++) {
+ const DictColumn& dictColumn = *dictTable.getColumn(j);
+ if (dictColumn.getDefaultValue() != 0 && ! code.findAttrId(dictColumn.getAttrId())) {
+ const char* defaultValue = dictColumn.getDefaultValue();
+ ExtType extType(ExtType::Char);
+ ExtSpec extSpec(extType);
+ SQLINTEGER ind = SQL_NTS;
+ ExtField extField(extSpec, (SQLPOINTER)defaultValue, 0, &ind);
+ SqlField& f = code.m_defaultValue->getEntry(++i);
+ f.copyin(ctx, extField);
+ if (! ctx.ok())
+ return 0;
+ }
+ }
+ }
+ // create the exec
+ Exec_insert* exec = new Exec_insert(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ exec->setCode(code);
+ exec->setQuery(execQuery);
+ return exec;
+}
+
+void
+Plan_insert::print(Ctx& ctx)
+{
+ ctx.print(" [%s", m_insertOp == Insert_op_insert ? "insert" : "write");
+ Plan_base* a[] = { m_table, m_dmlRow, m_exprRow, m_query };
+ printList(ctx, a, 4);
+ ctx.print("]");
+}
+
+// Exec_insert
+
+Exec_insert::Code::~Code()
+{
+ delete[] m_tableName;
+ delete[] m_attrId;
+ delete[] m_isKey;
+ delete[] m_defaultId;
+ delete m_defaultValue;
+}
+
+bool
+Exec_insert::Code::findAttrId(NdbAttrId attrId) const
+{
+ for (unsigned i = 1; i <= m_attrCount; i++) {
+ if (m_attrId[i] == attrId)
+ return true;
+ }
+ return false;
+}
+
+Exec_insert::Data::~Data()
+{
+}
+
+Exec_insert::~Exec_insert()
+{
+}
+
+void
+Exec_insert::alloc(Ctx& ctx, Ctl& ctl)
+{
+ // allocate the query
+ ctx_assert(m_query != 0);
+ m_query->alloc(ctx, ctl);
+ // create data
+ Data& data = *new Data();
+ setData(data);
+}
+
+void
+Exec_insert::close(Ctx& ctx)
+{
+}
+
+void
+Exec_insert::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx_assert(m_query != 0);
+ ctx.print(" [insert");
+ ctx.print(" attrId=");
+ for (unsigned i = 1; i <= code.m_attrCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_attrId[i]);
+ }
+ ctx.print(" table=%s", code.m_tableName);
+ m_query->print(ctx);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_insert.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_insert.hpp
new file mode 100644
index 00000000000..748b092e33a
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_insert.hpp
@@ -0,0 +1,229 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_insert_hpp
+#define ODBC_CODEGEN_Code_insert_hpp
+
+#include <common/common.hpp>
+#include "Code_base.hpp"
+#include "Code_dml.hpp"
+#include "Code_dml_row.hpp"
+#include "Code_expr_row.hpp"
+#include "Code_select.hpp"
+#include "Code_query.hpp"
+#include "Code_table.hpp"
+#include "Code_set_row.hpp"
+
+enum Insert_op {
+ Insert_op_undef = 0,
+ Insert_op_insert = 1,
+ Insert_op_write = 2
+};
+
+/**
+ * @class Plan_insert
+ * @brief Insert in PlanTree
+ *
+ * Insert. Becomes directly executable.
+ */
+class Plan_insert : public Plan_dml {
+public:
+ Plan_insert(Plan_root* root, Insert_op insertOp);
+ virtual ~Plan_insert();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx& ctx);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setTable(Plan_table* table);
+ Plan_dml_row* getDmlRow() const;
+ void setDmlRow(Plan_dml_row* dmlRow);
+ void setExprRow(Plan_expr_row* exprRow);
+ void setSelect(Plan_select* select);
+ void setQuery(Plan_query* query);
+ void setMysqlRow(Plan_set_row* mysqlRow);
+protected:
+ Insert_op m_insertOp;
+ Plan_table* m_table;
+ Plan_dml_row* m_dmlRow;
+ Plan_expr_row* m_exprRow;
+ Plan_select* m_select;
+ Plan_query* m_query;
+ Plan_set_row* m_mysqlRow;
+};
+
+inline
+Plan_insert::Plan_insert(Plan_root* root, Insert_op insertOp) :
+ Plan_dml(root),
+ m_insertOp(insertOp),
+ m_table(0),
+ m_dmlRow(0),
+ m_exprRow(0),
+ m_select(0),
+ m_query(0),
+ m_mysqlRow(0)
+{
+}
+
+// children
+
+inline void
+Plan_insert::setTable(Plan_table* table)
+{
+ ctx_assert(table != 0);
+ m_table = table;
+}
+
+inline void
+Plan_insert::setDmlRow(Plan_dml_row* dmlRow)
+{
+ ctx_assert(dmlRow != 0);
+ m_dmlRow = dmlRow;
+}
+
+inline Plan_dml_row*
+Plan_insert::getDmlRow() const
+{
+ ctx_assert(m_dmlRow != 0);
+ return m_dmlRow;
+}
+
+inline void
+Plan_insert::setExprRow(Plan_expr_row* exprRow)
+{
+ ctx_assert(exprRow != 0);
+ m_exprRow = exprRow;
+}
+
+inline void
+Plan_insert::setSelect(Plan_select* select)
+{
+ ctx_assert(select != 0);
+ m_select = select;
+}
+
+inline void
+Plan_insert::setQuery(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+inline void
+Plan_insert::setMysqlRow(Plan_set_row* mysqlRow)
+{
+ ctx_assert(mysqlRow != 0);
+ m_mysqlRow = mysqlRow;
+}
+
+/**
+ * @class Exec_insert
+ * @brief Executable insert
+ */
+class Exec_insert : public Exec_dml {
+public:
+ class Code : public Exec_dml::Code {
+ public:
+ Code();
+ virtual ~Code();
+ protected:
+ friend class Plan_insert;
+ friend class Exec_insert;
+ Insert_op m_insertOp;
+ char* m_tableName;
+ unsigned m_attrCount;
+ NdbAttrId* m_attrId;
+ bool* m_isKey;
+ unsigned m_tupleId; // position of tuple id
+ unsigned m_autoIncrement; // position of ai key
+ SqlType m_idType; // type of tuple id or ai key
+ unsigned m_defaultCount;
+ NdbAttrId* m_defaultId;
+ SqlRow* m_defaultValue;
+ bool findAttrId(NdbAttrId attrId) const;
+ };
+ class Data : public Exec_dml::Data {
+ public:
+ Data();
+ virtual ~Data();
+ protected:
+ friend class Exec_insert;
+ };
+ Exec_insert(Exec_root* root);
+ virtual ~Exec_insert();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setQuery(Exec_query* query);
+private:
+ Exec_query* m_query;
+};
+
+inline
+Exec_insert::Code::Code() :
+ m_insertOp(Insert_op_undef),
+ m_tableName(0),
+ m_attrCount(0),
+ m_attrId(0),
+ m_isKey(0),
+ m_tupleId(0),
+ m_autoIncrement(0),
+ m_defaultCount(0),
+ m_defaultId(0),
+ m_defaultValue(0)
+{
+}
+
+inline
+Exec_insert::Data::Data()
+{
+}
+
+inline
+Exec_insert::Exec_insert(Exec_root* root) :
+ Exec_dml(root),
+ m_query(0)
+{
+}
+
+// children
+
+inline const Exec_insert::Code&
+Exec_insert::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_insert::Data&
+Exec_insert::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_insert::setQuery(Exec_query* query)
+{
+ ctx_assert(m_query == 0 && query != 0);
+ m_query = query;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_pred.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_pred.cpp
new file mode 100644
index 00000000000..fe7cac7606e
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_pred.cpp
@@ -0,0 +1,70 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_pred.hpp"
+#include "Code_pred_op.hpp"
+#include "Code_root.hpp"
+
+// Plan_pred
+
+Plan_pred::~Plan_pred()
+{
+}
+
+bool
+Plan_pred::isGroupBy(const Plan_expr_row* row) const
+{
+ return false;
+}
+
+Plan_pred*
+Plan_pred::opAnd(Plan_pred* pred2)
+{
+ Plan_pred_op* predAnd = new Plan_pred_op(m_root, Pred_op::And);
+ m_root->saveNode(predAnd);
+ predAnd->setPred(1, this);
+ predAnd->setPred(2, pred2);
+ return predAnd;
+}
+
+// Exec_pred
+
+Exec_pred::Code::~Code()
+{
+}
+
+Exec_pred::Data::~Data()
+{
+}
+
+Exec_pred::~Exec_pred()
+{
+}
+
+Pred_value&
+Exec_pred::Data::groupValue(unsigned i, bool initFlag)
+{
+ if (m_groupValue.size() == 0) {
+ m_groupValue.resize(1);
+ }
+ if (initFlag) {
+ //unsigned i2 = m_groupValue.size();
+ //ctx_assert(i == i2);
+ m_groupValue.push_back(Pred_value_unknown);
+ }
+ ctx_assert(i != 0 && i < m_groupValue.size());
+ return m_groupValue[i];
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_pred.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_pred.hpp
new file mode 100644
index 00000000000..a77c1161fa1
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_pred.hpp
@@ -0,0 +1,172 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_pred_hpp
+#define ODBC_CODEGEN_Code_pred_hpp
+
+#include <common/common.hpp>
+#include <common/DataField.hpp>
+#include "Code_base.hpp"
+
+enum Pred_value {
+ Pred_value_unknown = -1,
+ Pred_value_false = 0,
+ Pred_value_true = 1
+};
+
+class Ctx;
+class Plan_expr_row;
+class Exec_pred;
+
+/**
+ * @class Plan_pred
+ * @brief Base class for predicates in PlanTree
+ *
+ * Predicate represents a boolean value.
+ */
+class Plan_pred : public Plan_base {
+public:
+ // type is convenient since RTTI cannot be used
+ enum Type {
+ TypeUndefined = 0,
+ TypeComp = 1,
+ TypeOp = 2
+ };
+ Plan_pred(Plan_root* root, Type type);
+ virtual ~Plan_pred() = 0;
+ Type type() const;
+ const TableSet& tableSet() const;
+ const TableSet& noInterp() const;
+ virtual bool isGroupBy(const Plan_expr_row* row) const;
+ // helpers
+ Plan_pred* opAnd(Plan_pred* pred2);
+protected:
+ const Type m_type;
+ TableSet m_tableSet; // depends on these tables
+ TableSet m_noInterp; // cannot use interpreted TUP program on these tables
+ Exec_pred* m_exec; // probably stupid
+};
+
+inline
+Plan_pred::Plan_pred(Plan_root* root, Type type) :
+ Plan_base(root),
+ m_type(type),
+ m_exec(0)
+{
+}
+
+inline Plan_pred::Type
+Plan_pred::type() const
+{
+ return m_type;
+}
+
+inline const Plan_pred::TableSet&
+Plan_pred::tableSet() const
+{
+ return m_tableSet;
+}
+
+inline const Plan_pred::TableSet&
+Plan_pred::noInterp() const
+{
+ return m_noInterp;
+}
+
+/**
+ * @class Exec_pred
+ * @brief Base class for predicates in ExecTree
+ */
+class Exec_pred : public Exec_base {
+public:
+ class Code : public Exec_base::Code {
+ public:
+ Code();
+ virtual ~Code() = 0;
+ protected:
+ friend class Exec_pred;
+ };
+ class Data : public Exec_base::Data {
+ public:
+ Data();
+ virtual ~Data() = 0;
+ Pred_value getValue() const;
+ Pred_value groupValue(unsigned i) const;
+ protected:
+ friend class Exec_pred;
+ Pred_value m_value; // the value
+ // group-by data
+ typedef std::vector<Pred_value> GroupValue;
+ GroupValue m_groupValue;
+ Pred_value& groupValue(unsigned i, bool initFlag);
+ };
+ Exec_pred(Exec_root* root);
+ virtual ~Exec_pred() = 0;
+ virtual void execInterp(Ctx& ctx, Ctl& ctl) = 0;
+ virtual void evaluate(Ctx& ctx, Ctl& ctl) = 0;
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+};
+
+inline
+Exec_pred::Code::Code()
+{
+}
+
+inline
+Exec_pred::Data::Data() :
+ m_value(Pred_value_unknown)
+{
+}
+
+inline Pred_value
+Exec_pred::Data::getValue() const
+{
+ return m_value;
+}
+
+inline Pred_value
+Exec_pred::Data::groupValue(unsigned i) const
+{
+ ctx_assert(i != 0 && i < m_groupValue.size());
+ return m_groupValue[i];
+}
+
+inline
+Exec_pred::Exec_pred(Exec_root* root) :
+ Exec_base(root)
+{
+}
+
+// children
+
+inline const Exec_pred::Code&
+Exec_pred::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_pred::Data&
+Exec_pred::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_pred_op.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_pred_op.cpp
new file mode 100644
index 00000000000..29736e45818
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_pred_op.cpp
@@ -0,0 +1,188 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_pred.hpp"
+#include "Code_pred_op.hpp"
+#include "Code_root.hpp"
+
+// Pred_op
+
+const char*
+Pred_op::name() const
+{
+ switch (m_opcode) {
+ case And:
+ return "and";
+ case Or:
+ return "or";
+ case Not:
+ return "not";
+ }
+ ctx_assert(false);
+ return "";
+}
+
+unsigned
+Pred_op::arity() const
+{
+ switch (m_opcode) {
+ case And:
+ case Or:
+ return 2;
+ case Not:
+ return 1;
+ }
+ ctx_assert(false);
+ return 0;
+}
+
+// Plan_pred_op
+
+Plan_pred_op::~Plan_pred_op()
+{
+}
+
+Plan_base*
+Plan_pred_op::analyze(Ctx& ctx, Ctl& ctl)
+{
+ m_exec = 0;
+ unsigned arity = m_op.arity();
+ // check if we remain in top-level AND-clause
+ const bool topand = ctl.m_topand;
+ if (m_op.m_opcode != Pred_op::And)
+ ctl.m_topand = false;
+ // analyze sub-predicates
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_pred[i] != 0);
+ m_pred[i]->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ }
+ // save top level predicate on list
+ if (topand && ! ctl.m_topand) {
+ ctl.m_topcomp.push_back(this);
+ }
+ ctl.m_topand = topand;
+ // table dependencies are union from operands
+ m_tableSet.clear();
+ for (unsigned i = 1; i <= arity; i++) {
+ const TableSet& ts = m_pred[i]->tableSet();
+ m_tableSet.insert(ts.begin(), ts.end());
+ }
+ // set of tables for which interpreter cannot be used
+ m_noInterp.clear();
+ for (unsigned i = 1; i <= arity; i++) {
+ const TableSet& ts = m_pred[i]->noInterp();
+ m_noInterp.insert(ts.begin(), ts.end());
+ }
+ return this;
+}
+
+Exec_base*
+Plan_pred_op::codegen(Ctx& ctx, Ctl& ctl)
+{
+ if (m_exec != 0)
+ return m_exec;
+ unsigned arity = m_op.arity();
+ Exec_pred_op* exec = new Exec_pred_op(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ // create code for operands
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_pred[i] != 0);
+ Exec_pred* execPred = static_cast<Exec_pred*>(m_pred[i]->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execPred != 0);
+ exec->setPred(i, execPred);
+ }
+ // create the code
+ Exec_pred_op::Code& code = *new Exec_pred_op::Code(m_op);
+ exec->setCode(code);
+ m_exec = exec;
+ return exec;
+}
+
+void
+Plan_pred_op::print(Ctx& ctx)
+{
+ ctx.print(" [%s", m_op.name());
+ Plan_base* a[] = { m_pred[1], m_pred[2] };
+ printList(ctx, a, m_op.arity());
+ ctx.print("]");
+}
+
+bool
+Plan_pred_op::isGroupBy(const Plan_expr_row* row) const
+{
+ const unsigned arity = m_op.arity();
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_pred[i] != 0);
+ if (! m_pred[i]->isGroupBy(row))
+ return false;
+ }
+ return true;
+}
+
+// Code_pred_op
+
+Exec_pred_op::Code::~Code()
+{
+}
+
+Exec_pred_op::Data::~Data()
+{
+}
+
+Exec_pred_op::~Exec_pred_op()
+{
+}
+
+void
+Exec_pred_op::alloc(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ // allocate sub-predicates
+ unsigned arity = code.m_op.arity();
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_pred[i] != 0);
+ m_pred[i]->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ }
+ Data& data = *new Data;
+ setData(data);
+}
+
+void
+Exec_pred_op::close(Ctx& ctx)
+{
+ const Code& code = getCode();
+ unsigned arity = code.m_op.arity();
+ for (unsigned i = 1; i <= arity; i++) {
+ ctx_assert(m_pred[i] != 0);
+ m_pred[i]->close(ctx);
+ }
+}
+
+void
+Exec_pred_op::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [%s", code.m_op.name());
+ Exec_base* a[] = { m_pred[1], m_pred[2] };
+ printList(ctx, a, code.m_op.arity());
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_pred_op.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_pred_op.hpp
new file mode 100644
index 00000000000..9130bc3cb81
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_pred_op.hpp
@@ -0,0 +1,158 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_pred_op_hpp
+#define ODBC_CODEGEN_Code_pred_op_hpp
+
+#include <common/common.hpp>
+#include <common/DataField.hpp>
+#include "Code_pred.hpp"
+
+/**
+ * @class Pred_op
+ * @brief Boolean operators
+ */
+struct Pred_op {
+ enum Opcode {
+ And = 1, // binary
+ Or,
+ Not // unary
+ };
+ Pred_op(Opcode opcode);
+ const char* name() const;
+ unsigned arity() const;
+ Opcode m_opcode;
+};
+
+inline
+Pred_op::Pred_op(Opcode opcode) :
+ m_opcode(opcode)
+{
+}
+
+/**
+ * @class Plan_pred_op
+ * @brief Operator node in a predicate in PlanTree
+ */
+class Plan_pred_op : public Plan_pred {
+public:
+ Plan_pred_op(Plan_root* root, Pred_op op);
+ virtual ~Plan_pred_op();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ bool isGroupBy(const Plan_expr_row* row) const;
+ // children
+ void setPred(unsigned i, Plan_pred* pred);
+protected:
+ friend class Plan_pred;
+ Pred_op m_op;
+ Plan_pred* m_pred[1 + 2];
+};
+
+inline
+Plan_pred_op::Plan_pred_op(Plan_root* root, Pred_op op) :
+ Plan_pred(root, TypeOp),
+ m_op(op)
+{
+ m_pred[0] = m_pred[1] = m_pred[2] = 0;
+}
+
+inline void
+Plan_pred_op::setPred(unsigned i, Plan_pred* pred)
+{
+ ctx_assert(1 <= i && i <= m_op.arity() && pred != 0);
+ m_pred[i] = pred;
+}
+
+/**
+ * @class Exec_pred_op
+ * @brief Operator node in a predicate in ExecTree
+ */
+class Exec_pred_op : public Exec_pred {
+public:
+ class Code : public Exec_pred::Code {
+ public:
+ Code(Pred_op op);
+ virtual ~Code();
+ protected:
+ friend class Exec_pred_op;
+ Pred_op m_op;
+ };
+ class Data : public Exec_pred::Data {
+ public:
+ Data();
+ virtual ~Data();
+ protected:
+ friend class Exec_pred_op;
+ };
+ Exec_pred_op(Exec_root* root);
+ virtual ~Exec_pred_op();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execInterp(Ctx& ctx, Ctl& ctl);
+ void evaluate(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setPred(unsigned i, Exec_pred* pred);
+protected:
+ Exec_pred* m_pred[1 + 2];
+};
+
+inline
+Exec_pred_op::Code::Code(Pred_op op) :
+ m_op(op)
+{
+}
+
+inline
+Exec_pred_op::Data::Data()
+{
+}
+
+inline
+Exec_pred_op::Exec_pred_op(Exec_root* root) :
+ Exec_pred(root)
+{
+ m_pred[0] = m_pred[1] = m_pred[2] = 0;
+}
+
+// children
+
+inline const Exec_pred_op::Code&
+Exec_pred_op::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_pred_op::Data&
+Exec_pred_op::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_pred_op::setPred(unsigned i, Exec_pred* pred)
+{
+ ctx_assert(1 <= i && i <= 2 && m_pred[i] == 0);
+ m_pred[i] = pred;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query.cpp
new file mode 100644
index 00000000000..9e983942601
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query.cpp
@@ -0,0 +1,299 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include "Code_query.hpp"
+#include "Code_query_project.hpp"
+#include "Code_query_count.hpp"
+
+// Plan_query
+
+Plan_query::~Plan_query()
+{
+}
+
+Plan_expr_row*
+Plan_query::getRow()
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_query::describe(Ctx& ctx)
+{
+ const Plan_expr_row* exprRow = getRow();
+ const unsigned count = exprRow->getSize();
+ // create IRD
+ DescArea& ird = descArea(Desc_usage_IRD);
+ ird.setCount(ctx, count);
+ for (unsigned i = 1; i <= count; i++) {
+ DescRec& rec = ird.getRecord(i);
+ const Plan_expr* expr = exprRow->m_exprList[i];
+ const SqlType& sqlType = expr->sqlType();
+ // data type
+ SQLSMALLINT desc_TYPE = sqlType.type();
+ rec.setField(SQL_DESC_TYPE, desc_TYPE);
+ SQLSMALLINT desc_CONCISE_TYPE = desc_TYPE;
+ rec.setField(SQL_DESC_CONCISE_TYPE, desc_CONCISE_TYPE);
+ SQLSMALLINT desc_DESC_DATETIME_INTERVAL_CODE = 0;
+ rec.setField(SQL_DESC_DATETIME_INTERVAL_CODE, desc_DESC_DATETIME_INTERVAL_CODE);
+ // nullable
+ SQLSMALLINT desc_NULLABLE = sqlType.nullable() ? SQL_NULLABLE : SQL_NO_NULLS;
+ rec.setField(SQL_DESC_NULLABLE, desc_NULLABLE);
+ // unsigned
+ SQLSMALLINT desc_UNSIGNED;
+ switch (sqlType.type()) {
+ case SQL_SMALLINT:
+ case SQL_INTEGER:
+ case SQL_BIGINT:
+ desc_UNSIGNED = sqlType.unSigned() ? SQL_TRUE : SQL_FALSE;
+ break;
+ default:
+ desc_UNSIGNED = SQL_TRUE; // thus spake microsoft
+ break;
+ }
+ rec.setField(SQL_DESC_UNSIGNED, desc_UNSIGNED);
+ // sizes
+ SQLUINTEGER desc_LENGTH = sqlType.length();
+ rec.setField(SQL_DESC_LENGTH, desc_LENGTH);
+ SQLINTEGER desc_OCTET_LENGTH = sqlType.size();
+ rec.setField(SQL_DESC_OCTET_LENGTH, desc_OCTET_LENGTH);
+ SQLINTEGER desc_DISPLAY_SIZE = sqlType.displaySize();
+ rec.setField(SQL_DESC_DISPLAY_SIZE, desc_DISPLAY_SIZE);
+ // name
+ ctx_assert(i < exprRow->m_aliasList.size());
+ const char* desc_NAME = exprRow->m_aliasList[i].c_str();
+ rec.setField(SQL_DESC_NAME, desc_NAME);
+ }
+ ctx_log3(("describe %u columns done", count));
+ stmtArea().setFunction(ctx, "SELECT CURSOR", SQL_DIAG_SELECT_CURSOR);
+}
+
+// Exec_query
+
+Exec_query::Code::~Code()
+{
+}
+
+Exec_query::Data::~Data()
+{
+ delete m_extRow;
+ m_extRow = 0;
+ delete[] m_extPos;
+ m_extPos = 0;
+}
+
+Exec_query::~Exec_query()
+{
+}
+
+const Exec_query*
+Exec_query::getRawQuery() const
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Exec_query::bind(Ctx& ctx)
+{
+ const Code& code = getCode();
+ const SqlSpecs& sqlSpecs = code.sqlSpecs();
+ const unsigned count = sqlSpecs.count();
+ // read ARD
+ DescArea& ard = descArea(Desc_usage_ARD);
+ const unsigned ardCount = ard.getCount();
+ // create specification row
+ ExtSpecs extSpecs(count);
+ for (unsigned i = 1; i <= count; i++) {
+ ExtType extType;
+ if (i <= ardCount) {
+ OdbcData descData;
+ DescRec& rec = ard.getRecord(i);
+ // check for unbound column
+ rec.getField(ctx, SQL_DESC_DATA_PTR, descData);
+ SQLPOINTER desc_DATA_PTR = descData.type() != OdbcData::Undef ? descData.pointer() : 0;
+ if (desc_DATA_PTR == 0) {
+ extType.setType(ctx, ExtType::Unbound);
+ } else {
+ rec.getField(ctx, SQL_DESC_TYPE, descData);
+ if (descData.type() == OdbcData::Undef) {
+ ctx.pushStatus(Error::Gen, "query column %u: external type not defined", i);
+ return;
+ }
+ SQLSMALLINT desc_TYPE = descData.smallint();
+ if (desc_TYPE == SQL_C_DEFAULT) {
+ if (i <= code.m_sqlSpecs.count())
+ desc_TYPE = code.m_sqlSpecs.getEntry(i).sqlType().sqlcdefault(ctx);
+ }
+ switch (desc_TYPE) {
+ case SQL_C_CHAR:
+ case SQL_C_BINARY:
+ case SQL_C_SHORT: // for sun.jdbc.odbc
+ case SQL_C_SSHORT:
+ case SQL_C_USHORT:
+ case SQL_C_LONG: // for sun.jdbc.odbc
+ case SQL_C_SLONG:
+ case SQL_C_ULONG:
+ case SQL_C_SBIGINT:
+ case SQL_C_UBIGINT:
+ case SQL_C_FLOAT:
+ case SQL_C_DOUBLE:
+ case SQL_C_TYPE_TIMESTAMP:
+ break;
+ default:
+ ctx.pushStatus(Error::Gen, "query column %u: unsupported external type %d", i, (int)desc_TYPE);
+ return;
+ }
+ extType.setType(ctx, static_cast<ExtType::Type>(desc_TYPE));
+ }
+ } else {
+ extType.setType(ctx, ExtType::Unbound);
+ }
+ const ExtSpec extSpec(extType);
+ extSpecs.setEntry(i, extSpec);
+ }
+ // create data row
+ ExtRow& extRow = *new ExtRow(extSpecs);
+ unsigned boundCount = 0;
+ for (unsigned i = 1; i <= count; i++) {
+ const ExtSpec& extSpec = extSpecs.getEntry(i);
+ if (extSpec.extType().type() != ExtType::Unbound) {
+ OdbcData descData;
+ DescRec& rec = ard.getRecord(i);
+ rec.getField(ctx, SQL_DESC_DATA_PTR, descData);
+ SQLPOINTER desc_DATA_PTR = descData.type() != OdbcData::Undef ? descData.pointer() : 0;
+ rec.getField(ctx, SQL_DESC_OCTET_LENGTH, descData);
+ SQLINTEGER desc_OCTET_LENGTH = descData.type() != OdbcData::Undef ? descData.integer() : 0;
+ rec.getField(ctx, SQL_DESC_INDICATOR_PTR, descData);
+ SQLINTEGER* desc_INDICATOR_PTR = descData.type() != OdbcData::Undef ? descData.integerPtr() : 0;
+ ctx_log4(("column %u: bind to 0x%x %d 0x%x", i, (unsigned)desc_DATA_PTR, (int)desc_OCTET_LENGTH, (unsigned)desc_INDICATOR_PTR));
+ ExtField extField(extSpec, desc_DATA_PTR, desc_OCTET_LENGTH, desc_INDICATOR_PTR, i);
+ extRow.setEntry(i, extField);
+ boundCount++;
+ } else {
+ ExtField extField(extSpec, i);
+ extRow.setEntry(i, extField);
+ }
+ }
+ Data& data = getData();
+ delete data.m_extRow;
+ data.m_extRow = &extRow;
+ ctx_log3(("bound %u out of %u columns", boundCount, count));
+}
+
+// execute and fetch
+
+void
+Exec_query::execute(Ctx& ctx, Ctl& ctl)
+{
+ Data& data = getData();
+ execImpl(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ data.initState();
+ if (m_topLevel) {
+ stmtArea().setRowCount(ctx, data.getCount());
+ }
+}
+
+bool
+Exec_query::fetch(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ Data& data = getData();
+ if (data.fetch(ctx, ctl)) {
+ if (m_topLevel) {
+ stmtArea().setRowCount(ctx, data.getCount());
+ }
+ if (data.m_extRow != 0) {
+ data.sqlRow().copyout(ctx, *data.m_extRow);
+ if (! ctx.ok())
+ return false;
+ }
+ if (data.m_extPos != 0) {
+ const unsigned count = code.sqlSpecs().count();
+ for (unsigned i = 0; i <= count; i++) {
+ data.m_extPos[i] = 0;
+ }
+ }
+ return true;
+ }
+ if (m_topLevel) {
+ stmtArea().setRowCount(ctx, data.getCount());
+ if (ctx.ok()) {
+ ctx.setCode(SQL_NO_DATA);
+ }
+ }
+ return false;
+}
+
+// odbc support
+
+void
+Exec_query::sqlGetData(Ctx& ctx, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValue, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_Ind)
+{
+ const Code& code = getCode();
+ Data& data = getData();
+ const SqlSpecs& sqlSpecs = code.m_sqlSpecs;
+ const unsigned count = sqlSpecs.count();
+ if (columnNumber == 0 || columnNumber > count) {
+ ctx.pushStatus(Sqlstate::_07009, Error::Gen, "column index %u is not within 1 to %u", (unsigned)columnNumber, count);
+ return;
+ }
+ // create positions array on first use
+ if (data.m_extPos == 0) {
+ data.m_extPos = new int[1 + count];
+ for (unsigned i = 0; i <= count; i++) {
+ data.m_extPos[i] = 0;
+ }
+ }
+ if (targetType == SQL_ARD_TYPE) {
+ // get type from ARD
+ DescArea& ard = descArea(Desc_usage_ARD);
+ const unsigned ardCount = ard.getCount();
+ if (columnNumber <= ardCount) {
+ OdbcData descData;
+ DescRec& rec = ard.getRecord(columnNumber);
+ rec.getField(ctx, SQL_DESC_CONCISE_TYPE, descData);
+ if (descData.type() != OdbcData::Undef) {
+ targetType = descData.smallint();
+ }
+ }
+ if (targetType == SQL_ARD_TYPE) {
+ ctx.pushStatus(Sqlstate::_07009, Error::Gen, "output column %u type not bound - cannot use SQL_ARD_TYPE", (unsigned)columnNumber);
+ return;
+ }
+ }
+ ExtType extType;
+ if (targetValue != 0) {
+ extType.setType(ctx, static_cast<ExtType::Type>(targetType));
+ // check if supported
+ if (! ctx.ok())
+ return;
+ } else {
+ extType.setType(ctx, ExtType::Unbound);
+ }
+ ExtSpec extSpec(extType);
+ ExtField extField(extSpec, targetValue, bufferLength, strlen_or_Ind, columnNumber);
+ // copy out and update position
+ extField.setPos(data.m_extPos[columnNumber]);
+ const SqlRow& sqlRow = data.sqlRow();
+ const SqlField& sqlField = sqlRow.getEntry(columnNumber);
+ sqlField.copyout(ctx, extField);
+ data.m_extPos[columnNumber] = extField.getPos();
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query.hpp
new file mode 100644
index 00000000000..97f98f859ff
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query.hpp
@@ -0,0 +1,155 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_hpp
+#define ODBC_CODEGEN_Code_query_hpp
+
+#include <common/common.hpp>
+#include <common/DataRow.hpp>
+#include <common/ResultArea.hpp>
+#include "Code_stmt.hpp"
+
+class Plan_expr_row;
+class Plan_table;
+class Exec_expr_row;
+
+/**
+ * @class Plan_query
+ * @brief Base class for queries in PlanTree
+ */
+class Plan_query : public Plan_stmt {
+public:
+ Plan_query(Plan_root* root);
+ virtual ~Plan_query() = 0;
+ void describe(Ctx& ctx);
+ virtual Plan_expr_row* getRow();
+};
+
+inline
+Plan_query::Plan_query(Plan_root* root) :
+ Plan_stmt(root)
+{
+}
+
+/**
+ * @class Exec_query
+ * @brief Base class for executable queries.
+ *
+ * Executable queriable statement.
+ */
+class Exec_query : public Exec_stmt {
+public:
+ class Code : public Exec_stmt::Code {
+ public:
+ Code(const SqlSpecs& sqlSpecs);
+ virtual ~Code() = 0;
+ const SqlSpecs& sqlSpecs() const;
+ protected:
+ friend class Exec_query;
+ const SqlSpecs& m_sqlSpecs; // subclass must contain
+ };
+ class Data : public Exec_stmt::Data, public ResultSet {
+ public:
+ Data(Exec_query* node, const SqlRow& sqlRow);
+ virtual ~Data() = 0;
+ const SqlRow& sqlRow() const;
+ ExtRow* extRow() const;
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ protected:
+ friend class Exec_query;
+ Exec_query* const m_node;
+ ExtRow* m_extRow; // output bindings
+ int* m_extPos; // positions for SQLGetData
+ };
+ Exec_query(Exec_root* root);
+ virtual ~Exec_query() = 0;
+ void bind(Ctx& ctx);
+ void execute(Ctx& ctx, Ctl& ctl);
+ bool fetch(Ctx& ctx, Ctl& ctl);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ virtual const Exec_query* getRawQuery() const;
+ // odbc support
+ void sqlGetData(Ctx& ctx, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValue, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_Ind);
+protected:
+ friend class Data;
+ virtual void execImpl(Ctx& ctx, Ctl& ctl) = 0;
+ virtual bool fetchImpl(Ctx& ctx, Ctl& ctl) = 0;
+};
+
+inline
+Exec_query::Code::Code(const SqlSpecs& sqlSpecs) :
+ m_sqlSpecs(sqlSpecs)
+{
+}
+
+inline const SqlSpecs&
+Exec_query::Code::sqlSpecs() const
+{
+ return m_sqlSpecs;
+}
+
+inline
+Exec_query::Data::Data(Exec_query* node, const SqlRow& sqlRow) :
+ ResultSet(sqlRow),
+ m_node(node),
+ m_extRow(0),
+ m_extPos(0)
+{
+}
+
+inline const SqlRow&
+Exec_query::Data::sqlRow() const
+{
+ return static_cast<const SqlRow&>(m_dataRow);
+}
+
+inline ExtRow*
+Exec_query::Data::extRow() const
+{
+ return m_extRow;
+}
+
+inline bool
+Exec_query::Data::fetchImpl(Ctx& ctx, Ctl& ctl)
+{
+ return m_node->fetchImpl(ctx, ctl);
+}
+
+inline
+Exec_query::Exec_query(Exec_root* root) :
+ Exec_stmt(root)
+{
+}
+
+// children
+
+inline const Exec_query::Code&
+Exec_query::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query::Data&
+Exec_query::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_count.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_count.cpp
new file mode 100644
index 00000000000..f52c41df802
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_count.cpp
@@ -0,0 +1,177 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_query_count.hpp"
+#include "Code_column.hpp"
+#include "Code_expr_row.hpp"
+#include "Code_root.hpp"
+
+// Plan_query_count
+
+Plan_query_count::~Plan_query_count()
+{
+}
+
+Plan_expr_row*
+Plan_query_count::getRow()
+{
+ ctx_assert(m_exprRow != 0);
+ return m_exprRow;
+}
+
+Plan_base*
+Plan_query_count::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_exprRow != 0);
+ ctl.m_aggrok = true;
+ ctl.m_aggrin = false;
+ m_exprRow->analyze(ctx, ctl);
+ ctl.m_aggrok = false;
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_query != 0);
+ m_query->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+Exec_base*
+Plan_query_count::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // create code for the subquery
+ ctx_assert(m_query != 0);
+ Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execQuery != 0);
+ // create code for the row based on query code
+ ctx_assert(m_exprRow != 0);
+ ctl.m_execQuery = execQuery;
+ Exec_expr_row* execRow = static_cast<Exec_expr_row*>(m_exprRow->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execRow != 0);
+ Exec_query_count* exec = new Exec_query_count(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ // re-use SqlSpecs from the row
+ const SqlSpecs& sqlSpecs = execRow->getCode().sqlSpecs();
+ Exec_query_count::Code& code = *new Exec_query_count::Code(sqlSpecs);
+ exec->setCode(code);
+ exec->setQuery(execQuery);
+ exec->setRow(execRow);
+ return exec;
+}
+
+void
+Plan_query_count::print(Ctx& ctx)
+{
+ ctx.print(" [query_count");
+ Plan_base* a[] = { m_query, m_exprRow };
+ printList(ctx, a, sizeof(a)/sizeof(a[0]));
+ ctx.print("]");
+}
+
+// Exec_query_count
+
+Exec_query_count::Code::~Code()
+{
+}
+
+Exec_query_count::Data::~Data()
+{
+}
+
+Exec_query_count::~Exec_query_count()
+{
+}
+
+const Exec_query*
+Exec_query_count::getRawQuery() const
+{
+ ctx_assert(m_query != 0);
+ return m_query;
+}
+
+void
+Exec_query_count::alloc(Ctx& ctx, Ctl& ctl)
+{
+ // allocate the subquery
+ ctx_assert(m_query != 0);
+ m_query->alloc(ctx, ctl);
+ // allocate the row based on subquery data
+ ctx_assert(m_exprRow != 0);
+ ctl.m_query = m_query;
+ m_exprRow->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // re-use SqlRow from the expression row
+ const SqlRow& sqlRow = m_exprRow->getData().sqlRow();
+ Data& data = *new Data(this, sqlRow);
+ setData(data);
+}
+
+void
+Exec_query_count::execImpl(Ctx& ctx, Ctl& ctl)
+{
+ Data& data = getData();
+ // zero counters
+ ctx_assert(m_exprRow != 0);
+ m_exprRow->close(ctx);
+ data.m_done = false;
+ // execute the subquery
+ ctx_assert(m_query != 0);
+ m_query->execute(ctx, ctl);
+}
+
+bool
+Exec_query_count::fetchImpl(Ctx& ctx, Ctl& ctl)
+{
+ Data& data = getData();
+ // returns one row only
+ if (data.m_done)
+ return false;
+ ctx_assert(m_query != 0 && m_exprRow != 0);
+ while (m_query->fetch(ctx, ctl)) {
+ // accumulate values
+ m_exprRow->evaluate(ctx, ctl);
+ if (! ctx.ok())
+ return false;
+ }
+ data.m_done = true;
+ return true;
+}
+
+void
+Exec_query_count::close(Ctx& ctx)
+{
+ ctx_assert(m_query != 0);
+ m_query->close(ctx);
+ ctx_assert(m_exprRow != 0);
+ m_exprRow->close(ctx);
+}
+
+void
+Exec_query_count::print(Ctx& ctx)
+{
+ ctx.print(" [query_count");
+ Exec_base* a[] = { m_query };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_count.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_count.hpp
new file mode 100644
index 00000000000..a094eba4519
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_count.hpp
@@ -0,0 +1,162 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_count_hpp
+#define ODBC_CODEGEN_Code_query_count_hpp
+
+#include <common/common.hpp>
+#include "Code_query.hpp"
+#include "Code_expr_row.hpp"
+#include "Code_root.hpp"
+
+class Ctx;
+
+/**
+ * @class Plan_query_count
+ * @brief Select count and other aggregates (no group by)
+ */
+class Plan_query_count : public Plan_query {
+public:
+ Plan_query_count(Plan_root* root);
+ virtual ~Plan_query_count();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setQuery(Plan_query* query);
+ void setRow(Plan_expr_row* exprRow);
+protected:
+ Plan_expr_row* getRow();
+ Plan_query* m_query;
+ Plan_expr_row* m_exprRow;
+};
+
+inline
+Plan_query_count::Plan_query_count(Plan_root* root) :
+ Plan_query(root),
+ m_query(0),
+ m_exprRow(0)
+{
+}
+
+// children
+
+inline void
+Plan_query_count::setQuery(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+inline void
+Plan_query_count::setRow(Plan_expr_row* exprRow)
+{
+ ctx_assert(exprRow != 0);
+ m_exprRow = exprRow;
+}
+
+/**
+ * @class Exec_query_count
+ * @brief Select count and other aggregates (no group by)
+ */
+class Exec_query_count : public Exec_query {
+public:
+ class Code : public Exec_query::Code {
+ public:
+ Code(const SqlSpecs& sqlSpecs);
+ virtual ~Code();
+ protected:
+ friend class Exec_query_count;
+ // sets reference to Sqlspecs from the row
+ };
+ class Data : public Exec_query::Data {
+ public:
+ Data(Exec_query_count* node, const SqlRow& sqlRow);
+ virtual ~Data();
+ protected:
+ friend class Exec_query_count;
+ // sets reference to SqlRow from the row
+ bool m_done; // returns one row
+ };
+ Exec_query_count(Exec_root* root);
+ virtual ~Exec_query_count();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setQuery(Exec_query* query);
+ void setRow(Exec_expr_row* exprRow);
+ const Exec_query* getRawQuery() const;
+protected:
+ Exec_query* m_query;
+ Exec_expr_row* m_exprRow;
+};
+
+inline
+Exec_query_count::Code::Code(const SqlSpecs& sqlSpecs) :
+ Exec_query::Code(sqlSpecs)
+{
+}
+
+inline
+Exec_query_count::Data::Data(Exec_query_count* node, const SqlRow& sqlRow) :
+ Exec_query::Data(node, sqlRow)
+{
+}
+
+inline
+Exec_query_count::Exec_query_count(Exec_root* root) :
+ Exec_query(root),
+ m_query(0),
+ m_exprRow(0)
+{
+}
+
+// children
+
+inline const Exec_query_count::Code&
+Exec_query_count::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query_count::Data&
+Exec_query_count::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_query_count::setQuery(Exec_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+inline void
+Exec_query_count::setRow(Exec_expr_row* exprRow)
+{
+ ctx_assert(m_exprRow == 0 && exprRow != 0);
+ m_exprRow = exprRow;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_distinct.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_distinct.cpp
new file mode 100644
index 00000000000..4cbfbfe812d
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_distinct.cpp
@@ -0,0 +1,204 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <algorithm>
+#include "Code_query_distinct.hpp"
+#include "Code_root.hpp"
+
+// Plan_query_distinct
+
+Plan_query_distinct::~Plan_query_distinct()
+{
+}
+
+Plan_expr_row*
+Plan_query_distinct::getRow()
+{
+ ctx_assert(m_query != 0);
+ return m_query->getRow();
+}
+
+Plan_base*
+Plan_query_distinct::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_query != 0);
+ m_query->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+Exec_base*
+Plan_query_distinct::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // create code for the subquery
+ ctx_assert(m_query != 0);
+ Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execQuery != 0);
+ // the exec node
+ Exec_query_distinct* exec = new Exec_query_distinct(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ // re-use SqlSpecs from subquery
+ const Exec_query::Code& codeQuery = execQuery->getCode();
+ const SqlSpecs& sqlSpecs = codeQuery.sqlSpecs();
+ Exec_query_distinct::Code& code = *new Exec_query_distinct::Code(sqlSpecs);
+ exec->setCode(code);
+ exec->setQuery(execQuery);
+ return exec;
+}
+
+void
+Plan_query_distinct::print(Ctx& ctx)
+{
+ ctx.print(" [query_distinct");
+ Plan_base* a[] = { m_query };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
+
+// Exec_query_distinct
+
+Exec_query_distinct::Code::~Code()
+{
+}
+
+Exec_query_distinct::Data::~Data()
+{
+ for (DistinctList::iterator i = m_groupList.begin(); i != m_groupList.end(); i++) {
+ delete (*i).first;
+ }
+}
+
+Exec_query_distinct::~Exec_query_distinct()
+{
+}
+
+const Exec_query*
+Exec_query_distinct::getRawQuery() const
+{
+ ctx_assert(m_query != 0);
+ return m_query->getRawQuery();
+}
+
+void
+Exec_query_distinct::alloc(Ctx& ctx, Ctl& ctl)
+{
+ // allocate subquery
+ ctx_assert(m_query != 0);
+ m_query->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ Data& data = *new Data(this, getCode().sqlSpecs());
+ setData(data);
+}
+
+void
+Exec_query_distinct::execImpl(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_query != 0);
+ m_query->execute(ctx, ctl);
+}
+
+bool
+DistinctLess::operator()(const SqlRow* s1, const SqlRow* s2) const
+{
+ ctx_assert(s1 != 0 && s2 != 0);
+ const SqlRow& r1 = *s1;
+ const SqlRow& r2 = *s2;
+ for (unsigned i = 1; i <= r1.count(); i++) {
+ const SqlField& f1 = r1.getEntry(i);
+ const SqlField& f2 = r2.getEntry(i);
+ // nulls last is default in oracle
+ const bool f1null = f1.sqlNull();
+ const bool f2null = f2.sqlNull();
+ if (f1null && f2null)
+ continue;
+ if (! f1null && f2null)
+ return true;
+ if (f1null && ! f2null)
+ return false;
+ if (f1.less(f2))
+ return true;
+ if (f2.less(f1))
+ return false;
+ }
+ return false;
+}
+
+bool
+Exec_query_distinct::fetchImpl(Ctx& ctx, Ctl& ctl)
+{
+ Data& data = getData();
+ ctx_assert(m_query != 0);
+ if (! data.m_grouped) {
+ // read and group all rows
+ while (m_query->fetch(ctx, ctl)) {
+ const SqlRow* dataRow = &m_query->getData().sqlRow();
+ DistinctList::iterator i = data.m_groupList.find(dataRow);
+ if (i != data.m_groupList.end())
+ continue;
+ unsigned index = data.m_count++;
+ dataRow = dataRow->copy();
+ const DistinctList::value_type groupPair(dataRow, index);
+ data.m_groupList.insert(groupPair);
+ data.m_groupVector.push_back(dataRow);
+ }
+ if (! ctx.ok())
+ return false;
+ data.m_index = 0;
+ data.m_grouped = true;
+ }
+ ctx_assert(data.m_count == data.m_groupVector.size());
+ if (data.m_index < data.m_count) {
+ const SqlRow* currRow = data.m_groupVector[data.m_index];
+ // make our SqlRow reference to it
+ for (unsigned i = 1; i <= data.m_sqlRow.count(); i++) {
+ const SqlField& currField = currRow->getEntry(i);
+ SqlSpec sqlSpec(currField.sqlSpec(), SqlSpec::Reference);
+ SqlField sqlField(sqlSpec, &currField);
+ data.m_sqlRow.setEntry(i, sqlField);
+ }
+ data.m_index++;
+ return true;
+ }
+ return false;
+}
+
+void
+Exec_query_distinct::close(Ctx& ctx)
+{
+ Data& data = getData();
+ ctx_assert(m_query != 0);
+ m_query->close(ctx);
+ data.m_grouped = false;
+ data.m_count = 0;
+ for (DistinctList::iterator i = data.m_groupList.begin(); i != data.m_groupList.end(); i++) {
+ delete (*i).first;
+ }
+ data.m_groupList.clear();
+ data.m_groupVector.clear();
+}
+
+void
+Exec_query_distinct::print(Ctx& ctx)
+{
+ ctx.print(" [query_distinct");
+ Exec_base* a[] = { m_query };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_distinct.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_distinct.hpp
new file mode 100644
index 00000000000..62c46bda901
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_distinct.hpp
@@ -0,0 +1,165 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_distinct_hpp
+#define ODBC_CODEGEN_Code_query_distinct_hpp
+
+#include <functional>
+#include <common/common.hpp>
+#include "Code_query.hpp"
+#include "Code_expr_row.hpp"
+#include "Code_pred.hpp"
+
+/**
+ * @class Plan_query_distinct
+ * @brief Group-by node in PlanTree
+ */
+class Plan_query_distinct : public Plan_query {
+public:
+ Plan_query_distinct(Plan_root* root);
+ virtual ~Plan_query_distinct();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setQuery(Plan_query* query);
+ Plan_expr_row* getRow();
+protected:
+ Plan_query* m_query;
+};
+
+inline
+Plan_query_distinct::Plan_query_distinct(Plan_root* root) :
+ Plan_query(root),
+ m_query(0)
+{
+}
+
+// children
+
+inline void
+Plan_query_distinct::setQuery(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+/**
+ * Distinct preserves order of input rows so we use 2 data structures:
+ * map<row> = index and vector<index> = row (index >= 0).
+ */
+
+class Exec_query_distinct;
+
+struct DistinctLess : std::binary_function<const SqlRow*, const SqlRow*, bool> {
+ bool operator()(const SqlRow* s1, const SqlRow* s2) const;
+};
+
+typedef std::map<const SqlRow*, unsigned, DistinctLess> DistinctList;
+
+typedef std::vector<const SqlRow*> DistinctVector;
+
+/**
+ * @class Exec_query_distinct
+ * @brief Group-by node in ExecTree
+ */
+class Exec_query_distinct : public Exec_query {
+public:
+ class Code : public Exec_query::Code {
+ public:
+ Code(const SqlSpecs& sqlSpecs);
+ virtual ~Code();
+ protected:
+ friend class Exec_query_distinct;
+ // sets reference to Sqlspecs from subquery
+ };
+ class Data : public Exec_query::Data {
+ public:
+ Data(Exec_query_distinct* node, const SqlSpecs& sqlSpecs);
+ virtual ~Data();
+ protected:
+ friend class Exec_query_distinct;
+ SqlRow m_sqlRow; // current row
+ bool m_grouped; // fetch and group-by done
+ unsigned m_count;
+ DistinctList m_groupList;
+ DistinctVector m_groupVector;
+ unsigned m_index;
+ };
+ Exec_query_distinct(Exec_root* root);
+ virtual ~Exec_query_distinct();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setQuery(Exec_query* query);
+ const Exec_query* getRawQuery() const;
+protected:
+ friend class Exec_query;
+ Exec_query* m_query;
+};
+
+inline
+Exec_query_distinct::Code::Code(const SqlSpecs& sqlSpecs) :
+ Exec_query::Code(sqlSpecs)
+{
+}
+
+inline
+Exec_query_distinct::Data::Data(Exec_query_distinct* node, const SqlSpecs& sqlSpecs) :
+ Exec_query::Data(node, m_sqlRow),
+ m_sqlRow(sqlSpecs),
+ m_grouped(false),
+ m_count(0),
+ m_index(0)
+{
+}
+
+inline
+Exec_query_distinct::Exec_query_distinct(Exec_root* root) :
+ Exec_query(root),
+ m_query(0)
+{
+}
+
+// children
+
+inline const Exec_query_distinct::Code&
+Exec_query_distinct::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query_distinct::Data&
+Exec_query_distinct::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_query_distinct::setQuery(Exec_query* query)
+{
+ ctx_assert(m_query == 0 && query != 0);
+ m_query = query;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_filter.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_filter.cpp
new file mode 100644
index 00000000000..934a24d182d
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_filter.cpp
@@ -0,0 +1,161 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_query_filter.hpp"
+#include "Code_query_join.hpp"
+#include "Code_query_scan.hpp"
+#include "Code_root.hpp"
+
+// Plan_query_filter
+
+Plan_query_filter::~Plan_query_filter()
+{
+}
+
+Plan_base*
+Plan_query_filter::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_query != 0);
+ m_query->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_pred != 0);
+ m_pred->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+Exec_base*
+Plan_query_filter::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // generate code for the subquery
+ ctx_assert(m_query != 0);
+ Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execQuery != 0);
+ // create code for the predicate based on query code
+ Exec_pred* execPred = 0;
+ ctl.m_execQuery = execQuery;
+ ctx_assert(m_topTable != 0);
+ ctl.m_topTable = m_topTable;
+ ctx_assert(m_pred != 0);
+ execPred = static_cast<Exec_pred*>(m_pred->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execPred != 0);
+ ctl.m_topTable = 0;
+ // re-use SqlSpecs from subquery
+ const Exec_query::Code& codeQuery = execQuery->getCode();
+ const SqlSpecs& sqlSpecs = codeQuery.sqlSpecs();
+ Exec_query_filter* exec = new Exec_query_filter(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ Exec_query_filter::Code& code = *new Exec_query_filter::Code(sqlSpecs);
+ exec->setCode(code);
+ exec->setQuery(execQuery);
+ exec->setPred(execPred);
+ return exec;
+}
+
+void
+Plan_query_filter::print(Ctx& ctx)
+{
+ ctx.print(" [query_filter");
+ Plan_base* a[] = { m_query, m_pred };
+ printList(ctx, a, 2);
+ ctx.print("]");
+}
+
+// Exec_query_filter
+
+Exec_query_filter::Code::~Code()
+{
+}
+
+Exec_query_filter::Data::~Data()
+{
+}
+
+Exec_query_filter::~Exec_query_filter()
+{
+}
+
+void
+Exec_query_filter::alloc(Ctx& ctx, Ctl& ctl)
+{
+ // allocate the subquery
+ ctx_assert(m_query != 0);
+ m_query->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // allocate the predicate
+ ctl.m_query = m_query;
+ ctx_assert(m_pred != 0);
+ m_pred->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // re-use SqlRow from subquery
+ Exec_query::Data& dataQuery = m_query->getData();
+ Data& data = *new Data(this, dataQuery.sqlRow());
+ setData(data);
+}
+
+void
+Exec_query_filter::execImpl(Ctx& ctx, Ctl& ctl)
+{
+ // execute subquery
+ ctx_assert(m_query != 0);
+ m_query->execute(ctx, ctl);
+}
+
+bool
+Exec_query_filter::fetchImpl(Ctx& ctx, Ctl& ctl)
+{
+ // invoke fetch on subquery until predicate is true
+ ctx_assert(m_query != 0);
+ while (m_query->fetch(ctx, ctl)) {
+ ctx_assert(m_pred != 0);
+ m_pred->evaluate(ctx, ctl);
+ if (! ctx.ok())
+ return false;
+ if (m_pred->getData().getValue() == Pred_value_true) {
+ ctl.m_postEval = true;
+ m_pred->evaluate(ctx, ctl);
+ ctl.m_postEval = false;
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+Exec_query_filter::close(Ctx& ctx)
+{
+ ctx_assert(m_query != 0);
+ m_query->close(ctx);
+ ctx_assert(m_pred != 0);
+ m_pred->close(ctx);
+}
+
+void
+Exec_query_filter::print(Ctx& ctx)
+{
+ ctx.print(" [query_filter");
+ Exec_base* a[] = { m_query, m_pred };
+ printList(ctx, a, 2);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_filter.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_filter.hpp
new file mode 100644
index 00000000000..60cbf0f86a7
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_filter.hpp
@@ -0,0 +1,162 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_filter_hpp
+#define ODBC_CODEGEN_Code_query_filter_hpp
+
+#include <common/common.hpp>
+#include "Code_query.hpp"
+#include "Code_table_list.hpp"
+#include "Code_pred.hpp"
+
+/**
+ * @class Plan_query_filter
+ * @brief Filter node in PlanTree
+ */
+class Plan_query_filter : public Plan_query {
+public:
+ Plan_query_filter(Plan_root* root);
+ virtual ~Plan_query_filter();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setQuery(Plan_query* query);
+ void setPred(Plan_pred* pred);
+protected:
+ friend class Plan_select;
+ friend class Plan_update;
+ friend class Plan_delete;
+ Plan_query* m_query;
+ Plan_pred* m_pred;
+ Plan_table* m_topTable; // top level table for interpreted progs
+};
+
+inline
+Plan_query_filter::Plan_query_filter(Plan_root* root) :
+ Plan_query(root),
+ m_query(0),
+ m_pred(0),
+ m_topTable(0)
+{
+}
+
+// children
+
+inline void
+Plan_query_filter::setQuery(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+inline void
+Plan_query_filter::setPred(Plan_pred* pred)
+{
+ ctx_assert(pred != 0);
+ m_pred = pred;
+}
+
+/**
+ * @class Exec_query_filter
+ * @brief Filter node in ExecTree
+ */
+class Exec_query_filter : public Exec_query {
+public:
+ class Code : public Exec_query::Code {
+ public:
+ Code(const SqlSpecs& sqlSpecs);
+ virtual ~Code();
+ protected:
+ friend class Exec_query_filter;
+ // sets reference to SqlSpecs from subquery
+ };
+ class Data : public Exec_query::Data {
+ public:
+ Data(Exec_query_filter* node, const SqlRow& sqlRow);
+ virtual ~Data();
+ protected:
+ friend class Exec_query_filter;
+ // sets reference to SqlRow from subquery
+ };
+ Exec_query_filter(Exec_root* root);
+ virtual ~Exec_query_filter();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setQuery(Exec_query* query);
+ void setPred(Exec_pred* pred);
+protected:
+ Exec_query* m_query;
+ Exec_pred* m_pred;
+};
+
+inline
+Exec_query_filter::Code::Code(const SqlSpecs& sqlSpecs) :
+ Exec_query::Code(sqlSpecs)
+{
+}
+
+inline
+Exec_query_filter::Data::Data(Exec_query_filter* node, const SqlRow& sqlRow) :
+ Exec_query::Data(node, sqlRow)
+{
+}
+
+inline
+Exec_query_filter::Exec_query_filter(Exec_root* root) :
+ Exec_query(root),
+ m_query(0),
+ m_pred(0)
+{
+}
+
+// children
+
+inline const Exec_query_filter::Code&
+Exec_query_filter::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query_filter::Data&
+Exec_query_filter::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_query_filter::setQuery(Exec_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+inline void
+Exec_query_filter::setPred(Exec_pred* pred)
+{
+ ctx_assert(pred != 0);
+ m_pred = pred;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_group.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_group.cpp
new file mode 100644
index 00000000000..c3019efaa85
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_group.cpp
@@ -0,0 +1,301 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <algorithm>
+#include "Code_query_group.hpp"
+#include "Code_root.hpp"
+
+// Plan_query_group
+
+Plan_query_group::~Plan_query_group()
+{
+}
+
+Plan_expr_row*
+Plan_query_group::getRow()
+{
+ ctx_assert(m_dataRow != 0);
+ return m_dataRow;
+}
+
+Plan_base*
+Plan_query_group::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_query != 0);
+ m_query->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_dataRow != 0);
+ m_dataRow->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_groupRow != 0);
+ m_groupRow->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ if (m_havingPred != 0) {
+ ctl.m_having = true;
+ m_havingPred->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctl.m_having = false;
+ }
+ return this;
+}
+
+Exec_base*
+Plan_query_group::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // create code for the subquery
+ ctx_assert(m_query != 0);
+ Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execQuery != 0);
+ // create code for the rows based on query code
+ ctl.m_execQuery = execQuery;
+ ctx_assert(m_dataRow != 0);
+ Exec_expr_row* execDataRow = static_cast<Exec_expr_row*>(m_dataRow->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execDataRow != 0);
+ ctx_assert(m_groupRow != 0);
+ Exec_expr_row* execGroupRow = static_cast<Exec_expr_row*>(m_groupRow->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execGroupRow != 0);
+ Exec_pred* execHavingPred = 0;
+ if (m_havingPred != 0) {
+ ctl.m_having = true;
+ execHavingPred = static_cast<Exec_pred*>(m_havingPred->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execHavingPred != 0);
+ ctl.m_having = false;
+ }
+ // the exec node
+ Exec_query_group* exec = new Exec_query_group(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ // re-use SqlSpecs from data row
+ const SqlSpecs& sqlSpecs = execDataRow->getCode().sqlSpecs();
+ Exec_query_group::Code& code = *new Exec_query_group::Code(sqlSpecs);
+ exec->setCode(code);
+ exec->setQuery(execQuery);
+ exec->setDataRow(execDataRow);
+ exec->setGroupRow(execGroupRow);
+ if (execHavingPred != 0)
+ exec->setHavingPred(execHavingPred);
+ return exec;
+}
+
+void
+Plan_query_group::print(Ctx& ctx)
+{
+ ctx.print(" [query_group");
+ Plan_base* a[] = { m_query, m_dataRow, m_groupRow };
+ printList(ctx, a, 3);
+ ctx.print("]");
+}
+
+// Exec_query_group
+
+Exec_query_group::Code::~Code()
+{
+}
+
+Exec_query_group::Data::~Data()
+{
+ for (GroupList::iterator i = m_groupList.begin(); i != m_groupList.end(); i++) {
+ delete (*i).first;
+ }
+}
+
+Exec_query_group::~Exec_query_group()
+{
+}
+
+const Exec_query*
+Exec_query_group::getRawQuery() const
+{
+ ctx_assert(m_query != 0);
+ return m_query;
+}
+
+void
+Exec_query_group::alloc(Ctx& ctx, Ctl& ctl)
+{
+ // allocate subquery
+ ctx_assert(m_query != 0);
+ m_query->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // allocate rows based on subquery data
+ ctl.m_query = m_query;
+ ctx_assert(m_dataRow != 0);
+ m_dataRow->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ ctx_assert(m_groupRow != 0);
+ m_groupRow->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ if (m_havingPred != 0) {
+ m_havingPred->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ }
+ Data& data = *new Data(this, getCode().sqlSpecs());
+ setData(data);
+}
+
+void
+Exec_query_group::execImpl(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_query != 0);
+ m_query->execute(ctx, ctl);
+}
+
+bool
+GroupLess::operator()(const SqlRow* s1, const SqlRow* s2) const
+{
+ ctx_assert(s1 != 0 && s2 != 0);
+ const SqlRow& r1 = *s1;
+ const SqlRow& r2 = *s2;
+ for (unsigned i = 1; i <= r1.count(); i++) {
+ const SqlField& f1 = r1.getEntry(i);
+ const SqlField& f2 = r2.getEntry(i);
+ // nulls last is default in oracle
+ const bool f1null = f1.sqlNull();
+ const bool f2null = f2.sqlNull();
+ if (f1null && f2null)
+ continue;
+ if (! f1null && f2null)
+ return true;
+ if (f1null && ! f2null)
+ return false;
+ if (f1.less(f2))
+ return true;
+ if (f2.less(f1))
+ return false;
+ }
+ return false;
+}
+
+bool
+Exec_query_group::fetchImpl(Ctx& ctx, Ctl& ctl)
+{
+ Data& data = getData();
+ ctx_assert(m_query != 0 && m_groupRow != 0);
+ if (! data.m_grouped) {
+ // read and group all rows
+ while (m_query->fetch(ctx, ctl)) {
+ // evaluate and insert group-by values
+ m_groupRow->evaluate(ctx, ctl);
+ if (! ctx.ok())
+ return false;
+ const SqlRow* groupRow = 0;
+ unsigned index = 0;
+ bool init;
+ GroupList::iterator i = data.m_groupList.find(&m_groupRow->getData().sqlRow());
+ if (i == data.m_groupList.end()) {
+ groupRow = m_groupRow->getData().sqlRow().copy();
+ index = ++data.m_count;
+ const GroupList::value_type groupPair(groupRow, index);
+ data.m_groupList.insert(groupPair);
+ init = true;
+ } else {
+ groupRow = (*i).first;
+ index = (*i).second;
+ ctx_assert(groupRow != 0 && index != 0);
+ init = false;
+ }
+ // evaluate rows saving expression values at index position
+ ctl.m_groupIndex = index;
+ ctl.m_groupInit = init;
+ m_dataRow->evaluate(ctx, ctl);
+ if (! ctx.ok())
+ return false;
+ if (m_havingPred != 0) {
+ m_havingPred->evaluate(ctx, ctl);
+ if (! ctx.ok())
+ return false;
+ }
+ if (ctl.m_sortRow != 0) {
+ ctl.m_sortRow->evaluate(ctx, ctl);
+ if (! ctx.ok())
+ return false;
+ }
+ ctl.m_groupIndex = 0;
+ }
+ if (! ctx.ok())
+ return false;
+ data.m_iterator = data.m_groupList.begin();
+ data.m_grouped = true;
+ }
+ while (data.m_iterator != data.m_groupList.end()) {
+ const SqlRow* groupRow = (*data.m_iterator).first;
+ const unsigned index = (*data.m_iterator).second;
+ ctx_assert(groupRow != 0 && index != 0);
+ if (m_havingPred != 0) {
+ Pred_value v = m_havingPred->getData().groupValue(index);
+ if (v != Pred_value_true) {
+ data.m_iterator++;
+ continue;
+ }
+ }
+ // make our SqlRow reference to the saved values
+ for (unsigned i = 1; i <= data.m_sqlRow.count(); i++) {
+ const SqlField& currField = m_dataRow->getExpr(i)->getData().groupField(index);
+ SqlSpec sqlSpec(currField.sqlSpec(), SqlSpec::Reference);
+ SqlField sqlField(sqlSpec, &currField);
+ data.m_sqlRow.setEntry(i, sqlField);
+ }
+ // send group index up for possible order by
+ ctl.m_groupIndex = index;
+ data.m_iterator++;
+ return true;
+ }
+ return false;
+}
+
+void
+Exec_query_group::close(Ctx& ctx)
+{
+ Data& data = getData();
+ ctx_assert(m_query != 0);
+ m_query->close(ctx);
+ ctx_assert(m_dataRow != 0);
+ m_dataRow->close(ctx);
+ ctx_assert(m_groupRow != 0);
+ m_groupRow->close(ctx);
+ if (m_havingPred != 0)
+ m_havingPred->close(ctx);
+ data.m_grouped = false;
+ data.m_count = 0;
+ for (GroupList::iterator i = data.m_groupList.begin(); i != data.m_groupList.end(); i++) {
+ delete (*i).first;
+ }
+ data.m_groupList.clear();
+}
+
+void
+Exec_query_group::print(Ctx& ctx)
+{
+ ctx.print(" [query_group");
+ Exec_base* a[] = { m_query, m_dataRow, m_groupRow };
+ printList(ctx, a, 3);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_group.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_group.hpp
new file mode 100644
index 00000000000..e79022c5284
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_group.hpp
@@ -0,0 +1,221 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_group_hpp
+#define ODBC_CODEGEN_Code_query_group_hpp
+
+#include <functional>
+#include <common/common.hpp>
+#include "Code_query.hpp"
+#include "Code_expr_row.hpp"
+#include "Code_pred.hpp"
+
+/**
+ * @class Plan_query_group
+ * @brief Group-by node in PlanTree
+ */
+class Plan_query_group : public Plan_query {
+public:
+ Plan_query_group(Plan_root* root);
+ virtual ~Plan_query_group();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setQuery(Plan_query* query);
+ void setDataRow(Plan_expr_row* dataRow);
+ void setGroupRow(Plan_expr_row* groupRow);
+ void setHavingPred(Plan_pred* havingPred);
+ Plan_expr_row* getRow();
+protected:
+ Plan_query* m_query;
+ Plan_expr_row* m_dataRow;
+ Plan_expr_row* m_groupRow;
+ Plan_pred* m_havingPred;
+};
+
+inline
+Plan_query_group::Plan_query_group(Plan_root* root) :
+ Plan_query(root),
+ m_query(0),
+ m_dataRow(0),
+ m_groupRow(0),
+ m_havingPred(0)
+{
+}
+
+// children
+
+inline void
+Plan_query_group::setQuery(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+inline void
+Plan_query_group::setDataRow(Plan_expr_row* dataRow)
+{
+ ctx_assert(dataRow != 0);
+ m_dataRow = dataRow;
+}
+
+inline void
+Plan_query_group::setGroupRow(Plan_expr_row* groupRow)
+{
+ ctx_assert(groupRow != 0);
+ m_groupRow = groupRow;
+}
+
+inline void
+Plan_query_group::setHavingPred(Plan_pred* havingPred)
+{
+ ctx_assert(havingPred != 0);
+ m_havingPred = havingPred;
+}
+
+/**
+ * Group-by uses a std::map. Key is values grouped by. Data is unique index
+ * (starting at 1) into arrays in expression data.
+ */
+
+class Exec_query_group;
+
+struct GroupLess : std::binary_function<const SqlRow*, const SqlRow*, bool> {
+ bool operator()(const SqlRow* s1, const SqlRow* s2) const;
+};
+
+typedef std::map<const SqlRow*, unsigned, GroupLess> GroupList;
+
+/**
+ * @class Exec_query_group
+ * @brief Group-by node in ExecTree
+ */
+class Exec_query_group : public Exec_query {
+public:
+ class Code : public Exec_query::Code {
+ public:
+ Code(const SqlSpecs& sqlSpecs);
+ virtual ~Code();
+ protected:
+ friend class Exec_query_group;
+ // sets reference to Sqlspecs from subquery
+ };
+ class Data : public Exec_query::Data {
+ public:
+ Data(Exec_query_group* node, const SqlSpecs& sqlSpecs);
+ virtual ~Data();
+ protected:
+ friend class Exec_query_group;
+ SqlRow m_sqlRow; // current row
+ bool m_grouped; // fetch and group-by done
+ unsigned m_count;
+ GroupList m_groupList;
+ GroupList::iterator m_iterator;
+ };
+ Exec_query_group(Exec_root* root);
+ virtual ~Exec_query_group();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setQuery(Exec_query* query);
+ void setDataRow(Exec_expr_row* dataRow);
+ void setGroupRow(Exec_expr_row* groupRow);
+ void setHavingPred(Exec_pred* havingPred);
+ const Exec_query* getRawQuery() const;
+protected:
+ friend class Exec_query;
+ Exec_query* m_query;
+ Exec_expr_row* m_dataRow;
+ Exec_expr_row* m_groupRow;
+ Exec_pred* m_havingPred;
+};
+
+inline
+Exec_query_group::Code::Code(const SqlSpecs& sqlSpecs) :
+ Exec_query::Code(sqlSpecs)
+{
+}
+
+inline
+Exec_query_group::Data::Data(Exec_query_group* node, const SqlSpecs& sqlSpecs) :
+ Exec_query::Data(node, m_sqlRow),
+ m_sqlRow(sqlSpecs),
+ m_grouped(false),
+ m_count(0)
+{
+}
+
+inline
+Exec_query_group::Exec_query_group(Exec_root* root) :
+ Exec_query(root),
+ m_query(0),
+ m_dataRow(0),
+ m_groupRow(0),
+ m_havingPred(0)
+{
+}
+
+// children
+
+inline const Exec_query_group::Code&
+Exec_query_group::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query_group::Data&
+Exec_query_group::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_query_group::setQuery(Exec_query* query)
+{
+ ctx_assert(m_query == 0 && query != 0);
+ m_query = query;
+}
+
+inline void
+Exec_query_group::setDataRow(Exec_expr_row* dataRow)
+{
+ ctx_assert(m_dataRow == 0 && dataRow != 0);
+ m_dataRow = dataRow;
+}
+
+inline void
+Exec_query_group::setGroupRow(Exec_expr_row* groupRow)
+{
+ ctx_assert(m_groupRow == 0 && groupRow != 0);
+ m_groupRow = groupRow;
+}
+
+inline void
+Exec_query_group::setHavingPred(Exec_pred* havingPred)
+{
+ ctx_assert(m_havingPred == 0 && havingPred != 0);
+ m_havingPred = havingPred;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_index.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_index.cpp
new file mode 100644
index 00000000000..ee19d6123cc
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_index.cpp
@@ -0,0 +1,186 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_query_index.hpp"
+#include "Code_column.hpp"
+#include "Code_expr.hpp"
+#include "Code_root.hpp"
+
+// Plan_query_index
+
+Plan_query_index::~Plan_query_index()
+{
+}
+
+Plan_base*
+Plan_query_index::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+Exec_base*
+Plan_query_index::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // set up
+ ctx_assert(m_table != 0 && m_index != 0);
+ const BaseString& tableName = m_table->getName();
+ ctx_assert(m_index->m_dictIndex != 0);
+ const DictIndex& dictIndex = *m_index->m_dictIndex;
+ const BaseString& indexName = dictIndex.getName();
+ const unsigned keyCount = m_index->m_keyCount;
+ const ColumnVector& columns = m_table->exprColumns();
+ ctx_assert(columns.size() > 0);
+ const unsigned attrCount = columns.size() - 1;
+ // create the code
+ Exec_query_index::Code& code = *new Exec_query_index::Code(keyCount, attrCount);
+ code.m_tableName = strcpy(new char[tableName.length() + 1], tableName.c_str());
+ code.m_indexName = strcpy(new char[indexName.length() + 1], indexName.c_str());
+ // key attributes
+ code.m_keyId = new NdbAttrId[1 + keyCount];
+ code.m_keyId[0] = (NdbAttrId)-1;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ const DictColumn* keyColumn = dictIndex.getColumn(k);
+ const SqlType& sqlType = keyColumn->sqlType();
+ SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
+ code.m_keySpecs.setEntry(k, sqlSpec);
+ code.m_keyId[k] = k - 1; // index column order
+ }
+ // matching expressions
+ ctx_assert(m_index->m_keyFound);
+ const ExprVector& keyEq = m_index->m_keyEq;
+ ctx_assert(keyEq.size() == 1 + keyCount);
+ code.m_keyMatch = new Exec_expr* [1 + keyCount];
+ code.m_keyMatch[0] = 0;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ Plan_expr* expr = keyEq[k];
+ Exec_expr* execExpr = static_cast<Exec_expr*>(expr->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execExpr != 0);
+ code.m_keyMatch[k] = execExpr;
+ }
+ // queried attributes
+ code.m_attrId = new NdbAttrId[1 + attrCount];
+ code.m_attrId[0] = (NdbAttrId)-1;
+ for (unsigned i = 1; i <= attrCount; i++) {
+ Plan_column* column = columns[i];
+ ctx_assert(column != 0);
+ const DictColumn& dictColumn = column->dictColumn();
+ const SqlType& sqlType = dictColumn.sqlType();
+ SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
+ code.m_sqlSpecs.setEntry(i, sqlSpec);
+ code.m_attrId[i] = dictColumn.getAttrId();
+ }
+ // create the exec
+ Exec_query_index* exec = new Exec_query_index(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ exec->setCode(code);
+ return exec;
+}
+
+void
+Plan_query_index::print(Ctx& ctx)
+{
+ ctx.print(" [query_index");
+ Plan_base* a[] = { m_table };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
+
+// Exec_query_index
+
+Exec_query_index::Code::~Code()
+{
+ delete[] m_tableName;
+ delete[] m_keyId;
+ delete[] m_keyMatch;
+ delete[] m_attrId;
+}
+
+Exec_query_index::Data::~Data()
+{
+ delete[] m_recAttr;
+}
+
+Exec_query_index::~Exec_query_index()
+{
+}
+
+void
+Exec_query_index::alloc(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ // create data
+ Data& data = *new Data(this, code.sqlSpecs());
+ setData(data);
+ // allocate matching expressions
+ for (unsigned k = 1; k <= code.m_keyCount; k++) {
+ Exec_expr* expr = code.m_keyMatch[k];
+ ctx_assert(expr != 0);
+ expr->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ }
+ // needed for isNULL
+ data.m_recAttr = new NdbRecAttr* [1 + code.m_attrCount];
+ for (unsigned i = 0; i <= code.m_attrCount; i++) {
+ data.m_recAttr[i] = 0;
+ }
+}
+
+void
+Exec_query_index::close(Ctx& ctx)
+{
+ Data& data = getData();
+ if (data.m_con != 0) {
+ Ndb* const ndb = ndbObject();
+ ndb->closeTransaction(data.m_con);
+ data.m_con = 0;
+ data.m_op = 0;
+ data.m_done = true;
+ ctx_log2(("lookup closed at statement close"));
+ }
+}
+
+void
+Exec_query_index::print(Ctx& ctx)
+{
+ ctx.print(" [query_index");
+ if (m_code != 0) {
+ const Code& code = getCode();
+ ctx.print(" keyId=");
+ for (unsigned i = 1; i <= code.m_keyCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_keyId[i]);
+ }
+ ctx.print(" attrId=");
+ for (unsigned i = 1; i <= code.m_attrCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_attrId[i]);
+ }
+ ctx.print(" table=%s", code.m_tableName);
+ }
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_index.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_index.hpp
new file mode 100644
index 00000000000..87affd50580
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_index.hpp
@@ -0,0 +1,160 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_index_hpp
+#define ODBC_CODEGEN_Code_query_index_hpp
+
+#include <common/common.hpp>
+#include "Code_query.hpp"
+#include "Code_table.hpp"
+
+class Ctx;
+class StmtArea;
+class NdbConnection;
+class NdbOperation;
+class NdbRecAttr;
+
+/**
+ * @class Plan_query_index
+ * @brief Full select (no where clause)
+ */
+class Plan_query_index : public Plan_query {
+public:
+ Plan_query_index(Plan_root* root);
+ virtual ~Plan_query_index();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setTable(Plan_table* table, Plan_table::Index* index);
+protected:
+ Plan_table* m_table;
+ Plan_table::Index* m_index;
+};
+
+inline
+Plan_query_index::Plan_query_index(Plan_root* root) :
+ Plan_query(root),
+ m_table(0),
+ m_index(0)
+{
+}
+
+// children
+
+inline void
+Plan_query_index::setTable(Plan_table* table, Plan_table::Index* index)
+{
+ ctx_assert(table != 0 && index != 0 && index == &table->m_indexList[index->m_pos] && index->m_pos != 0);
+ m_table = table;
+ m_index = index;
+}
+
+/**
+ * @class Exec_query_index
+ * @brief Full select (no where clause)
+ */
+class Exec_query_index : public Exec_query {
+public:
+ class Code : public Exec_query::Code {
+ public:
+ Code(unsigned keyCount, unsigned attrCount);
+ virtual ~Code();
+ protected:
+ friend class Plan_query_index;
+ friend class Exec_query_index;
+ const char* m_tableName;
+ const char* m_indexName;
+ unsigned m_keyCount;
+ SqlSpecs m_keySpecs; // key types
+ NdbAttrId* m_keyId;
+ Exec_expr** m_keyMatch; // XXX pointers for now
+ unsigned m_attrCount;
+ SqlSpecs m_sqlSpecs;
+ NdbAttrId* m_attrId;
+ };
+ class Data : public Exec_query::Data {
+ public:
+ Data(Exec_query_index* node, const SqlSpecs& sqlSpecs);
+ virtual ~Data();
+ protected:
+ friend class Exec_query_index;
+ SqlRow m_sqlRow;
+ NdbConnection* m_con;
+ NdbOperation* m_op;
+ NdbRecAttr** m_recAttr;
+ bool m_done; // returns one row
+ };
+ Exec_query_index(Exec_root* root);
+ virtual ~Exec_query_index();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+};
+
+inline
+Exec_query_index::Code::Code(unsigned keyCount, unsigned attrCount) :
+ Exec_query::Code(m_sqlSpecs),
+ m_tableName(0),
+ m_indexName(0),
+ m_keyCount(keyCount),
+ m_keySpecs(keyCount),
+ m_keyId(0),
+ m_attrCount(attrCount),
+ m_sqlSpecs(attrCount),
+ m_attrId(0)
+{
+}
+
+inline
+Exec_query_index::Data::Data(Exec_query_index* node, const SqlSpecs& sqlSpecs) :
+ Exec_query::Data(node, m_sqlRow),
+ m_sqlRow(sqlSpecs),
+ m_con(0),
+ m_op(0),
+ m_recAttr(0),
+ m_done(false)
+{
+}
+
+inline
+Exec_query_index::Exec_query_index(Exec_root* root) :
+ Exec_query(root)
+{
+}
+
+// children
+
+inline const Exec_query_index::Code&
+Exec_query_index::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query_index::Data&
+Exec_query_index::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_join.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_join.cpp
new file mode 100644
index 00000000000..89aafe13610
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_join.cpp
@@ -0,0 +1,192 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_query.hpp"
+#include "Code_query_join.hpp"
+#include "Code_query_scan.hpp"
+#include "Code_root.hpp"
+
+// Plan_query_join
+
+Plan_query_join::~Plan_query_join()
+{
+}
+
+Plan_base*
+Plan_query_join::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_inner != 0);
+ m_inner->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_outer != 0);
+ m_outer->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+Exec_base*
+Plan_query_join::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // generate code for subqueries
+ ctx_assert(m_inner != 0);
+ Exec_query* execInner = static_cast<Exec_query*>(m_inner->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execInner != 0);
+ ctx_assert(m_outer != 0);
+ ctl.m_execQuery = execInner;
+ Exec_query* execOuter = static_cast<Exec_query*>(m_outer->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execOuter != 0);
+ // combine sql specs from subqueries
+ const SqlSpecs& specsInner = execInner->getCode().sqlSpecs();
+ const SqlSpecs& specsOuter = execOuter->getCode().sqlSpecs();
+ SqlSpecs sqlSpecs(specsInner.count() + specsOuter.count());
+ for (unsigned i = 1; i <= specsInner.count(); i++) {
+ const SqlSpec sqlSpec(specsInner.getEntry(i), SqlSpec::Reference);
+ sqlSpecs.setEntry(i, sqlSpec);
+ }
+ for (unsigned i = 1; i <= specsOuter.count(); i++) {
+ const SqlSpec sqlSpec(specsOuter.getEntry(i), SqlSpec::Reference);
+ sqlSpecs.setEntry(specsInner.count() + i, sqlSpec);
+ }
+ // create the code
+ Exec_query_join* exec = new Exec_query_join(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ exec->setInner(execInner);
+ exec->setOuter(execOuter);
+ Exec_query_join::Code& code = *new Exec_query_join::Code(sqlSpecs);
+ exec->setCode(code);
+ return exec;
+}
+
+void
+Plan_query_join::print(Ctx& ctx)
+{
+ ctx.print(" [query_join");
+ Plan_base* a[] = { m_inner, m_outer };
+ printList(ctx, a, 2);
+ ctx.print("]");
+}
+
+// Exec_query_join
+
+Exec_query_join::Code::~Code()
+{
+}
+
+Exec_query_join::Data::~Data()
+{
+}
+
+Exec_query_join::~Exec_query_join()
+{
+}
+
+void
+Exec_query_join::alloc(Ctx& ctx, Ctl& ctl)
+{
+ // allocate the subqueries
+ ctx_assert(m_inner != 0);
+ m_inner->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ ctx_assert(m_outer != 0);
+ ctl.m_query = m_inner;
+ m_outer->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // combine data rows from subqueries
+ const Code& code = getCode();
+ const SqlRow& rowInner = m_inner->getData().sqlRow();
+ const SqlRow& rowOuter = m_outer->getData().sqlRow();
+ SqlRow sqlRow(code.m_sqlSpecs);
+ for (unsigned i = 1; i <= rowInner.count(); i++) {
+ const SqlSpec& sqlSpec = code.m_sqlSpecs.getEntry(i);
+ const SqlField sqlField(sqlSpec, &rowInner.getEntry(i));
+ sqlRow.setEntry(i, sqlField);
+ }
+ for (unsigned i = 1; i <= rowOuter.count(); i++) {
+ const SqlSpec& sqlSpec = code.m_sqlSpecs.getEntry(rowInner.count() + i);
+ const SqlField sqlField(sqlSpec, &rowOuter.getEntry(i));
+ sqlRow.setEntry(rowInner.count() + i, sqlField);
+ }
+ // create the data
+ Data& data = *new Data(this, sqlRow);
+ setData(data);
+}
+
+void
+Exec_query_join::execImpl(Ctx& ctx, Ctl& ctl)
+{
+ // execute only inner query
+ ctx_assert(m_inner != 0);
+ m_inner->execute(ctx, ctl);
+}
+
+bool
+Exec_query_join::fetchImpl(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_inner != 0);
+ ctx_assert(m_outer != 0);
+ if (getData().getState() == ResultSet::State_init) {
+ // fetch first row from inner
+ if (! m_inner->fetch(ctx, ctl))
+ return false;
+ }
+ while (1) {
+ if (m_outer->getData().getState() == ResultSet::State_end) {
+ // execute or re-execute outer
+ Ctl ctl(0);
+ m_outer->close(ctx);
+ if (! ctx.ok())
+ return false;
+ m_outer->execute(ctx, ctl);
+ if (! ctx.ok())
+ return false;
+ }
+ if (! m_outer->fetch(ctx, ctl)) {
+ if (! ctx.ok())
+ return false;
+ // fetch next row from inner
+ if (! m_inner->fetch(ctx, ctl))
+ return false;
+ }
+ else
+ return true;
+ }
+}
+
+void
+Exec_query_join::close(Ctx& ctx)
+{
+ ctx_assert(m_inner != 0);
+ m_inner->close(ctx);
+ ctx_assert(m_outer != 0);
+ m_outer->close(ctx);
+}
+
+void
+Exec_query_join::print(Ctx& ctx)
+{
+ ctx.print(" [query_join");
+ Exec_base* a[] = { m_inner, m_outer };
+ printList(ctx, a, 2);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_join.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_join.hpp
new file mode 100644
index 00000000000..f6ac9205329
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_join.hpp
@@ -0,0 +1,159 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_join_hpp
+#define ODBC_CODEGEN_Code_query_join_hpp
+
+#include <common/common.hpp>
+#include "Code_query.hpp"
+#include "Code_table_list.hpp"
+#include "Code_pred.hpp"
+
+/**
+ * @class Plan_query_join
+ * @brief Filter node in PlanTree
+ */
+class Plan_query_join : public Plan_query {
+public:
+ Plan_query_join(Plan_root* root);
+ virtual ~Plan_query_join();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setInner(Plan_query* query);
+ void setOuter(Plan_query* query);
+protected:
+ Plan_query* m_inner;
+ Plan_query* m_outer;
+};
+
+inline
+Plan_query_join::Plan_query_join(Plan_root* root) :
+ Plan_query(root),
+ m_inner(0),
+ m_outer(0)
+{
+}
+
+// children
+
+inline void
+Plan_query_join::setInner(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_inner = query;
+}
+
+inline void
+Plan_query_join::setOuter(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_outer = query;
+}
+
+/**
+ * @class Exec_query_join
+ * @brief Filter node in ExecTree
+ */
+class Exec_query_join : public Exec_query {
+public:
+ class Code : public Exec_query::Code {
+ public:
+ Code(const SqlSpecs& sqlSpecs);
+ virtual ~Code();
+ protected:
+ friend class Exec_query_join;
+ SqlSpecs m_sqlSpecs;
+ };
+ class Data : public Exec_query::Data {
+ public:
+ Data(Exec_query_join* node, const SqlRow& sqlRow);
+ virtual ~Data();
+ protected:
+ friend class Exec_query_join;
+ SqlRow m_sqlRow;
+ };
+ Exec_query_join(Exec_root* root);
+ virtual ~Exec_query_join();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setInner(Exec_query* query);
+ void setOuter(Exec_query* query);
+protected:
+ Exec_query* m_inner;
+ Exec_query* m_outer;
+};
+
+inline
+Exec_query_join::Code::Code(const SqlSpecs& sqlSpecs) :
+ Exec_query::Code(m_sqlSpecs),
+ m_sqlSpecs(sqlSpecs)
+{
+}
+
+inline
+Exec_query_join::Data::Data(Exec_query_join* node, const SqlRow& sqlRow) :
+ Exec_query::Data(node, m_sqlRow),
+ m_sqlRow(sqlRow)
+{
+}
+
+inline
+Exec_query_join::Exec_query_join(Exec_root* root) :
+ Exec_query(root),
+ m_inner(0),
+ m_outer(0)
+{
+}
+
+// children
+
+inline const Exec_query_join::Code&
+Exec_query_join::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query_join::Data&
+Exec_query_join::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_query_join::setInner(Exec_query* query)
+{
+ ctx_assert(query != 0);
+ m_inner = query;
+}
+
+inline void
+Exec_query_join::setOuter(Exec_query* query)
+{
+ ctx_assert(query != 0);
+ m_outer = query;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_lookup.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_lookup.cpp
new file mode 100644
index 00000000000..bad4199190b
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_lookup.cpp
@@ -0,0 +1,184 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_query_lookup.hpp"
+#include "Code_column.hpp"
+#include "Code_expr.hpp"
+#include "Code_root.hpp"
+
+// Plan_query_lookup
+
+Plan_query_lookup::~Plan_query_lookup()
+{
+}
+
+Plan_base*
+Plan_query_lookup::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+Exec_base*
+Plan_query_lookup::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // set up
+ ctx_assert(m_table != 0);
+ const BaseString& tableName = m_table->getName();
+ const DictTable& dictTable = m_table->dictTable();
+ const unsigned keyCount = dictTable.keyCount();
+ const ColumnVector& columns = m_table->exprColumns();
+ ctx_assert(columns.size() > 0);
+ const unsigned attrCount = columns.size() - 1;
+ // create the code
+ Exec_query_lookup::Code& code = *new Exec_query_lookup::Code(keyCount, attrCount);
+ code.m_tableName = strcpy(new char[tableName.length() + 1], tableName.c_str());
+ // key attributes
+ code.m_keyId = new NdbAttrId[1 + keyCount];
+ code.m_keyId[0] = (NdbAttrId)-1;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ const DictColumn* keyColumn = dictTable.getKey(k);
+ const SqlType& sqlType = keyColumn->sqlType();
+ SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
+ code.m_keySpecs.setEntry(k, sqlSpec);
+ code.m_keyId[k] = keyColumn->getAttrId();
+ }
+ // matching expressions
+ const Plan_table::Index& index = m_table->m_indexList[0];
+ ctx_assert(index.m_keyFound);
+ const ExprVector& keyEq = index.m_keyEq;
+ ctx_assert(keyEq.size() == 1 + keyCount);
+ code.m_keyMatch = new Exec_expr* [1 + keyCount];
+ code.m_keyMatch[0] = 0;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ Plan_expr* expr = keyEq[k];
+ Exec_expr* execExpr = static_cast<Exec_expr*>(expr->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execExpr != 0);
+ code.m_keyMatch[k] = execExpr;
+ }
+ // queried attributes
+ code.m_attrId = new NdbAttrId[1 + attrCount];
+ code.m_attrId[0] = (NdbAttrId)-1;
+ for (unsigned i = 1; i <= attrCount; i++) {
+ Plan_column* column = columns[i];
+ ctx_assert(column != 0);
+ const DictColumn& dictColumn = column->dictColumn();
+ const SqlType& sqlType = dictColumn.sqlType();
+ SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
+ code.m_sqlSpecs.setEntry(i, sqlSpec);
+ code.m_attrId[i] = dictColumn.getAttrId();
+ }
+ // create the exec
+ Exec_query_lookup* exec = new Exec_query_lookup(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ exec->setCode(code);
+ return exec;
+}
+
+void
+Plan_query_lookup::print(Ctx& ctx)
+{
+ ctx.print(" [query_lookup");
+ Plan_base* a[] = { m_table };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
+
+// Exec_query_lookup
+
+Exec_query_lookup::Code::~Code()
+{
+ delete[] m_tableName;
+ delete[] m_keyId;
+ delete[] m_keyMatch;
+ delete[] m_attrId;
+}
+
+Exec_query_lookup::Data::~Data()
+{
+ delete[] m_recAttr;
+}
+
+Exec_query_lookup::~Exec_query_lookup()
+{
+}
+
+void
+Exec_query_lookup::alloc(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ // create data
+ Data& data = *new Data(this, code.sqlSpecs());
+ setData(data);
+ // allocate matching expressions
+ for (unsigned k = 1; k <= code.m_keyCount; k++) {
+ Exec_expr* expr = code.m_keyMatch[k];
+ ctx_assert(expr != 0);
+ expr->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ }
+ // needed for isNULL
+ data.m_recAttr = new NdbRecAttr* [1 + code.m_attrCount];
+ for (unsigned i = 0; i <= code.m_attrCount; i++) {
+ data.m_recAttr[i] = 0;
+ }
+}
+
+void
+Exec_query_lookup::close(Ctx& ctx)
+{
+ Data& data = getData();
+ if (data.m_con != 0) {
+ Ndb* const ndb = ndbObject();
+ ndb->closeTransaction(data.m_con);
+ data.m_con = 0;
+ data.m_op = 0;
+ data.m_done = true;
+ ctx_log2(("lookup closed at statement close"));
+ }
+}
+
+void
+Exec_query_lookup::print(Ctx& ctx)
+{
+ ctx.print(" [query_lookup");
+ if (m_code != 0) {
+ const Code& code = getCode();
+ ctx.print(" keyId=");
+ for (unsigned i = 1; i <= code.m_keyCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_keyId[i]);
+ }
+ ctx.print(" attrId=");
+ for (unsigned i = 1; i <= code.m_attrCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_attrId[i]);
+ }
+ ctx.print(" table=%s", code.m_tableName);
+ }
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_lookup.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_lookup.hpp
new file mode 100644
index 00000000000..e66623d4030
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_lookup.hpp
@@ -0,0 +1,155 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_lookup_hpp
+#define ODBC_CODEGEN_Code_query_lookup_hpp
+
+#include <common/common.hpp>
+#include "Code_query.hpp"
+#include "Code_table.hpp"
+
+class Ctx;
+class StmtArea;
+class NdbConnection;
+class NdbOperation;
+class NdbRecAttr;
+
+/**
+ * @class Plan_query_lookup
+ * @brief Full select (no where clause)
+ */
+class Plan_query_lookup : public Plan_query {
+public:
+ Plan_query_lookup(Plan_root* root);
+ virtual ~Plan_query_lookup();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setTable(Plan_table* table);
+protected:
+ Plan_table* m_table;
+};
+
+inline
+Plan_query_lookup::Plan_query_lookup(Plan_root* root) :
+ Plan_query(root),
+ m_table(0)
+{
+}
+
+// children
+
+inline void
+Plan_query_lookup::setTable(Plan_table* table)
+{
+ ctx_assert(table != 0);
+ m_table = table;
+}
+
+/**
+ * @class Exec_query_lookup
+ * @brief Full select (no where clause)
+ */
+class Exec_query_lookup : public Exec_query {
+public:
+ class Code : public Exec_query::Code {
+ public:
+ Code(unsigned keyCount, unsigned attrCount);
+ virtual ~Code();
+ protected:
+ friend class Plan_query_lookup;
+ friend class Exec_query_lookup;
+ char* m_tableName;
+ unsigned m_keyCount;
+ SqlSpecs m_keySpecs; // key types
+ NdbAttrId* m_keyId;
+ Exec_expr** m_keyMatch; // XXX pointers for now
+ unsigned m_attrCount;
+ SqlSpecs m_sqlSpecs;
+ NdbAttrId* m_attrId;
+ };
+ class Data : public Exec_query::Data {
+ public:
+ Data(Exec_query_lookup* node, const SqlSpecs& sqlSpecs);
+ virtual ~Data();
+ protected:
+ friend class Exec_query_lookup;
+ SqlRow m_sqlRow;
+ NdbConnection* m_con;
+ NdbOperation* m_op;
+ NdbRecAttr** m_recAttr;
+ bool m_done; // returns one row
+ };
+ Exec_query_lookup(Exec_root* root);
+ virtual ~Exec_query_lookup();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+};
+
+inline
+Exec_query_lookup::Code::Code(unsigned keyCount, unsigned attrCount) :
+ Exec_query::Code(m_sqlSpecs),
+ m_tableName(0),
+ m_keyCount(keyCount),
+ m_keySpecs(keyCount),
+ m_keyId(0),
+ m_attrCount(attrCount),
+ m_sqlSpecs(attrCount),
+ m_attrId(0)
+{
+}
+
+inline
+Exec_query_lookup::Data::Data(Exec_query_lookup* node, const SqlSpecs& sqlSpecs) :
+ Exec_query::Data(node, m_sqlRow),
+ m_sqlRow(sqlSpecs),
+ m_con(0),
+ m_op(0),
+ m_recAttr(0),
+ m_done(false)
+{
+}
+
+inline
+Exec_query_lookup::Exec_query_lookup(Exec_root* root) :
+ Exec_query(root)
+{
+}
+
+// children
+
+inline const Exec_query_lookup::Code&
+Exec_query_lookup::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query_lookup::Data&
+Exec_query_lookup::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_project.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_project.cpp
new file mode 100644
index 00000000000..54043ce3d5d
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_project.cpp
@@ -0,0 +1,184 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_query_project.hpp"
+#include "Code_root.hpp"
+
+// Plan_query_project
+
+Plan_query_project::~Plan_query_project()
+{
+}
+
+Plan_base*
+Plan_query_project::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_query != 0);
+ m_query->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_exprRow != 0);
+ ctl.m_aggrok = true;
+ ctl.m_aggrin = false;
+ m_exprRow->analyze(ctx, ctl);
+ ctl.m_aggrok = false;
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+Plan_expr_row*
+Plan_query_project::getRow()
+{
+ ctx_assert(m_exprRow != 0);
+ return m_exprRow;
+}
+
+Exec_base*
+Plan_query_project::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // create code for the subquery
+ ctx_assert(m_query != 0);
+ Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execQuery != 0);
+ // create code for the row based on query code
+ ctx_assert(m_exprRow != 0);
+ ctl.m_execQuery = execQuery;
+ Exec_expr_row* execRow = static_cast<Exec_expr_row*>(m_exprRow->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execRow != 0);
+ Exec_query_project* exec = new Exec_query_project(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ // re-use SqlSpecs from the row
+ const SqlSpecs& sqlSpecs = execRow->getCode().sqlSpecs();
+ Exec_query_project::Code& code = *new Exec_query_project::Code(sqlSpecs);
+ code.m_limitOff = m_limitOff;
+ code.m_limitCnt = m_limitCnt;
+ exec->setCode(code);
+ exec->setQuery(execQuery);
+ exec->setRow(execRow);
+ return exec;
+}
+
+void
+Plan_query_project::print(Ctx& ctx)
+{
+ ctx.print(" [query_project");
+ Plan_base* a[] = { m_query, m_exprRow };
+ printList(ctx, a, 2);
+ ctx.print("]");
+}
+
+// Exec_query_project
+
+Exec_query_project::Code::~Code()
+{
+}
+
+Exec_query_project::Data::~Data()
+{
+}
+
+Exec_query_project::~Exec_query_project()
+{
+}
+
+const Exec_query*
+Exec_query_project::getRawQuery() const
+{
+ ctx_assert(m_query != 0);
+ return m_query;
+}
+
+void
+Exec_query_project::alloc(Ctx& ctx, Ctl& ctl)
+{
+ // allocate the subquery
+ ctx_assert(m_query != 0);
+ m_query->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // allocate the row based on subquery data
+ ctx_assert(m_exprRow != 0);
+ ctl.m_query = m_query;
+ m_exprRow->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // re-use SqlRow from the expression row
+ const SqlRow& sqlRow = m_exprRow->getData().sqlRow();
+ Data& data = *new Data(this, sqlRow);
+ setData(data);
+}
+
+void
+Exec_query_project::execImpl(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_query != 0);
+ m_query->execute(ctx, ctl);
+}
+
+bool
+Exec_query_project::fetchImpl(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ Data& data = getData();
+ ctx_assert(m_query != 0);
+ while (1) {
+ if (! m_query->fetch(ctx, ctl))
+ return false;
+ ctx_assert(m_exprRow != 0);
+ m_exprRow->evaluate(ctx, ctl);
+ if (! ctx.ok())
+ return false;
+ ctl.m_postEval = true;
+ m_exprRow->evaluate(ctx, ctl);
+ ctl.m_postEval = false;
+ const int n = ++data.m_cnt;
+ const int o = code.m_limitOff <= 0 ? 0 : code.m_limitOff;
+ const int c = code.m_limitCnt;
+ if (n <= o)
+ continue;
+ if (c < 0)
+ break;
+ if (n - o <= c)
+ break;
+ return false;
+ }
+ return true;
+}
+
+void
+Exec_query_project::close(Ctx& ctx)
+{
+ Data& data = getData();
+ data.m_cnt = 0;
+ ctx_assert(m_query != 0);
+ m_query->close(ctx);
+ ctx_assert(m_exprRow != 0);
+ m_exprRow->close(ctx);
+}
+
+void
+Exec_query_project::print(Ctx& ctx)
+{
+ ctx.print(" [query_project");
+ Exec_base* a[] = { m_query, m_exprRow };
+ printList(ctx, a, 2);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_project.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_project.hpp
new file mode 100644
index 00000000000..545685ab9df
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_project.hpp
@@ -0,0 +1,178 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_project_hpp
+#define ODBC_CODEGEN_Code_query_project_hpp
+
+#include <common/common.hpp>
+#include "Code_query.hpp"
+#include "Code_expr_row.hpp"
+
+/**
+ * @class Plan_query_project
+ * @brief Project node in PlanTree
+ */
+class Plan_query_project : public Plan_query {
+public:
+ Plan_query_project(Plan_root* root);
+ virtual ~Plan_query_project();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setQuery(Plan_query* query);
+ void setRow(Plan_expr_row* exprRow);
+ void setLimit(int off, int cnt);
+protected:
+ Plan_expr_row* getRow();
+ Plan_query* m_query;
+ Plan_expr_row* m_exprRow;
+ int m_limitOff;
+ int m_limitCnt;
+};
+
+inline
+Plan_query_project::Plan_query_project(Plan_root* root) :
+ Plan_query(root),
+ m_query(0),
+ m_exprRow(0),
+ m_limitOff(0),
+ m_limitCnt(-1)
+{
+}
+
+// children
+
+inline void
+Plan_query_project::setQuery(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+inline void
+Plan_query_project::setRow(Plan_expr_row* exprRow)
+{
+ ctx_assert(exprRow != 0);
+ m_exprRow = exprRow;
+}
+
+inline void
+Plan_query_project::setLimit(int off, int cnt)
+{
+ m_limitOff = off;
+ m_limitCnt = cnt;
+}
+
+/**
+ * @class Exec_query_project
+ * @brief Project node in ExecTree
+ */
+class Exec_query_project : public Exec_query {
+public:
+ class Code : public Exec_query::Code {
+ public:
+ Code(const SqlSpecs& sqlSpecs);
+ virtual ~Code();
+ protected:
+ friend class Plan_query_project;
+ friend class Exec_query_project;
+ // sets reference to Sqlspecs from the row
+ int m_limitOff;
+ int m_limitCnt;
+ };
+ class Data : public Exec_query::Data {
+ public:
+ Data(Exec_query_project* node, const SqlRow& sqlRow);
+ virtual ~Data();
+ protected:
+ friend class Exec_query_project;
+ // sets reference to SqlRow from the row
+ unsigned m_cnt;
+ };
+ Exec_query_project(Exec_root* root);
+ virtual ~Exec_query_project();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setQuery(Exec_query* query);
+ void setRow(Exec_expr_row* exprRow);
+ const Exec_query* getRawQuery() const;
+protected:
+ friend class Exec_query;
+ Exec_query* m_query;
+ Exec_expr_row* m_exprRow;
+};
+
+inline
+Exec_query_project::Code::Code(const SqlSpecs& sqlSpecs) :
+ Exec_query::Code(sqlSpecs),
+ m_limitOff(0),
+ m_limitCnt(-1)
+{
+}
+
+inline
+Exec_query_project::Data::Data(Exec_query_project* node, const SqlRow& sqlRow) :
+ Exec_query::Data(node, sqlRow),
+ m_cnt(0)
+{
+}
+
+inline
+Exec_query_project::Exec_query_project(Exec_root* root) :
+ Exec_query(root),
+ m_query(0),
+ m_exprRow(0)
+{
+}
+
+// children
+
+inline const Exec_query_project::Code&
+Exec_query_project::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query_project::Data&
+Exec_query_project::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_query_project::setQuery(Exec_query* query)
+{
+ ctx_assert(m_query == 0 && query != 0);
+ m_query = query;
+}
+
+inline void
+Exec_query_project::setRow(Exec_expr_row* exprRow)
+{
+ ctx_assert(m_exprRow == 0 && exprRow != 0);
+ m_exprRow = exprRow;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_range.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_range.cpp
new file mode 100644
index 00000000000..5d29c5af315
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_range.cpp
@@ -0,0 +1,211 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_query_range.hpp"
+#include "Code_column.hpp"
+#include "Code_expr.hpp"
+#include "Code_root.hpp"
+
+// Plan_query_range
+
+Plan_query_range::~Plan_query_range()
+{
+}
+
+Plan_base*
+Plan_query_range::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+Exec_base*
+Plan_query_range::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // set up
+ ctx_assert(m_table != 0 && m_index != 0);
+ const BaseString& tableName = m_table->getName();
+ ctx_assert(m_index->m_dictIndex != 0);
+ const DictIndex& dictIndex = *m_index->m_dictIndex;
+ const BaseString& indexName = dictIndex.getName();
+ const unsigned keyCount = m_index->m_keyCountUsed;
+ const ColumnVector& columns = m_table->exprColumns();
+ ctx_assert(columns.size() > 0);
+ const unsigned attrCount = columns.size() - 1;
+ // create the code
+ Exec_query_range::Code& code = *new Exec_query_range::Code(keyCount, attrCount);
+ code.m_tableName = strcpy(new char[tableName.length() + 1], tableName.c_str());
+ code.m_indexName = strcpy(new char[indexName.length() + 1], indexName.c_str());
+ code.m_exclusive = m_exclusive;
+ // key attributes
+ code.m_keyId = new NdbAttrId[1 + keyCount];
+ code.m_keyId[0] = (NdbAttrId)-1;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ const DictColumn* keyColumn = dictIndex.getColumn(k);
+ const SqlType& sqlType = keyColumn->sqlType();
+ SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
+ code.m_keySpecs.setEntry(k, sqlSpec);
+ code.m_keyId[k] = k - 1; // index column order
+ }
+ // matching expressions
+ ctx_assert(m_index->m_keyFound);
+ const ExprVector& keyEq = m_index->m_keyEq;
+ // check size matches
+ ctx_assert(keyEq.size() == 1 + keyCount);
+ code.m_keyMatch = new Exec_expr* [1 + keyCount];
+ code.m_keyMatch[0] = 0;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ Plan_expr* expr = keyEq[k];
+ Exec_expr* execExpr = static_cast<Exec_expr*>(expr->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execExpr != 0);
+ code.m_keyMatch[k] = execExpr;
+ }
+ // queried attributes
+ code.m_attrId = new NdbAttrId[1 + attrCount];
+ code.m_attrId[0] = (NdbAttrId)-1;
+ for (unsigned i = 1; i <= attrCount; i++) {
+ Plan_column* column = columns[i];
+ ctx_assert(column != 0);
+ const DictColumn& dictColumn = column->dictColumn();
+ const SqlType& sqlType = dictColumn.sqlType();
+ SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
+ code.m_sqlSpecs.setEntry(i, sqlSpec);
+ code.m_attrId[i] = dictColumn.getAttrId();
+ }
+ // create the exec
+ Exec_query_range* exec = new Exec_query_range(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ exec->setCode(code);
+ // interpreter
+ ctl.m_execQuery = exec;
+ Exec_pred* execInterp = 0;
+ ctl.m_topTable = m_table;
+ if (m_interp != 0) {
+ execInterp = static_cast<Exec_pred*>(m_interp->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execInterp != 0);
+ }
+ ctl.m_topTable = 0;
+ if (m_interp != 0)
+ exec->setInterp(execInterp);
+ return exec;
+}
+
+void
+Plan_query_range::print(Ctx& ctx)
+{
+ ctx.print(" [query_range");
+ Plan_base* a[] = { m_table };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
+
+// Exec_query_range
+
+Exec_query_range::Code::~Code()
+{
+ delete[] m_tableName;
+ delete[] m_keyId;
+ delete[] m_keyMatch;
+ delete[] m_attrId;
+}
+
+Exec_query_range::Data::~Data()
+{
+ delete[] m_recAttr;
+}
+
+Exec_query_range::~Exec_query_range()
+{
+}
+
+void
+Exec_query_range::alloc(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ // create data
+ Data& data = *new Data(this, code.sqlSpecs());
+ setData(data);
+ // allocate matching expressions
+ for (unsigned k = 1; k <= code.m_keyCount; k++) {
+ Exec_expr* expr = code.m_keyMatch[k];
+ ctx_assert(expr != 0);
+ expr->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ }
+ // needed for isNULL
+ data.m_recAttr = new NdbRecAttr* [1 + code.m_attrCount];
+ for (unsigned i = 0; i <= code.m_attrCount; i++) {
+ data.m_recAttr[i] = 0;
+ }
+ // parallel
+ data.m_parallel = code.m_exclusive ? 1 : 240; // best supported
+ // interpreter
+ if (m_interp != 0) {
+ //m_interp->alloc(ctx, ctl); XXX
+ if (! ctx.ok())
+ return;
+ }
+}
+
+void
+Exec_query_range::close(Ctx& ctx)
+{
+ Data& data = getData();
+ if (data.m_con != 0) {
+ Ndb* const ndb = ndbObject();
+ ndb->closeTransaction(data.m_con);
+ data.m_con = 0;
+ data.m_op = 0;
+ data.m_done = true;
+ ctx_log2(("lookup closed at statement close"));
+ }
+ // if (m_interp != 0)
+ // m_interp->close(ctx);
+}
+
+void
+Exec_query_range::print(Ctx& ctx)
+{
+ ctx.print(" [query_range");
+ if (m_code != 0) {
+ const Code& code = getCode();
+ ctx.print(" keyId=");
+ for (unsigned i = 1; i <= code.m_keyCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_keyId[i]);
+ }
+ ctx.print(" attrId=");
+ for (unsigned i = 1; i <= code.m_attrCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_attrId[i]);
+ }
+ ctx.print(" table=%s", code.m_tableName);
+ }
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_range.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_range.hpp
new file mode 100644
index 00000000000..4438189522c
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_range.hpp
@@ -0,0 +1,186 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_range_hpp
+#define ODBC_CODEGEN_Code_query_range_hpp
+
+#include <common/common.hpp>
+#include "Code_query.hpp"
+#include "Code_table.hpp"
+#include "Code_pred.hpp"
+
+class Ctx;
+class StmtArea;
+class NdbConnection;
+class NdbOperation;
+class NdbRecAttr;
+
+/*
+ * Range scan via ordered index. We implement only the case of equality
+ * on an initial sequence of index keys.
+ */
+
+class Plan_query_range : public Plan_query {
+public:
+ Plan_query_range(Plan_root* root);
+ virtual ~Plan_query_range();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ void setTable(Plan_table* table, Plan_table::Index* index);
+ void setInterp(Plan_pred* interp);
+ void setExclusive();
+protected:
+ Plan_table* m_table;
+ Plan_table::Index* m_index;
+ Plan_pred* m_interp;
+ bool m_exclusive;
+};
+
+inline
+Plan_query_range::Plan_query_range(Plan_root* root) :
+ Plan_query(root),
+ m_table(0),
+ m_index(0),
+ m_interp(0),
+ m_exclusive(false)
+{
+}
+
+inline void
+Plan_query_range::setTable(Plan_table* table, Plan_table::Index* index)
+{
+ ctx_assert(table != 0 && index != 0 && index == &table->m_indexList[index->m_pos] && index->m_pos != 0);
+ m_table = table;
+ m_index = index;
+}
+
+inline void
+Plan_query_range::setInterp(Plan_pred* interp)
+{
+ ctx_assert(interp != 0);
+ m_interp = interp;
+}
+
+inline void
+Plan_query_range::setExclusive()
+{
+ m_exclusive = true;
+}
+
+class Exec_query_range : public Exec_query {
+public:
+ class Code : public Exec_query::Code {
+ public:
+ Code(unsigned keyCount, unsigned attrCount);
+ virtual ~Code();
+ protected:
+ friend class Plan_query_range;
+ friend class Exec_query_range;
+ const char* m_tableName;
+ const char* m_indexName;
+ unsigned m_keyCount;
+ SqlSpecs m_keySpecs; // key types
+ NdbAttrId* m_keyId;
+ Exec_expr** m_keyMatch; // XXX pointers for now
+ unsigned m_attrCount;
+ SqlSpecs m_sqlSpecs;
+ NdbAttrId* m_attrId;
+ bool m_exclusive;
+ };
+ class Data : public Exec_query::Data {
+ public:
+ Data(Exec_query_range* node, const SqlSpecs& sqlSpecs);
+ virtual ~Data();
+ protected:
+ friend class Exec_query_range;
+ SqlRow m_sqlRow;
+ NdbConnection* m_con;
+ NdbOperation* m_op;
+ NdbRecAttr** m_recAttr;
+ unsigned m_parallel;
+ bool m_done; // if no match possible due to range
+ };
+ Exec_query_range(Exec_root* root);
+ virtual ~Exec_query_range();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ const Code& getCode() const;
+ Data& getData() const;
+ void setInterp(Exec_pred* interp);
+protected:
+ Exec_pred* m_interp;
+};
+
+inline
+Exec_query_range::Code::Code(unsigned keyCount, unsigned attrCount) :
+ Exec_query::Code(m_sqlSpecs),
+ m_tableName(0),
+ m_indexName(0),
+ m_keyCount(keyCount),
+ m_keySpecs(keyCount),
+ m_keyId(0),
+ m_attrCount(attrCount),
+ m_sqlSpecs(attrCount),
+ m_attrId(0),
+ m_exclusive(false)
+{
+}
+
+inline
+Exec_query_range::Data::Data(Exec_query_range* node, const SqlSpecs& sqlSpecs) :
+ Exec_query::Data(node, m_sqlRow),
+ m_sqlRow(sqlSpecs),
+ m_con(0),
+ m_op(0),
+ m_recAttr(0),
+ m_parallel(1),
+ m_done(false)
+{
+}
+
+inline
+Exec_query_range::Exec_query_range(Exec_root* root) :
+ Exec_query(root),
+ m_interp(0)
+{
+}
+
+inline const Exec_query_range::Code&
+Exec_query_range::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query_range::Data&
+Exec_query_range::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_query_range::setInterp(Exec_pred* interp)
+{
+ ctx_assert(interp != 0);
+ m_interp = interp;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_repeat.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_repeat.cpp
new file mode 100644
index 00000000000..8b295a97916
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_repeat.cpp
@@ -0,0 +1,109 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_query_repeat.hpp"
+#include "Code_root.hpp"
+
+// Plan_query_repeat
+
+Plan_query_repeat::~Plan_query_repeat()
+{
+}
+
+Plan_base*
+Plan_query_repeat::analyze(Ctx& ctx, Ctl& ctl)
+{
+ return this;
+}
+
+Exec_base*
+Plan_query_repeat::codegen(Ctx& ctx, Ctl& ctl)
+{
+ Exec_query_repeat* exec = new Exec_query_repeat(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ // SqlSpecs is empty
+ const SqlSpecs sqlSpecs(0);
+ Exec_query_repeat::Code& code = *new Exec_query_repeat::Code(sqlSpecs, m_forever, m_maxcount);
+ exec->setCode(code);
+ return exec;
+}
+
+void
+Plan_query_repeat::print(Ctx& ctx)
+{
+ ctx.print(" [query_repeat");
+ if (! m_forever)
+ ctx.print(" %ld", (long)m_maxcount);
+ ctx.print("]");
+}
+
+// Exec_query_repeat
+
+Exec_query_repeat::Code::~Code()
+{
+}
+
+Exec_query_repeat::Data::~Data()
+{
+}
+
+Exec_query_repeat::~Exec_query_repeat()
+{
+}
+
+void
+Exec_query_repeat::alloc(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ // SqlRow is empty
+ Data& data = *new Data(this, code.sqlSpecs());
+ setData(data);
+}
+
+void
+Exec_query_repeat::execImpl(Ctx& ctx, Ctl& ctl)
+{
+ Data& data = getData();
+ data.m_count = 0;
+}
+
+bool
+Exec_query_repeat::fetchImpl(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ Data& data = getData();
+ // fetch until count is up
+ if (code.m_forever || data.m_count < code.m_maxcount) {
+ data.m_count++;
+ return true;
+ }
+ return false;
+}
+
+void
+Exec_query_repeat::close(Ctx& ctx)
+{
+}
+
+void
+Exec_query_repeat::print(Ctx& ctx)
+{
+ const Code& code = getCode();
+ ctx.print(" [query_repeat");
+ if (! code.m_forever)
+ ctx.print(" %ld", (long)code.m_maxcount);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_repeat.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_repeat.hpp
new file mode 100644
index 00000000000..90d6ef55104
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_repeat.hpp
@@ -0,0 +1,133 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_repeat_hpp
+#define ODBC_CODEGEN_Code_query_repeat_hpp
+
+#include <common/common.hpp>
+#include "Code_query.hpp"
+#include "Code_expr_row.hpp"
+
+/**
+ * @class Plan_query_repeat
+ * @brief Constant query node in PlanTree
+ */
+class Plan_query_repeat : public Plan_query {
+public:
+ Plan_query_repeat(Plan_root* root);
+ Plan_query_repeat(Plan_root* root, CountType maxcount);
+ virtual ~Plan_query_repeat();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+private:
+ bool m_forever;
+ CountType m_maxcount;
+};
+
+inline
+Plan_query_repeat::Plan_query_repeat(Plan_root* root) :
+ Plan_query(root),
+ m_forever(true),
+ m_maxcount(0)
+{
+}
+
+inline
+Plan_query_repeat::Plan_query_repeat(Plan_root* root, CountType maxcount) :
+ Plan_query(root),
+ m_forever(false),
+ m_maxcount(maxcount)
+{
+}
+
+/**
+ * @class Exec_query_repeat
+ * @brief Constant query node in ExecTree
+ */
+class Exec_query_repeat : public Exec_query {
+public:
+ class Code : public Exec_query::Code {
+ public:
+ Code(const SqlSpecs& sqlSpecs, bool forever, CountType maxcount);
+ virtual ~Code();
+ protected:
+ friend class Exec_query_repeat;
+ SqlSpecs m_sqlSpecs;
+ bool m_forever;
+ CountType m_maxcount;
+ };
+ class Data : public Exec_query::Data {
+ public:
+ Data(Exec_query_repeat* node, const SqlSpecs& sqlSpecs);
+ virtual ~Data();
+ protected:
+ friend class Exec_query_repeat;
+ SqlRow m_sqlRow;
+ CountType m_count;
+ };
+ Exec_query_repeat(Exec_root* root);
+ virtual ~Exec_query_repeat();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+};
+
+inline
+Exec_query_repeat::Code::Code(const SqlSpecs& sqlSpecs, bool forever, CountType maxcount) :
+ Exec_query::Code(m_sqlSpecs),
+ m_sqlSpecs(sqlSpecs),
+ m_forever(forever),
+ m_maxcount(maxcount)
+{
+}
+
+inline
+Exec_query_repeat::Data::Data(Exec_query_repeat* node, const SqlSpecs& sqlSpecs) :
+ Exec_query::Data(node, m_sqlRow),
+ m_sqlRow(sqlSpecs),
+ m_count(0)
+{
+}
+
+inline
+Exec_query_repeat::Exec_query_repeat(Exec_root* root) :
+ Exec_query(root)
+{
+}
+
+// children
+
+inline const Exec_query_repeat::Code&
+Exec_query_repeat::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query_repeat::Data&
+Exec_query_repeat::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_scan.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_scan.cpp
new file mode 100644
index 00000000000..1c0f58980e5
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_scan.cpp
@@ -0,0 +1,177 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NdbApi.hpp>
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_query_scan.hpp"
+#include "Code_column.hpp"
+#include "Code_root.hpp"
+
+// Plan_query_scan
+
+Plan_query_scan::~Plan_query_scan()
+{
+}
+
+Plan_base*
+Plan_query_scan::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ if (m_interp != 0) {
+ m_interp = static_cast<Plan_pred*>(m_interp->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_interp != 0);
+ }
+ return this;
+}
+
+Exec_base*
+Plan_query_scan::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // set up
+ ctx_assert(m_table != 0);
+ const BaseString& tableName = m_table->getName();
+ const DictTable& dictTable = m_table->dictTable();
+ const ColumnVector& columns = m_table->exprColumns();
+ ctx_assert(columns.size() > 0);
+ const unsigned attrCount = columns.size() - 1;
+ // create the code
+ Exec_query_scan::Code& code = *new Exec_query_scan::Code(attrCount);
+ code.m_tableName = strcpy(new char[tableName.length() + 1], tableName.c_str());
+ code.m_exclusive = m_exclusive;
+ // queried attributes
+ code.m_attrId = new NdbAttrId[1 + attrCount];
+ code.m_attrId[0] = (NdbAttrId)-1;
+ for (unsigned i = 1; i <= attrCount; i++) {
+ Plan_column* column = columns[i];
+ ctx_assert(column != 0);
+ const DictColumn& dictColumn = column->dictColumn();
+ const SqlType& sqlType = dictColumn.sqlType();
+ SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
+ code.m_sqlSpecs.setEntry(i, sqlSpec);
+ code.m_attrId[i] = dictColumn.getAttrId();
+ }
+ // create the exec
+ Exec_query_scan* exec = new Exec_query_scan(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ exec->setCode(code);
+ // interpreter
+ Exec_pred* execInterp = 0;
+ ctl.m_execQuery = exec;
+ ctl.m_topTable = m_table;
+ if (m_interp != 0) {
+ execInterp = static_cast<Exec_pred*>(m_interp->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execInterp != 0);
+ }
+ ctl.m_topTable = 0;
+ if (m_interp != 0)
+ exec->setInterp(execInterp);
+ return exec;
+}
+
+void
+Plan_query_scan::print(Ctx& ctx)
+{
+ ctx.print(" [query_scan");
+ Plan_base* a[] = { m_table, m_interp };
+ printList(ctx, a, 2);
+ ctx.print("]");
+}
+
+// Exec_query_scan
+
+Exec_query_scan::Code::~Code()
+{
+ delete[] m_tableName;
+ delete[] m_attrId;
+}
+
+Exec_query_scan::Data::~Data()
+{
+ delete[] m_recAttr;
+}
+
+Exec_query_scan::~Exec_query_scan()
+{
+}
+
+void
+Exec_query_scan::alloc(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ // create data
+ Data& data = *new Data(this, code.sqlSpecs());
+ // needed for isNULL
+ data.m_recAttr = new NdbRecAttr* [1 + code.m_attrCount];
+ for (unsigned i = 0; i <= code.m_attrCount; i++) {
+ data.m_recAttr[i] = 0;
+ }
+ data.m_parallel = code.m_exclusive ? 1 : 240; // best supported
+ setData(data);
+ // interpreter
+ ctl.m_query = this;
+ if (m_interp != 0) {
+ //m_interp->alloc(ctx, ctl); XXX
+ if (! ctx.ok())
+ return;
+ }
+}
+
+void
+Exec_query_scan::close(Ctx& ctx)
+{
+ Data& data = getData();
+ if (data.m_con != 0) {
+ Ndb* const ndb = ndbObject();
+ int ret = data.m_con->stopScan();
+ if (ret == -1) {
+ ctx.pushStatus(ndb, data.m_con, data.m_op, "stopScan");
+ }
+ ndb->closeTransaction(data.m_con);
+ data.m_con = 0;
+ data.m_op = 0;
+ ctx_log2(("scan closed at statement close"));
+ }
+ if (m_interp != 0)
+ m_interp->close(ctx);
+}
+
+void
+Exec_query_scan::print(Ctx& ctx)
+{
+ ctx.print(" [query_scan");
+ if (m_code != 0) {
+ const Code& code = getCode();
+ ctx.print(" attrId=");
+ for (unsigned i = 1; i <= code.m_attrCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_attrId[i]);
+ }
+ ctx.print(" table=%s", code.m_tableName);
+ }
+ if (m_interp != 0)
+ m_interp->print(ctx);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_scan.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_scan.hpp
new file mode 100644
index 00000000000..d6d1630ddf8
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_scan.hpp
@@ -0,0 +1,174 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_scan_hpp
+#define ODBC_CODEGEN_Code_query_scan_hpp
+
+#include <common/common.hpp>
+#include "Code_query.hpp"
+#include "Code_table.hpp"
+#include "Code_pred.hpp"
+
+class Ctx;
+class StmtArea;
+class NdbConnection;
+class NdbOperation;
+class NdbRecAttr;
+
+/*
+ * Table scan.
+ */
+
+class Plan_query_scan : public Plan_query {
+public:
+ Plan_query_scan(Plan_root* root);
+ virtual ~Plan_query_scan();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ void setTable(Plan_table* table);
+ void setInterp(Plan_pred* interp);
+ void setExclusive();
+protected:
+ Plan_table* m_table;
+ Plan_pred* m_interp;
+ bool m_exclusive; // exclusive
+};
+
+inline
+Plan_query_scan::Plan_query_scan(Plan_root* root) :
+ Plan_query(root),
+ m_table(0),
+ m_interp(0),
+ m_exclusive(false)
+{
+}
+
+inline void
+Plan_query_scan::setTable(Plan_table* table)
+{
+ ctx_assert(table != 0);
+ m_table = table;
+}
+
+inline void
+Plan_query_scan::setInterp(Plan_pred* interp)
+{
+ ctx_assert(interp != 0);
+ m_interp = interp;
+}
+
+inline void
+Plan_query_scan::setExclusive()
+{
+ m_exclusive = true;
+}
+
+class Exec_query_scan : public Exec_query {
+public:
+ class Code : public Exec_query::Code {
+ public:
+ Code(unsigned attrCount);
+ virtual ~Code();
+ protected:
+ friend class Plan_query_scan;
+ friend class Exec_query_scan;
+ char* m_tableName;
+ unsigned m_attrCount;
+ SqlSpecs m_sqlSpecs;
+ NdbAttrId* m_attrId;
+ bool m_exclusive;
+ };
+ class Data : public Exec_query::Data {
+ public:
+ Data(Exec_query_scan* node, const SqlSpecs& sqlSpecs);
+ virtual ~Data();
+ protected:
+ friend class Exec_query_scan;
+ SqlRow m_sqlRow;
+ NdbConnection* m_con;
+ NdbOperation* m_op;
+ NdbRecAttr** m_recAttr;
+ unsigned m_parallel; // parallelism could be runtime option
+ };
+ Exec_query_scan(Exec_root* root);
+ virtual ~Exec_query_scan();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setInterp(Exec_pred* interp);
+protected:
+ Exec_pred* m_interp;
+};
+
+inline
+Exec_query_scan::Code::Code(unsigned attrCount) :
+ Exec_query::Code(m_sqlSpecs),
+ m_tableName(0),
+ m_attrCount(attrCount),
+ m_sqlSpecs(attrCount),
+ m_attrId(0),
+ m_exclusive(false)
+{
+}
+
+inline
+Exec_query_scan::Data::Data(Exec_query_scan* node, const SqlSpecs& sqlSpecs) :
+ Exec_query::Data(node, m_sqlRow),
+ m_sqlRow(sqlSpecs),
+ m_con(0),
+ m_op(0),
+ m_recAttr(0),
+ m_parallel(1)
+{
+}
+
+inline
+Exec_query_scan::Exec_query_scan(Exec_root* root) :
+ Exec_query(root),
+ m_interp(0)
+{
+}
+
+// children
+
+inline const Exec_query_scan::Code&
+Exec_query_scan::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query_scan::Data&
+Exec_query_scan::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_query_scan::setInterp(Exec_pred* interp)
+{
+ ctx_assert(interp != 0);
+ m_interp = interp;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_sort.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_sort.cpp
new file mode 100644
index 00000000000..4ea6db8c4e2
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_sort.cpp
@@ -0,0 +1,239 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <algorithm>
+#include "Code_query_sort.hpp"
+#include "Code_root.hpp"
+
+// Plan_query_sort
+
+Plan_query_sort::~Plan_query_sort()
+{
+}
+
+Plan_expr_row*
+Plan_query_sort::getRow()
+{
+ ctx_assert(m_query != 0);
+ return m_query->getRow();
+}
+
+Plan_base*
+Plan_query_sort::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_query != 0);
+ m_query->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_sortRow != 0);
+ m_sortRow->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+Exec_base*
+Plan_query_sort::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // create code for the subquery
+ ctx_assert(m_query != 0);
+ Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execQuery != 0);
+ // create code for the row based on query code
+ ctx_assert(m_sortRow != 0);
+ ctl.m_execQuery = execQuery->getRawQuery();
+ Exec_expr_row* execRow = static_cast<Exec_expr_row*>(m_sortRow->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execRow != 0);
+ Exec_query_sort* exec = new Exec_query_sort(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ // re-use SqlSpecs from subquery
+ const Exec_query::Code& codeQuery = execQuery->getCode();
+ const SqlSpecs& sqlSpecs = codeQuery.sqlSpecs();
+ // make asc
+ unsigned size = m_sortRow->getSize();
+ bool* asc = new bool[1 + size];
+ for (unsigned i = 1; i <= size; i++) {
+ asc[i] = m_sortRow->m_ascList[i];
+ }
+ Exec_query_sort::Code& code = *new Exec_query_sort::Code(sqlSpecs, asc);
+ exec->setCode(code);
+ exec->setQuery(execQuery);
+ exec->setRow(execRow);
+ return exec;
+}
+
+void
+Plan_query_sort::print(Ctx& ctx)
+{
+ ctx.print(" [query_sort");
+ Plan_base* a[] = { m_query, m_sortRow };
+ printList(ctx, a, 2);
+ ctx.print("]");
+}
+
+// Exec_query_sort
+
+Exec_query_sort::Code::~Code()
+{
+}
+
+Exec_query_sort::Data::~Data()
+{
+ for (unsigned i = 0; i < m_sortList.size(); i++) {
+ SortItem& sortItem = m_sortList[i];
+ delete sortItem.m_dataRow;
+ delete sortItem.m_sortRow;
+ }
+}
+
+Exec_query_sort::~Exec_query_sort()
+{
+}
+
+void
+Exec_query_sort::alloc(Ctx& ctx, Ctl& ctl)
+{
+ // allocate subquery
+ ctx_assert(m_query != 0);
+ m_query->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // allocate sort row based on subquery data
+ ctx_assert(m_sortRow != 0);
+ ctl.m_query = m_query->getRawQuery();
+ m_sortRow->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ Data& data = *new Data(this, getCode().sqlSpecs());
+ setData(data);
+}
+
+void
+Exec_query_sort::execImpl(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_query != 0 && m_sortRow != 0);
+ ctl.m_sortRow = m_sortRow;
+ m_query->execute(ctx, ctl);
+}
+
+bool
+SortLess::operator()(SortItem s1, SortItem s2) const
+{
+ const Exec_query_sort::Code& code = m_node->getCode();
+ const SqlRow& r1 = *s1.m_sortRow;
+ const SqlRow& r2 = *s2.m_sortRow;
+ for (unsigned i = 1; i <= r1.count(); i++) {
+ const SqlField& f1 = r1.getEntry(i);
+ const SqlField& f2 = r2.getEntry(i);
+ // nulls last is default in oracle
+ bool f1null = f1.sqlNull();
+ bool f2null = f2.sqlNull();
+ if (f1null && f2null)
+ continue;
+ if (! f1null && f2null)
+ return code.getAsc(i) ? true : false;
+ if (f1null && ! f2null)
+ return code.getAsc(i) ? false : true;
+ if (f1.less(f2))
+ return code.getAsc(i) ? true : false;
+ if (f2.less(f1))
+ return code.getAsc(i) ? false : true;
+ }
+ return false;
+}
+
+bool
+Exec_query_sort::fetchImpl(Ctx& ctx, Ctl& ctl)
+{
+ Data& data = getData();
+ ctx_assert(m_query != 0 && m_sortRow != 0);
+ ctl.m_sortRow = m_sortRow;
+ if (! data.m_sorted) {
+ // read and cache all rows
+ data.m_count = 0;
+ while (m_query->fetch(ctx, ctl)) {
+ const SqlRow* dataRow = m_query->getData().sqlRow().copy();
+ const SqlRow* sortRow = 0;
+ if (ctl.m_groupIndex == 0) {
+ // evaluate sort row
+ m_sortRow->evaluate(ctx, ctl);
+ if (! ctx.ok())
+ return false;
+ sortRow = m_sortRow->getData().sqlRow().copy();
+ } else {
+ // evaluate done by group-by
+ SqlRow tmpSortRow(m_sortRow->getCode().sqlSpecs());
+ for (unsigned i = 1; i <= tmpSortRow.count(); i++) {
+ tmpSortRow.setEntry(i, m_sortRow->getExpr(i)->getData().groupField(ctl.m_groupIndex));
+ }
+ sortRow = tmpSortRow.copy();
+ }
+ SortItem sortItem(dataRow, sortRow);
+ data.m_sortList.push_back(sortItem);
+ data.m_count++;
+ }
+ data.m_index = 0;
+ if (! ctx.ok())
+ return false;
+ // sort the rows XXX use iterated stable_sort
+ SortLess sortLess(this);
+ std::sort(data.m_sortList.begin(), data.m_sortList.end(), sortLess);
+ data.m_sorted = true;
+ }
+ if (data.m_index < data.m_count) {
+ // make our SqlRow reference to current row
+ const SqlRow& currRow = *data.m_sortList[data.m_index].m_dataRow;
+ for (unsigned i = 1; i <= data.m_sqlRow.count(); i++) {
+ const SqlField& currField = currRow.getEntry(i);
+ SqlSpec sqlSpec(currField.sqlSpec(), SqlSpec::Reference);
+ SqlField sqlField(sqlSpec, &currField);
+ data.m_sqlRow.setEntry(i, sqlField);
+ }
+ data.m_index++;
+ return true;
+ }
+ return false;
+}
+
+void
+Exec_query_sort::close(Ctx& ctx)
+{
+ Data& data = getData();
+ ctx_assert(m_query != 0);
+ m_query->close(ctx);
+ data.m_sorted = false;
+ for (unsigned i = 0; i < data.m_sortList.size(); i++) {
+ SortItem& sortItem = data.m_sortList[i];
+ delete sortItem.m_dataRow;
+ delete sortItem.m_sortRow;
+ }
+ data.m_sortList.clear();
+ data.m_count = 0;
+ data.m_index = 0;
+}
+
+void
+Exec_query_sort::print(Ctx& ctx)
+{
+ ctx.print(" [query_sort");
+ Exec_base* a[] = { m_query, m_sortRow };
+ printList(ctx, a, 2);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_sort.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_sort.hpp
new file mode 100644
index 00000000000..d1aa03d9aef
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_sort.hpp
@@ -0,0 +1,208 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_sort_hpp
+#define ODBC_CODEGEN_Code_query_sort_hpp
+
+#include <functional>
+#include <common/common.hpp>
+#include "Code_query.hpp"
+#include "Code_expr_row.hpp"
+
+/**
+ * @class Plan_query_sort
+ * @brief Project node in PlanTree
+ */
+class Plan_query_sort : public Plan_query {
+public:
+ Plan_query_sort(Plan_root* root);
+ virtual ~Plan_query_sort();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setQuery(Plan_query* query);
+ void setRow(Plan_expr_row* sortRow);
+protected:
+ Plan_expr_row* getRow();
+ Plan_query* m_query;
+ Plan_expr_row* m_sortRow;
+};
+
+inline
+Plan_query_sort::Plan_query_sort(Plan_root* root) :
+ Plan_query(root),
+ m_query(0),
+ m_sortRow(0)
+{
+}
+
+// children
+
+inline void
+Plan_query_sort::setQuery(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+inline void
+Plan_query_sort::setRow(Plan_expr_row* sortRow)
+{
+ ctx_assert(sortRow != 0);
+ m_sortRow = sortRow;
+}
+
+/**
+ * Item to sort includes data row and sort row.
+ */
+struct SortItem {
+ SortItem(const SqlRow* dataRow, const SqlRow* sortRow);
+ const SqlRow* m_dataRow; // copy of fetched row from subquery
+ const SqlRow* m_sortRow; // copy of values to sort on
+};
+
+typedef std::vector<SortItem> SortList;
+
+class Exec_query_sort;
+
+struct SortLess : std::binary_function<SortItem, SortItem, bool> {
+ SortLess(const Exec_query_sort* node);
+ const Exec_query_sort* m_node;
+ bool operator()(SortItem s1, SortItem s2) const;
+};
+
+inline
+SortItem::SortItem(const SqlRow* dataRow, const SqlRow* sortRow) :
+ m_dataRow(dataRow),
+ m_sortRow(sortRow)
+{
+}
+
+inline
+SortLess::SortLess(const Exec_query_sort* node) :
+ m_node(node)
+{
+}
+
+/**
+ * @class Exec_query_sort
+ * @brief Project node in ExecTree
+ */
+class Exec_query_sort : public Exec_query {
+public:
+ class Code : public Exec_query::Code {
+ public:
+ Code(const SqlSpecs& sqlSpecs, bool* asc);
+ virtual ~Code();
+ bool getAsc(unsigned i) const;
+ protected:
+ friend class Exec_query_sort;
+ const bool* const m_asc;
+ // sets reference to Sqlspecs from subquery
+ };
+ class Data : public Exec_query::Data {
+ public:
+ Data(Exec_query_sort* node, const SqlSpecs& sqlSpecs);
+ virtual ~Data();
+ protected:
+ friend class Exec_query_sort;
+ SqlRow m_sqlRow; // current row
+ bool m_sorted; // fetch and sort done
+ SortList m_sortList;
+ unsigned m_count; // number of rows
+ unsigned m_index; // current fetch index
+ };
+ Exec_query_sort(Exec_root* root);
+ virtual ~Exec_query_sort();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setQuery(Exec_query* query);
+ void setRow(Exec_expr_row* sortRow);
+protected:
+ friend class Exec_query;
+ Exec_query* m_query;
+ Exec_expr_row* m_sortRow;
+};
+
+inline
+Exec_query_sort::Code::Code(const SqlSpecs& sqlSpecs, bool* asc) :
+ Exec_query::Code(sqlSpecs),
+ m_asc(asc)
+{
+}
+
+inline bool
+Exec_query_sort::Code::getAsc(unsigned i) const
+{
+ return m_asc[i];
+}
+
+inline
+Exec_query_sort::Data::Data(Exec_query_sort* node, const SqlSpecs& sqlSpecs) :
+ Exec_query::Data(node, m_sqlRow),
+ m_sqlRow(sqlSpecs),
+ m_sorted(false),
+ m_count(0),
+ m_index(0)
+{
+}
+
+inline
+Exec_query_sort::Exec_query_sort(Exec_root* root) :
+ Exec_query(root),
+ m_query(0),
+ m_sortRow(0)
+{
+}
+
+// children
+
+inline const Exec_query_sort::Code&
+Exec_query_sort::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query_sort::Data&
+Exec_query_sort::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_query_sort::setQuery(Exec_query* query)
+{
+ ctx_assert(m_query == 0 && query != 0);
+ m_query = query;
+}
+
+inline void
+Exec_query_sort::setRow(Exec_expr_row* sortRow)
+{
+ ctx_assert(m_sortRow == 0 && sortRow != 0);
+ m_sortRow = sortRow;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_sys.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_sys.cpp
new file mode 100644
index 00000000000..affe3dc1264
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_sys.cpp
@@ -0,0 +1,130 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NdbApi.hpp>
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_query_sys.hpp"
+#include "Code_column.hpp"
+#include "Code_root.hpp"
+
+// Plan_query_sys
+
+Plan_query_sys::~Plan_query_sys()
+{
+}
+
+Plan_base*
+Plan_query_sys::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+Exec_base*
+Plan_query_sys::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // set up
+ ctx_assert(m_table != 0);
+ const DictTable& dictTable = m_table->dictTable();
+ const ColumnVector& columns = m_table->exprColumns();
+ ctx_assert(columns.size() > 0);
+ const unsigned attrCount = columns.size() - 1;
+ // create the code
+ Exec_query_sys::Code& code = *new Exec_query_sys::Code(attrCount);
+ code.m_sysId = dictTable.sysId();
+ // queried attributes
+ code.m_attrId = new NdbAttrId[1 + attrCount];
+ code.m_attrId[0] = (NdbAttrId)-1;
+ for (unsigned i = 1; i <= attrCount; i++) {
+ Plan_column* column = columns[i];
+ ctx_assert(column != 0);
+ const DictColumn& dictColumn = column->dictColumn();
+ const SqlType& sqlType = dictColumn.sqlType();
+ SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
+ code.m_sqlSpecs.setEntry(i, sqlSpec);
+ code.m_attrId[i] = dictColumn.getAttrId();
+ }
+ // create the exec
+ Exec_query_sys* exec = new Exec_query_sys(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ exec->setCode(code);
+ return exec;
+}
+
+void
+Plan_query_sys::print(Ctx& ctx)
+{
+ ctx.print(" [query_sys");
+ Plan_base* a[] = { m_table };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
+
+// Exec_query_sys
+
+Exec_query_sys::Code::~Code()
+{
+ delete[] m_attrId;
+}
+
+Exec_query_sys::Data::~Data()
+{
+}
+
+Exec_query_sys::~Exec_query_sys()
+{
+}
+
+void
+Exec_query_sys::alloc(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ // create data
+ Data& data = *new Data(this, code.sqlSpecs());
+ setData(data);
+}
+
+void
+Exec_query_sys::close(Ctx& ctx)
+{
+ Data& data = getData();
+ data.m_rowPos = 0;
+ data.m_tablePos = 0;
+ data.m_attrPos = 0;
+ data.m_keyPos = 0;
+}
+
+void
+Exec_query_sys::print(Ctx& ctx)
+{
+ ctx.print(" [query_sys");
+ if (m_code != 0) {
+ const Code& code = getCode();
+ ctx.print(" attrId=");
+ for (unsigned i = 1; i <= code.m_attrCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_attrId[i]);
+ }
+ ctx.print(" sysId=%u", (unsigned)code.m_sysId);
+ }
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_query_sys.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_sys.hpp
new file mode 100644
index 00000000000..8eb069d0413
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_query_sys.hpp
@@ -0,0 +1,148 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_query_sys_hpp
+#define ODBC_CODEGEN_Code_query_sys_hpp
+
+#include <common/common.hpp>
+#include <dictionary/DictSys.hpp>
+#include "Code_query.hpp"
+#include "Code_table.hpp"
+
+class Ctx;
+class StmtArea;
+class NdbConnection;
+class NdbOperation;
+class NdbRecAttr;
+
+/**
+ * @class Plan_query_sys
+ * @brief Full select (no where clause)
+ */
+class Plan_query_sys : public Plan_query {
+public:
+ Plan_query_sys(Plan_root* root);
+ virtual ~Plan_query_sys();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setTable(Plan_table* table);
+protected:
+ Plan_table* m_table;
+};
+
+inline
+Plan_query_sys::Plan_query_sys(Plan_root* root) :
+ Plan_query(root),
+ m_table(0)
+{
+}
+
+// children
+
+inline void
+Plan_query_sys::setTable(Plan_table* table)
+{
+ ctx_assert(table != 0);
+ m_table = table;
+}
+
+/**
+ * @class Exec_query_sys
+ * @brief Full select (no where clause)
+ */
+class Exec_query_sys : public Exec_query {
+public:
+ class Code : public Exec_query::Code {
+ public:
+ Code(unsigned attrCount);
+ virtual ~Code();
+ protected:
+ friend class Plan_query_sys;
+ friend class Exec_query_sys;
+ DictSys::Id m_sysId;
+ unsigned m_attrCount;
+ SqlSpecs m_sqlSpecs;
+ NdbAttrId* m_attrId;
+ };
+ class Data : public Exec_query::Data {
+ public:
+ Data(Exec_query_sys* node, const SqlSpecs& sqlSpecs);
+ virtual ~Data();
+ protected:
+ friend class Exec_query_sys;
+ SqlRow m_sqlRow;
+ // for typeinfo
+ unsigned m_rowPos;
+ // for tables and columns
+ NdbDictionary::Dictionary::List m_objectList;
+ unsigned m_tablePos;
+ unsigned m_attrPos;
+ unsigned m_keyPos;
+ };
+ Exec_query_sys(Exec_root* root);
+ virtual ~Exec_query_sys();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ bool fetchImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+};
+
+inline
+Exec_query_sys::Code::Code(unsigned attrCount) :
+ Exec_query::Code(m_sqlSpecs),
+ m_sysId(DictSys::Undef),
+ m_attrCount(attrCount),
+ m_sqlSpecs(attrCount),
+ m_attrId(0)
+{
+}
+
+inline
+Exec_query_sys::Data::Data(Exec_query_sys* node, const SqlSpecs& sqlSpecs) :
+ Exec_query::Data(node, m_sqlRow),
+ m_sqlRow(sqlSpecs)
+{
+}
+
+inline
+Exec_query_sys::Exec_query_sys(Exec_root* root) :
+ Exec_query(root)
+{
+}
+
+// children
+
+inline const Exec_query_sys::Code&
+Exec_query_sys::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_query_sys::Data&
+Exec_query_sys::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_root.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_root.cpp
new file mode 100644
index 00000000000..4f45bdffdaf
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_root.cpp
@@ -0,0 +1,307 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include "Code_root.hpp"
+#include "Code_stmt.hpp"
+#include "Code_query.hpp"
+#include "Code_expr_param.hpp"
+#include "Code_root.hpp"
+
+// Plan_root
+
+Plan_root::~Plan_root()
+{
+}
+
+Plan_base*
+Plan_root::analyze(Ctx& ctx, Ctl& ctl)
+{
+ // analyze statement
+ ctx_assert(m_stmt != 0);
+ m_stmt = static_cast<Plan_stmt*>(m_stmt->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_stmt != 0);
+ // analyze parameters
+ ctx_assert(m_paramList.size() > 0);
+ const unsigned paramCount = m_paramList.size() - 1;
+ DescArea& ipd = descArea(Desc_usage_IPD);
+ ipd.setCount(ctx, paramCount);
+ for (unsigned i = 1; i <= paramCount; i++) {
+ Plan_expr_param* param = m_paramList[i];
+ ctx_assert(param != 0);
+ // analyze the parameter
+ param->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ }
+ // must return self
+ return this;
+}
+
+void
+Plan_root::describe(Ctx& ctx)
+{
+ // describe statement
+ ctx_assert(m_stmt != 0);
+ m_stmt->describe(ctx);
+ // describe parameters
+ ctx_assert(m_paramList.size() > 0);
+ const unsigned paramCount = m_paramList.size() - 1;
+ DescArea& ipd = descArea(Desc_usage_IPD);
+ ipd.setCount(ctx, paramCount);
+ unsigned unbound = 0;
+ for (unsigned i = 1; i <= paramCount; i++) {
+ Plan_expr_param* param = m_paramList[i];
+ ctx_assert(param != 0);
+ // describe the parameter
+ param->describe(ctx);
+ // check if SQL type is bound
+ ctx_assert(param->sqlType().type() != SqlType::Undef);
+ if (param->sqlType().type() == SqlType::Unbound)
+ unbound++;
+ }
+ if (unbound > 0)
+ ctx_log2(("%u out of %u params have unbound SQL type", unbound, paramCount));
+ m_stmtArea.m_unbound = unbound;
+}
+
+Exec_base*
+Plan_root::codegen(Ctx& ctx, Ctl& ctl)
+{
+ Exec_root* execRoot = new Exec_root(m_stmtArea);
+ Exec_root::Code& code = *new Exec_root::Code;
+ execRoot->setCode(code);
+ // set root in helper struct
+ ctl.m_execRoot = execRoot;
+ // generate code for the statement
+ ctx_assert(m_stmt != 0);
+ Exec_stmt* execStmt = static_cast<Exec_stmt*>(m_stmt->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ execRoot->setStmt(execStmt);
+ // create parameters list
+ execRoot->m_paramList.resize(m_paramList.size());
+ for (unsigned i = 1; i < m_paramList.size(); i++) {
+ Plan_expr_param* param = m_paramList[i];
+ ctx_assert(param != 0);
+ Exec_expr_param* execParam = static_cast<Exec_expr_param*>(param->codegen(ctx, ctl));
+ ctx_assert(execParam != 0);
+ execRoot->m_paramList[i] = execParam;
+ }
+ return execRoot;
+}
+
+void
+Plan_root::print(Ctx& ctx)
+{
+ ctx.print("[root");
+ Plan_base* a[] = { m_stmt };
+ printList(ctx, a, 1);
+ ctx.print("]\n");
+}
+
+void
+Plan_root::saveNode(Plan_base* node)
+{
+ ctx_assert(node != 0);
+ m_nodeList.push_back(node);
+}
+
+void
+Plan_root::freeNodeList()
+{
+ for (NodeList::iterator i = m_nodeList.begin(); i != m_nodeList.end(); i++) {
+ Plan_base* node = *i;
+ *i = 0;
+ delete node;
+ }
+ m_nodeList.clear();
+}
+
+// Exec_root
+
+Exec_root::Code::~Code()
+{
+}
+
+Exec_root::Data::~Data()
+{
+}
+
+Exec_root::~Exec_root()
+{
+}
+
+StmtArea&
+Exec_root::stmtArea() const
+{
+ return m_stmtArea;
+}
+
+void
+Exec_root::alloc(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_stmt != 0);
+ m_stmt->alloc(ctx, ctl);
+}
+
+void
+Exec_root::bind(Ctx& ctx)
+{
+ // bind output cols
+ ctx_assert(m_stmt != 0);
+ m_stmt->bind(ctx);
+ // bind input params
+ for (unsigned i = 1; i < m_paramList.size(); i++) {
+ Exec_expr_param* param = m_paramList[i];
+ ctx_assert(param != 0);
+ param->bind(ctx);
+ if (! ctx.ok())
+ return;
+ }
+}
+
+void
+Exec_root::execute(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_stmt != 0);
+ // check if data is needed
+ for (unsigned i = 1; i < m_paramList.size(); i++) {
+ Exec_expr_param* param = m_paramList[i];
+ ctx_assert(param != 0);
+ Exec_expr_param::Data& paramData = param->getData();
+ if (paramData.m_atExec && paramData.m_extPos == -1) {
+ ctx.setCode(SQL_NEED_DATA);
+ return;
+ }
+ }
+ m_stmt->execute(ctx, ctl);
+}
+
+void
+Exec_root::fetch(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(m_stmt != 0);
+ Exec_query* query = static_cast<Exec_query*>(m_stmt);
+ ctx_assert(query != 0);
+ query->fetch(ctx, ctl);
+}
+
+void
+Exec_root::close(Ctx& ctx)
+{
+ ctx_assert(m_stmt != 0);
+ m_stmt->close(ctx);
+ for (unsigned i = 1; i < m_paramList.size(); i++) {
+ Exec_expr_param* param = m_paramList[i];
+ ctx_assert(param != 0);
+ param->close(ctx);
+ }
+}
+
+void
+Exec_root::print(Ctx& ctx)
+{
+ ctx.print("[root");
+ Exec_base* a[] = { m_stmt };
+ printList(ctx, a, sizeof(a)/sizeof(a[0]));
+ ctx.print("]\n");
+}
+
+void
+Exec_root::saveNode(Exec_base* node)
+{
+ ctx_assert(node != 0);
+ m_nodeList.push_back(node);
+}
+
+void
+Exec_root::freeNodeList()
+{
+ for (NodeList::iterator i = m_nodeList.begin(); i != m_nodeList.end(); i++) {
+ Exec_base* node = *i;
+ *i = 0;
+ delete node;
+ }
+ m_nodeList.clear();
+}
+
+// odbc support
+
+void
+Exec_root::sqlGetData(Ctx& ctx, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValue, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_Ind)
+{
+ ctx_assert(m_stmt != 0);
+ Exec_query* query = static_cast<Exec_query*>(m_stmt);
+ ctx_assert(query != 0);
+ query->sqlGetData(ctx, columnNumber, targetType, targetValue, bufferLength, strlen_or_Ind);
+}
+
+void
+Exec_root::sqlParamData(Ctx& ctx, SQLPOINTER* value)
+{
+ ctx_assert(m_paramList.size() > 0);
+ unsigned count = m_paramList.size() - 1;
+ for (unsigned i = 1; i <= count; i++) {
+ Exec_expr_param* param = m_paramList[i];
+ ctx_assert(param != 0);
+ Exec_expr_param::Data& paramData = param->getData();
+ if (! paramData.m_atExec || paramData.m_extPos >= 0)
+ continue;
+ ctx_assert(paramData.m_extField != 0);
+ ExtField& extField = *paramData.m_extField;
+ if (value != 0)
+ *value = extField.m_dataPtr;
+ m_paramData = i;
+ ctx.setCode(SQL_NEED_DATA);
+ return;
+ }
+}
+
+void
+Exec_root::sqlPutData(Ctx& ctx, SQLPOINTER data, SQLINTEGER strlen_or_Ind)
+{
+ ctx_assert(m_paramList.size() > 0);
+ unsigned count = m_paramList.size() - 1;
+ unsigned i = m_paramData;
+ if (i == 0) {
+ ctx.pushStatus(Sqlstate::_HY010, Error::Gen, "missing call to SQLParamData");
+ return;
+ }
+ if (i > count) {
+ ctx.pushStatus(Sqlstate::_HY010, Error::Gen, "parameter %u out of range 1 to %u", i, count);
+ return;
+ }
+ Exec_expr_param* param = m_paramList[i];
+ ctx_assert(param != 0);
+ Exec_expr_param::Data& paramData = param->getData();
+ if (! paramData.m_atExec) {
+ ctx.pushStatus(Sqlstate::_HY010, Error::Gen, "parameter %u not marked for data-at-exec", i);
+ return;
+ }
+ ctx_assert(paramData.m_extField != 0);
+ ExtField extField(paramData.m_extField->extSpec(), data, 0, &strlen_or_Ind, i);
+ if (paramData.m_extPos == -1)
+ paramData.m_extPos = 0;
+ extField.setPos(paramData.m_extPos);
+ // copy in and update position
+ SqlField& sqlField = paramData.m_sqlField;
+ sqlField.copyin(ctx, extField);
+ paramData.m_extPos = extField.getPos();
+ ctx_log4(("parameter %u data received", i));
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_root.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_root.hpp
new file mode 100644
index 00000000000..4f0f96725e3
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_root.hpp
@@ -0,0 +1,162 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_root_hpp
+#define ODBC_CODEGEN_Code_root_hpp
+
+#include <list>
+#include <common/common.hpp>
+#include "Code_base.hpp"
+#include "Code_stmt.hpp"
+
+class SqlField;
+class ExtField;
+
+/**
+ * @class Plan_root
+ * @brief Root node above top level statement node
+ */
+class Plan_root : public Plan_base {
+public:
+ Plan_root(StmtArea& stmtArea);
+ virtual ~Plan_root();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx& ctx);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setStmt(Plan_stmt* stmt);
+ // save and free nodes
+ void saveNode(Plan_base* node);
+ void freeNodeList();
+private:
+ friend class CodeGen;
+ friend class Plan_base;
+ friend class Plan_expr_param;
+ StmtArea& m_stmtArea;
+ Plan_stmt* m_stmt;
+ ParamVector m_paramList;
+ typedef std::list<Plan_base*> NodeList;
+ NodeList m_nodeList;
+};
+
+inline
+Plan_root::Plan_root(StmtArea& stmtArea) :
+ Plan_base(this),
+ m_stmtArea(stmtArea),
+ m_stmt(0)
+{
+}
+
+inline void
+Plan_root::setStmt(Plan_stmt* stmt)
+{
+ ctx_assert(stmt != 0);
+ m_stmt = stmt;
+}
+
+/**
+ * @class Exec_root
+ * @brief Root node above top level statement node
+ */
+class Exec_root : public Exec_base {
+public:
+ class Code : public Exec_base::Code {
+ public:
+ Code();
+ virtual ~Code();
+ };
+ class Data : public Exec_base::Data {
+ public:
+ Data();
+ virtual ~Data();
+ };
+ Exec_root(StmtArea& stmtArea);
+ virtual ~Exec_root();
+ StmtArea& stmtArea() const;
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void bind(Ctx& ctx);
+ void execute(Ctx& ctx, Ctl& ctl);
+ void fetch(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setStmt(Exec_stmt* stmt);
+ // save and free nodes
+ void saveNode(Exec_base* node);
+ void freeNodeList();
+ // odbc support
+ void sqlGetData(Ctx& ctx, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValue, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_Ind);
+ void sqlParamData(Ctx& ctx, SQLPOINTER* value);
+ void sqlPutData(Ctx& ctx, SQLPOINTER data, SQLINTEGER strlen_or_Ind);
+private:
+ friend class Plan_root;
+ friend class Exec_base;
+ friend class CodeGen;
+ StmtArea& m_stmtArea;
+ Exec_stmt* m_stmt;
+ ParamVector m_paramList;
+ unsigned m_paramData; // position of SQLParamData
+ typedef std::list<Exec_base*> NodeList;
+ NodeList m_nodeList;
+};
+
+inline
+Exec_root::Code::Code()
+{
+}
+
+inline
+Exec_root::Data::Data()
+{
+}
+
+inline
+Exec_root::Exec_root(StmtArea& stmtArea) :
+ Exec_base(this),
+ m_stmtArea(stmtArea),
+ m_stmt(0),
+ m_paramData(0)
+{
+}
+
+// children
+
+inline const Exec_root::Code&
+Exec_root::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_root::Data&
+Exec_root::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_root::setStmt(Exec_stmt* stmt)
+{
+ ctx_assert(stmt != 0);
+ m_stmt = stmt;
+ m_stmt->m_topLevel = true;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_select.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_select.cpp
new file mode 100644
index 00000000000..611b491968d
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_select.cpp
@@ -0,0 +1,406 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <algorithm>
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include "Code_select.hpp"
+#include "Code_query_lookup.hpp"
+#include "Code_query_index.hpp"
+#include "Code_query_scan.hpp"
+#include "Code_query_range.hpp"
+#include "Code_query_sys.hpp"
+#include "Code_query_project.hpp"
+#include "Code_query_filter.hpp"
+#include "Code_query_join.hpp"
+#include "Code_query_count.hpp"
+#include "Code_query_sort.hpp"
+#include "Code_query_group.hpp"
+#include "Code_query_distinct.hpp"
+#include "Code_expr_column.hpp"
+#include "Code_expr_const.hpp"
+#include "Code_pred_op.hpp"
+#include "Code_root.hpp"
+
+Plan_select::~Plan_select()
+{
+}
+
+Plan_base*
+Plan_select::analyze(Ctx& ctx, Ctl& ctl)
+{
+ stmtArea().stmtInfo().setName(Stmt_name_select);
+ // analyze tables
+ ctx_assert(m_tableList != 0);
+ for (unsigned i = 1; i <= m_tableList->countTable(); i++) {
+ Plan_table* table = m_tableList->getTable(i);
+ table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ }
+ ctx_assert(m_exprRow != 0);
+ if (m_exprRow->getAsterisk()) {
+ // expand unqualified asterisk to table-qualified columns
+ setRow(new Plan_expr_row(m_root));
+ m_root->saveNode(m_exprRow);
+ for (unsigned i = 1; i <= m_tableList->countTable(); i++) {
+ const Plan_table* table = m_tableList->getTable(i);
+ const DictTable& dictTable = table->dictTable();
+ for (unsigned i = 1; i <= dictTable.getSize(); i++) {
+ DictColumn* dictColumn = dictTable.getColumn(i);
+ Plan_expr_column* column = new Plan_expr_column(m_root, dictColumn->getName());
+ m_root->saveNode(column);
+ column->setCname(table->getCname());
+ m_exprRow->addExpr(column);
+ }
+ }
+ }
+ // set name resolution scope
+ ctl.m_tableList = m_tableList->m_tableList;
+ ctx_assert(ctl.m_tableList.size() >= 1 + 1);
+ ctl.m_aggrin = false;
+ // analyze select row
+ ctl.m_aggrok = true;
+ ctx_assert(m_exprRow != 0);
+ m_exprRow = static_cast<Plan_expr_row*>(m_exprRow->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_exprRow != 0);
+ // analyze group by row
+ ctl.m_aggrok = false;
+ if (m_groupRow != 0) {
+ m_groupRow = static_cast<Plan_expr_row*>(m_groupRow->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_groupRow != 0);
+ }
+ // analyze having predicate
+ ctl.m_aggrok = true;
+ if (m_havingPred != 0) {
+ m_havingPred = static_cast<Plan_pred*>(m_havingPred->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_havingPred != 0);
+ }
+ // ana|yze order by row
+ ctl.m_aggrok = true;
+ if (m_sortRow != 0) {
+ m_sortRow = static_cast<Plan_expr_row*>(m_sortRow->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_sortRow != 0);
+ }
+ // analyze the predicate
+ ctl.m_aggrok = false;
+ ctl.m_topand = true;
+ ctl.m_extra = false;
+ if (m_pred != 0) {
+ m_pred = static_cast<Plan_pred*>(m_pred->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_pred != 0);
+ }
+ // check if group by required
+ if (m_exprRow->anyAggr() && ! m_exprRow->allBound() && m_groupRow == 0) {
+ ctx.pushStatus(Error::Gen, "missing GROUP BY clause");
+ return 0;
+ }
+ // in special cases add "group by 1"
+ if (m_groupRow == 0) {
+ bool addgb = false;
+ if (m_havingPred != 0) {
+ // allowed by oracle but nearly useless
+ addgb = true;
+ } else if (m_exprRow->anyAggr() && m_sortRow != 0) {
+ // allowed by oracle but useless
+ ctx_assert(m_exprRow->allBound());
+ addgb = true;
+ }
+ if (addgb) {
+ ctx_log2(("adding 'group by 1'"));
+ m_groupRow = new Plan_expr_row(m_root);
+ m_root->saveNode(m_groupRow);
+ LexType type(LexType::Integer);
+ Plan_expr* expr = new Plan_expr_const(m_root, type, "1");
+ m_root->saveNode(expr);
+ m_groupRow->addExpr(expr);
+ m_groupRow = static_cast<Plan_expr_row*>(m_groupRow->analyze(ctx, ctl));
+ ctx_assert(ctx.ok());
+ ctx_assert(m_groupRow != 0);
+ }
+ }
+ // check group by allowed
+ if (m_groupRow != 0) {
+ if (! m_exprRow->isAllGroupBy(m_groupRow)) {
+ ctx.pushStatus(Error::Gen, "invalid GROUP BY expression in SELECT list");
+ return 0;
+ }
+ if (m_havingPred != 0) {
+ if (! m_havingPred->isGroupBy(m_groupRow)) {
+ ctx.pushStatus(Error::Gen, "invalid GROUP BY expression in HAVING clause");
+ return 0;
+ }
+ }
+ if (m_sortRow != 0) {
+ if (! m_sortRow->isAllGroupBy(m_groupRow)) {
+ ctx.pushStatus(Error::Gen, "invalid GROUP BY expression in ORDER BY clause");
+ return 0;
+ }
+ }
+ }
+ // log top level predicate
+ {
+ unsigned n = 0;
+ for (PredList::iterator i = ctl.m_topcomp.begin(); i != ctl.m_topcomp.end(); i++)
+ ctx_log2(("top level pred %u: count tables = %u, not interp = %u",
+ ++n,
+ (unsigned)(*i)->tableSet().size(),
+ (unsigned)(*i)->noInterp().size()));
+ }
+ // compose the raw query from lookups and scans
+ Plan_query* queryRaw = 0;
+ TableVector tableVector(1);
+ TableSet tsDone;
+ while (tableVector.size() < ctl.m_tableList.size()) {
+ Plan_table* tableBest = 0;
+ Plan_table::Index* indexBest = 0;
+ for (unsigned n = 1; n < ctl.m_tableList.size(); n++) {
+ Plan_table* table = ctl.m_tableList[n];
+ if (tsDone.find(table) != tsDone.end())
+ continue;
+ // get system table out of the way
+ if (table->dictTable().sysId()) {
+ tableBest = table;
+ break;
+ }
+ // find best match for primary key or index
+ for (unsigned i = 0; i <= table->indexCount(); i++) {
+ Plan_table::Index& index = table->m_indexList[i];
+ table->resolveSet(ctx, index, tsDone);
+ if (! ctx.ok())
+ return 0;
+ if (! index.m_keyFound)
+ continue;
+ // prefer smaller dependency set, smaller rank, less unused keys
+ int k;
+ (k = (indexBest == 0)) ||
+ (k = (indexBest->m_keySet.size() - index.m_keySet.size())) ||
+ (k = (indexBest->m_rank - index.m_rank)) ||
+ (k = (indexBest->m_keyCountUnused - index.m_keyCountUnused));
+ if (k > 0) {
+ tableBest = table;
+ indexBest = &index;
+ }
+ }
+ }
+ Plan_query* queryNext = 0;
+ Plan_table* tableNext = 0;
+ Plan_query_scan* queryScan = 0; // for pushing interpreted program
+ Plan_query_range* queryRange = 0; // ditto
+ if (tableBest == 0) {
+ // scan first unprocessed table
+ for (unsigned n = 1; n < ctl.m_tableList.size(); n++) {
+ Plan_table* table = ctl.m_tableList[n];
+ if (tsDone.find(table) != tsDone.end())
+ continue;
+ tableNext = table;
+ break;
+ }
+ ctx_assert(tableNext != 0);
+ queryScan = new Plan_query_scan(m_root);
+ m_root->saveNode(queryScan);
+ queryScan->setTable(tableNext);
+ queryNext = queryScan;
+ ctx_log2(("optim: scan %s", tableNext->getPrintName()));
+ } else if (tableBest->dictTable().sysId()) {
+ // "scan" system table
+ tableNext = tableBest;
+ Plan_query_sys* querySys = new Plan_query_sys(m_root);
+ m_root->saveNode(querySys);
+ querySys->setTable(tableNext);
+ queryNext = querySys;
+ ctx_log2(("optim: scan %s", tableNext->getPrintName()));
+ } else if (indexBest->m_keySet.size() > 0) {
+ // scan first table this one depends on
+ const TableSet& keySet = indexBest->m_keySet;
+ for (unsigned n = 1; n < ctl.m_tableList.size(); n++) {
+ Plan_table* table = ctl.m_tableList[n];
+ if (keySet.find(table) == keySet.end())
+ continue;
+ ctx_assert(tsDone.find(table) == tsDone.end());
+ tableNext = table;
+ break;
+ }
+ ctx_assert(tableNext != 0);
+ queryScan = new Plan_query_scan(m_root);
+ m_root->saveNode(queryScan);
+ queryScan->setTable(tableNext);
+ queryNext = queryScan;
+ ctx_log2(("optim: scan %s for %s", tableNext->getPrintName(), tableBest->getPrintName()));
+ } else if (indexBest->m_rank == 0) {
+ // primary key depends only on processed tables
+ tableNext = tableBest;
+ Plan_query_lookup* queryLookup = new Plan_query_lookup(m_root);
+ m_root->saveNode(queryLookup);
+ queryLookup->setTable(tableNext);
+ queryNext = queryLookup;
+ ctx_log2(("optim: lookup %s", tableNext->getPrintName()));
+ } else if (indexBest->m_rank == 1) {
+ // hash index key depends only on processed tables
+ tableNext = tableBest;
+ Plan_query_index* queryIndex = new Plan_query_index(m_root);
+ m_root->saveNode(queryIndex);
+ queryIndex->setTable(tableNext, indexBest);
+ queryNext = queryIndex;
+ ctx_log2(("optim: lookup %s via index %s", tableNext->getPrintName(), indexBest->m_dictIndex->getName().c_str()));
+ } else if (indexBest->m_rank == 2) {
+ // ordered index key depends only on processed tables
+ tableNext = tableBest;
+ queryRange = new Plan_query_range(m_root);
+ m_root->saveNode(queryRange);
+ queryRange->setTable(tableNext, indexBest);
+ queryNext = queryRange;
+ ctx_log2(("optim: range scan %s via index %s", tableNext->getPrintName(), indexBest->m_dictIndex->getName().c_str()));
+ } else {
+ ctx_assert(false);
+ }
+ if (queryRaw == 0) {
+ queryRaw = queryNext;
+ } else {
+ Plan_query_join* queryJoin = new Plan_query_join(m_root);
+ m_root->saveNode(queryJoin);
+ queryJoin->setInner(queryRaw);
+ queryJoin->setOuter(queryNext);
+ queryRaw = queryJoin;
+ }
+ tableVector.push_back(tableNext);
+ tsDone.insert(tableNext);
+ // push down part of top level predicate to table scan or range scan
+ Plan_pred* predPush = 0;
+ Plan_pred* predInterp = 0;
+ PredList::iterator i = ctl.m_topcomp.begin();
+ while (i != ctl.m_topcomp.end()) {
+ const TableSet& ts = (*i)->tableSet();
+ if (! std::includes(tsDone.begin(), tsDone.end(), ts.begin(), ts.end())) {
+ i++;
+ continue;
+ }
+ predPush = predPush == 0 ? *i : predPush->opAnd(*i);
+ if (queryScan != 0) {
+ const TableSet& ts2 = (*i)->noInterp();
+ if (ts2.find(tableNext) == ts2.end())
+ predInterp = predInterp == 0 ? *i : predInterp->opAnd(*i);
+ }
+ if (queryRange != 0) {
+ const TableSet& ts2 = (*i)->noInterp();
+ if (ts2.find(tableNext) == ts2.end())
+ predInterp = predInterp == 0 ? *i : predInterp->opAnd(*i);
+ }
+ // remove it from top level predicate
+ PredList::iterator j = i;
+ i++;
+ ctl.m_topcomp.erase(j);
+ }
+ if (predPush != 0) {
+ Plan_query_filter* queryPush = new Plan_query_filter(m_root);
+ m_root->saveNode(queryPush);
+ queryPush->setQuery(queryRaw);
+ queryPush->setPred(predPush);
+ queryPush->m_topTable = tableNext;
+ queryRaw = queryPush;
+ }
+ if (predInterp != 0) {
+ if (queryScan != 0)
+ queryScan->setInterp(predInterp);
+ else if (queryRange != 0)
+ queryRange->setInterp(predInterp);
+ else
+ ctx_assert(false);
+ }
+ }
+ ctx_assert(ctl.m_topcomp.empty());
+ // set base for column position offsets
+ for (unsigned n = 1; n < tableVector.size(); n++) {
+ Plan_table* table = tableVector[n];
+ if (n == 1) {
+ table->m_resOff = 1;
+ } else {
+ Plan_table* tablePrev = tableVector[n - 1];
+ table->m_resOff = tablePrev->m_resOff + tablePrev->m_exprColumns.size() - 1;
+ }
+ }
+ // next level up is one of project, count, group by
+ Plan_query* queryTop;
+ if (m_groupRow == 0) {
+ if (! m_exprRow->anyAggr()) {
+ Plan_query_project* queryProject = new Plan_query_project(m_root);
+ m_root->saveNode(queryProject);
+ queryProject->setQuery(queryRaw);
+ queryProject->setRow(m_exprRow);
+ queryProject->setLimit(m_limitOff, m_limitCnt);
+ queryTop = queryProject;
+ } else {
+ ctx_assert(m_exprRow->allBound());
+ Plan_query_count* queryCount = new Plan_query_count(m_root);
+ m_root->saveNode(queryCount);
+ queryCount->setQuery(queryRaw);
+ queryCount->setRow(m_exprRow);
+ queryTop = queryCount;
+ }
+ } else {
+ Plan_query_group* queryGroup = new Plan_query_group(m_root);
+ m_root->saveNode(queryGroup);
+ queryGroup->setQuery(queryRaw);
+ queryGroup->setDataRow(m_exprRow);
+ queryGroup->setGroupRow(m_groupRow);
+ if (m_havingPred != 0)
+ queryGroup->setHavingPred(m_havingPred);
+ queryTop = queryGroup;
+ }
+ // optional sort becomes new top level
+ if (m_sortRow != 0) {
+ Plan_query_sort* querySort = new Plan_query_sort(m_root);
+ m_root->saveNode(querySort);
+ querySort->setQuery(queryTop);
+ querySort->setRow(m_sortRow);
+ queryTop = querySort;
+ }
+ // optional distinct becomes new top level
+ if (m_distinct) {
+ Plan_query_distinct* queryDistinct = new Plan_query_distinct(m_root);
+ m_root->saveNode(queryDistinct);
+ queryDistinct->setQuery(queryTop);
+ queryTop = queryDistinct;
+ }
+ // return top node
+ return queryTop;
+}
+
+Exec_base*
+Plan_select::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_select::print(Ctx& ctx)
+{
+ ctx.print(" [select");
+ Plan_base* a[] = { m_tableList, m_exprRow, m_pred, m_groupRow, m_havingPred };
+ printList(ctx, a, 5);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_select.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_select.hpp
new file mode 100644
index 00000000000..eaa9b801f29
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_select.hpp
@@ -0,0 +1,132 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_select_hpp
+#define ODBC_CODEGEN_Code_select_hpp
+
+#include <common/common.hpp>
+#include "Code_stmt.hpp"
+#include "Code_expr_row.hpp"
+#include "Code_table_list.hpp"
+#include "Code_pred.hpp"
+
+/**
+ * @class Plan_select
+ * @brief General select in PlanTree
+ *
+ * General select. An initial PlanTree node.
+ */
+class Plan_select : public Plan_stmt {
+public:
+ Plan_select(Plan_root* root);
+ virtual ~Plan_select();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setList(Plan_table_list* tableList);
+ void setRow(Plan_expr_row* exprRow);
+ void setPred(Plan_pred* pred);
+ void setSort(Plan_expr_row* sortRow);
+ void setDistinct(bool distinct);
+ void setGroup(Plan_expr_row* groupRow);
+ void setHaving(Plan_pred* havingPred);
+ void setLimit(int off, int cnt);
+protected:
+ Plan_table_list* m_tableList;
+ Plan_expr_row* m_exprRow;
+ Plan_pred* m_pred;
+ Plan_expr_row* m_sortRow;
+ bool m_distinct;
+ Plan_expr_row* m_groupRow;
+ Plan_pred* m_havingPred;
+ int m_limitOff;
+ int m_limitCnt;
+};
+
+inline
+Plan_select::Plan_select(Plan_root* root) :
+ Plan_stmt(root),
+ m_tableList(0),
+ m_exprRow(0),
+ m_pred(0),
+ m_sortRow(0),
+ m_distinct(false),
+ m_groupRow(0),
+ m_havingPred(0),
+ m_limitOff(0),
+ m_limitCnt(-1)
+{
+}
+
+// children
+
+inline void
+Plan_select::setList(Plan_table_list* tableList)
+{
+ ctx_assert(tableList != 0);
+ m_tableList = tableList;
+}
+
+inline void
+Plan_select::setRow(Plan_expr_row* exprRow)
+{
+ ctx_assert(exprRow != 0);
+ m_exprRow = exprRow;
+}
+
+inline void
+Plan_select::setPred(Plan_pred* pred)
+{
+ ctx_assert(pred != 0);
+ m_pred = pred;
+}
+
+inline void
+Plan_select::setSort(Plan_expr_row* sortRow)
+{
+ ctx_assert(sortRow != 0);
+ m_sortRow = sortRow;
+}
+
+inline void
+Plan_select::setDistinct(bool distinct)
+{
+ m_distinct = distinct;
+}
+
+inline void
+Plan_select::setGroup(Plan_expr_row* groupRow)
+{
+ ctx_assert(groupRow != 0);
+ m_groupRow = groupRow;
+}
+
+inline void
+Plan_select::setHaving(Plan_pred* havingPred)
+{
+ ctx_assert(havingPred != 0);
+ m_havingPred = havingPred;
+}
+
+inline void
+Plan_select::setLimit(int off, int cnt)
+{
+ m_limitOff = off;
+ m_limitCnt = cnt;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_set_row.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_set_row.cpp
new file mode 100644
index 00000000000..dd13ba0c3f7
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_set_row.cpp
@@ -0,0 +1,44 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_set_row.hpp"
+#include "Code_dml_column.hpp"
+
+Plan_set_row::~Plan_set_row()
+{
+}
+
+Plan_base*
+Plan_set_row::analyze(Ctx& ctx, Ctl& ctl)
+{
+ return this;
+}
+
+Exec_base*
+Plan_set_row::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_set_row::print(Ctx& ctx)
+{
+ ctx.print(" [set_row");
+ Plan_base* a[] = { m_dmlRow, m_exprRow };
+ printList(ctx, a, 2);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_set_row.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_set_row.hpp
new file mode 100644
index 00000000000..10d62826ac7
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_set_row.hpp
@@ -0,0 +1,76 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_set_row_hpp
+#define ODBC_CODEGEN_Code_set_row_hpp
+
+#include <vector>
+#include <common/common.hpp>
+#include <common/DataRow.hpp>
+#include "Code_base.hpp"
+#include "Code_dml_row.hpp"
+#include "Code_expr_row.hpp"
+#include "Code_root.hpp"
+
+/**
+ * @class Plan_set_row
+ * @brief Row of column assigments in update
+ *
+ * Used only in parse. The column and expression rows are moved
+ * to the update node immediately after parse.
+ */
+class Plan_set_row : public Plan_base {
+public:
+ Plan_set_row(Plan_root* root);
+ virtual ~Plan_set_row();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void addColumn(Plan_dml_column* column);
+ void addExpr(Plan_expr* expr);
+protected:
+ friend class Plan_update;
+ friend class Plan_insert; // for MySql
+ Plan_dml_row* m_dmlRow;
+ Plan_expr_row* m_exprRow;
+};
+
+inline
+Plan_set_row::Plan_set_row(Plan_root* root) :
+ Plan_base(root)
+{
+ m_dmlRow = new Plan_dml_row(root);
+ root->saveNode(m_dmlRow);
+ m_exprRow = new Plan_expr_row(root);
+ root->saveNode(m_exprRow);
+}
+
+// children
+
+inline void
+Plan_set_row::addColumn(Plan_dml_column* column)
+{
+ m_dmlRow->addColumn(column);
+}
+
+inline void
+Plan_set_row::addExpr(Plan_expr* expr)
+{
+ m_exprRow->addExpr(expr);
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_stmt.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_stmt.cpp
new file mode 100644
index 00000000000..d790f667b84
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_stmt.cpp
@@ -0,0 +1,49 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_stmt.hpp"
+
+// Plan_stmt
+
+Plan_stmt::~Plan_stmt()
+{
+}
+
+// XXX remove
+void
+Plan_stmt::describe(Ctx& ctx)
+{
+ ctx_log1(("unimplemented describe"));
+}
+
+// Exec_stmt
+
+Exec_stmt::Code::~Code()
+{
+}
+
+Exec_stmt::Data::~Data()
+{
+}
+
+Exec_stmt::~Exec_stmt()
+{
+}
+
+void
+Exec_stmt::bind(Ctx& ctx)
+{
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_stmt.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_stmt.hpp
new file mode 100644
index 00000000000..20b7fb965fb
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_stmt.hpp
@@ -0,0 +1,76 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_stmt_hpp
+#define ODBC_CODEGEN_Code_stmt_hpp
+
+#include <common/common.hpp>
+#include <common/DataType.hpp>
+#include "Code_base.hpp"
+
+class Ctx;
+
+/**
+ * @class Plan_stmt
+ * @brief Base class for statements in PlanTree
+ *
+ * A statement is a complete or partial SQL statement which can
+ * be optimized into executable statements Exec_stmt.
+ */
+class Plan_stmt : public Plan_base {
+public:
+ Plan_stmt(Plan_root* root);
+ virtual ~Plan_stmt() = 0;
+ virtual void describe(Ctx& ctx);
+};
+
+inline
+Plan_stmt::Plan_stmt(Plan_root* root) :
+ Plan_base(root)
+{
+}
+
+/**
+ * @class Exec_stmt
+ * @brief Base class for statements in ExecTree
+ */
+class Exec_stmt : public Exec_base {
+public:
+ class Code : public Exec_base::Code {
+ public:
+ virtual ~Code() = 0;
+ };
+ class Data : public Exec_base::Data {
+ public:
+ virtual ~Data() = 0;
+ };
+ Exec_stmt(Exec_root* root);
+ virtual ~Exec_stmt() = 0;
+ virtual void bind(Ctx& ctx);
+ virtual void execute(Ctx& ctx, Ctl& ctl) = 0;
+protected:
+ friend class Exec_root;
+ bool m_topLevel;
+};
+
+inline
+Exec_stmt::Exec_stmt(Exec_root* root) :
+ Exec_base(root),
+ m_topLevel(false)
+{
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_table.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_table.cpp
new file mode 100644
index 00000000000..ee3c2a2ed07
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_table.cpp
@@ -0,0 +1,254 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NdbApi.hpp>
+#include <common/StmtArea.hpp>
+#include <dictionary/DictSchema.hpp>
+#include <dictionary/DictTable.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_table.hpp"
+#include "Code_column.hpp"
+#include "Code_expr_column.hpp"
+
+Plan_table::~Plan_table()
+{
+}
+
+Plan_base*
+Plan_table::analyze(Ctx& ctx, Ctl& ctl)
+{
+ if (m_dictTable != 0) // already done
+ return this;
+ DictTable* table = dictSchema().findTable(m_name);
+ if (table == 0) {
+ table = dictSchema().loadTable(ctx, m_name);
+ if (table == 0) {
+ ctx.pushStatus(Sqlstate::_42S02, Error::Gen, "table %s not found", m_name.c_str());
+ return 0;
+ }
+ }
+ m_dictTable = table;
+ // indexes
+ m_indexList.resize(1 + m_dictTable->indexCount());
+ for (unsigned i = 0; i <= indexCount(); i++) {
+ Index& index = m_indexList[i];
+ index.m_pos = i;
+ if (index.m_pos == 0) {
+ index.m_keyCount = m_dictTable->keyCount();
+ index.m_rank = 0;
+ } else {
+ index.m_dictIndex = m_dictTable->getIndex(i);
+ index.m_keyCount = index.m_dictIndex->getSize();
+ if (index.m_dictIndex->getType() == NdbDictionary::Object::UniqueHashIndex) {
+ index.m_rank = 1;
+ } else if (index.m_dictIndex->getType() == NdbDictionary::Object::OrderedIndex) {
+ index.m_rank = 2;
+ } else {
+ ctx_assert(false);
+ }
+ }
+ index.m_keyEqList.resize(1 + index.m_keyCount);
+ }
+ return this;
+}
+
+int
+Plan_table::resolveColumn(Ctx& ctx, Plan_column* column, bool stripSchemaName)
+{
+ ctx_assert(column != 0);
+ bool dml, unq;
+ switch (column->m_type) {
+ case Plan_column::Type_expr:
+ dml = false;
+ unq = false;
+ break;
+ case Plan_column::Type_dml:
+ dml = true;
+ unq = true;
+ break;
+ case Plan_column::Type_idx:
+ dml = false;
+ unq = true;
+ break;
+ default:
+ ctx_assert(false);
+ break;
+ }
+ ColumnVector& columns = ! dml ? m_exprColumns : m_dmlColumns;
+ const BaseString& name = column->m_name;
+ const BaseString& cname = column->m_cname;
+ ctx_log3(("resolve %s column %s in table %s", ! dml ? "expr" : "dml", column->getPrintName(), getPrintName()));
+ // find column in table
+ DictColumn* dictColumn = dictTable().findColumn(name);
+ if (dictColumn == 0)
+ return 0;
+ // qualified column must match table correlation name
+ if (! cname.empty()) {
+ const char* str;
+ if (! m_cname.empty()) {
+ str = m_cname.c_str();
+ } else {
+ str = m_name.c_str();
+ if (stripSchemaName && strrchr(str, '.') != 0)
+ str = strrchr(str, '.') + 1;
+ }
+ if (strcmp(cname.c_str(), str) != 0)
+ return 0;
+ }
+ // find in positional list or add to it
+ unsigned resPos;
+ for (resPos = 1; resPos < columns.size(); resPos++) {
+ if (strcmp(columns[resPos]->getName().c_str(), name.c_str()) != 0)
+ continue;
+ // these columns must be unique
+ if (unq) {
+ ctx.pushStatus(Error::Gen, "duplicate column %s", column->getName().c_str());
+ return -1;
+ }
+ break;
+ }
+ if (resPos >= columns.size()) {
+ columns.push_back(column);
+ }
+ ctx_log3(("resolve to attrId %u pos %u", (unsigned)dictColumn->getAttrId(), resPos));
+ column->m_dictColumn = dictColumn;
+ column->m_resTable = this;
+ column->m_resPos = resPos;
+ // found
+ return 1;
+}
+
+bool
+Plan_table::resolveEq(Ctx& ctx, Plan_expr_column* column, Plan_expr* expr)
+{
+ ctx_assert(m_dictTable != 0);
+ const TableSet& ts = expr->tableSet();
+ TableSet::const_iterator i = ts.find(this);
+ if (i != ts.end())
+ return false;
+ unsigned found = 0;
+ for (unsigned i = 0; i <= indexCount(); i++) {
+ Index& index = m_indexList[i];
+ for (unsigned n = 1, cnt = 0; n <= index.m_keyCount; n++) {
+ const DictColumn* dictColumn = 0;
+ if (index.m_pos == 0) {
+ ctx_assert(m_dictTable != 0);
+ dictColumn = m_dictTable->getKey(n);
+ } else {
+ ctx_assert(index.m_dictIndex != 0);
+ dictColumn = index.m_dictIndex->getColumn(n);
+ }
+ if (dictColumn != &column->dictColumn())
+ continue;
+ ctx_assert(++cnt == 1);
+ index.m_keyEqList[n].push_back(expr);
+ if (index.m_pos == 0)
+ ctx_log2(("%s: found match to primary key column %s pos %u", getPrintName(), column->getPrintName(), n));
+ else
+ ctx_log2(("%s: found match to index %s column %s pos %u", getPrintName(), index.m_dictIndex->getName().c_str(), column->getPrintName(), n));
+ found++;
+ }
+ }
+ return (found != 0);
+}
+
+void
+Plan_table::resolveSet(Ctx& ctx, Index& index, const TableSet& tsDone)
+{
+ index.m_keyFound = false;
+ ExprVector keyEq;
+ keyEq.resize(1 + index.m_keyCount);
+ resolveSet(ctx, index, tsDone, keyEq, 1);
+}
+
+void
+Plan_table::resolveSet(Ctx& ctx, Index& index, const TableSet& tsDone, ExprVector& keyEq, unsigned n)
+{
+ if (n <= index.m_keyCount) {
+ // building up combinations
+ ExprList& keyEqList = index.m_keyEqList[n];
+ for (ExprList::iterator i = keyEqList.begin(); i != keyEqList.end(); i++) {
+ keyEq[n] = *i;
+ resolveSet(ctx, index, tsDone, keyEq, n + 1);
+ }
+ if (! keyEqList.empty() || index.m_rank <= 1 || n == 1)
+ return;
+ // ordered index with maximal initial key match
+ }
+ TableSet keySet;
+ for (unsigned i = 1; i <= n - 1; i++) {
+ const TableSet& tableSet = keyEq[i]->tableSet();
+ for (TableSet::const_iterator j = tableSet.begin(); j != tableSet.end(); j++) {
+ if (tsDone.find(*j) == tsDone.end())
+ keySet.insert(*j);
+ }
+ }
+ if (! index.m_keyFound || index.m_keySet.size() > keySet.size()) {
+ index.m_keyFound = true;
+ index.m_keyEq = keyEq;
+ index.m_keySet = keySet;
+ index.m_keyCountUsed = n - 1;
+ index.m_keyCountUnused = index.m_keyCount - index.m_keyCountUsed;
+ // set matching size
+ index.m_keyEq.resize(1 + index.m_keyCountUsed);
+ }
+}
+
+bool
+Plan_table::exactKey(Ctx& ctx, const Index* indexKey) const
+{
+ ctx_assert(indexKey != 0 && indexKey == &m_indexList[indexKey->m_pos]);
+ for (unsigned i = 0; i <= indexCount(); i++) {
+ const Index& index = m_indexList[i];
+ const ExprListVector& keyEqList = index.m_keyEqList;
+ for (unsigned n = 1; n <= index.m_keyCount; n++) {
+ if (index.m_pos == indexKey->m_pos) {
+ ctx_assert(keyEqList[n].size() >= 1);
+ if (keyEqList[n].size() > 1) {
+ ctx_log2(("index %u not exact: column %u has %u > 1 matches",
+ indexKey->m_pos,
+ n,
+ (unsigned)keyEqList[n].size()));
+ return false;
+ }
+ } else {
+ if (keyEqList[n].size() > 0) {
+ ctx_log2(("index %u not exact: index %u column %u has %u > 0 matches",
+ indexKey->m_pos,
+ index.m_pos,
+ n,
+ (unsigned)keyEqList[n].size()));
+ return false;
+ }
+ }
+ }
+ }
+ ctx_log2(("index %u is exact", indexKey->m_pos));
+ return true;
+}
+
+Exec_base*
+Plan_table::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_table::print(Ctx& ctx)
+{
+ ctx.print(" [table %s]", getPrintName());
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_table.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_table.hpp
new file mode 100644
index 00000000000..8a95b8fa26c
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_table.hpp
@@ -0,0 +1,202 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_table_hpp
+#define ODBC_CODEGEN_Code_table_hpp
+
+#include <vector>
+#include <common/common.hpp>
+#include "Code_base.hpp"
+
+class DictTable;
+class DictColumn;
+class DictIndex;
+class Plan_query_filter;
+class Plan_query_lookup;
+class Plan_query_range;
+class Plan_column;
+class Plan_expr_column;
+class Plan_select;
+class Plan_delete;
+class Plan_delete_lookup;
+class Plan_update;
+class Plan_update_lookup;
+
+/**
+ * @class Plan_table
+ * @brief Table node in PlanTree
+ *
+ * This is a pure Plan node. Final executable nodes have table
+ * information built-in.
+ */
+class Plan_table : public Plan_base {
+public:
+ Plan_table(Plan_root* root, const BaseString& name);
+ virtual ~Plan_table();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // attributes
+ const BaseString& getName() const;
+ const BaseString& getCname() const;
+ const char* getPrintName() const;
+ void setCname(const BaseString& cname);
+ const DictTable& dictTable() const;
+ unsigned indexCount() const;
+ // resolve
+ const ColumnVector& exprColumns() const;
+ const ColumnVector& dmlColumns() const;
+protected:
+ friend class Plan_column;
+ friend class Plan_query_filter;
+ friend class Plan_query_lookup;
+ friend class Plan_query_index;
+ friend class Plan_query_range;
+ friend class Plan_expr_column;
+ friend class Plan_select;
+ friend class Plan_delete;
+ friend class Plan_delete_lookup;
+ friend class Plan_delete_index;
+ friend class Plan_update;
+ friend class Plan_update_lookup;
+ friend class Plan_update_index;
+ BaseString m_name;
+ BaseString m_cname;
+ BaseString m_printName;
+ DictTable* m_dictTable;
+ /*
+ * Resolve column. Returns 1 on found, 0 on not found, and -1 on error.
+ * Modifies both table and column data.
+ */
+ int resolveColumn(Ctx& ctx, Plan_column* column, bool stripSchemaName = false);
+ ColumnVector m_exprColumns;
+ ColumnVector m_dmlColumns;
+ /*
+ * Offset for resolved columns in join. This is sum over m_exprColumns
+ * lengths for all preceding tables.
+ */
+ unsigned m_resOff;
+ /*
+ * Each column in primary key and unique hash index has list of
+ * expressions it is set equal to in the where-clause (at top level).
+ */
+ bool resolveEq(Ctx& ctx, Plan_expr_column* column, Plan_expr* expr);
+ /*
+ * Index struct for primary key and indexes.
+ */
+ struct Index {
+ Index() :
+ m_pos(0),
+ m_keyFound(false),
+ m_dictIndex(0),
+ m_rank(~0),
+ m_keyCount(0),
+ m_keyCountUsed(0) {
+ }
+ unsigned m_pos;
+ ExprListVector m_keyEqList;
+ bool m_keyFound;
+ ExprVector m_keyEq;
+ TableSet m_keySet;
+ const DictIndex* m_dictIndex; // for index only
+ unsigned m_rank; // 0-pk 1-hash index 2-ordered index
+ unsigned m_keyCount; // number of columns
+ unsigned m_keyCountUsed; // may be less for ordered index
+ unsigned m_keyCountUnused; // m_keyCount - m_keyCountUsed
+ };
+ typedef std::vector<Index> IndexList; // primary key is entry 0
+ IndexList m_indexList;
+ /*
+ * Find set of additional tables (maybe empty) required to resolve the key
+ * columns.
+ */
+ void resolveSet(Ctx& ctx, Index& index, const TableSet& tsDone);
+ void resolveSet(Ctx& ctx, Index& index, const TableSet& tsDone, ExprVector& keyEq, unsigned n);
+ /*
+ * Check for exactly one key or index match.
+ */
+ bool exactKey(Ctx& ctx, const Index* indexKey) const;
+};
+
+inline
+Plan_table::Plan_table(Plan_root* root, const BaseString& name) :
+ Plan_base(root),
+ m_name(name),
+ m_printName(name),
+ m_dictTable(0),
+ m_exprColumns(1), // 1-based
+ m_dmlColumns(1), // 1-based
+ m_resOff(0),
+ m_indexList(1)
+{
+}
+
+inline const BaseString&
+Plan_table::getName() const
+{
+ return m_name;
+}
+
+inline const BaseString&
+Plan_table::getCname() const
+{
+ return m_cname;
+}
+
+inline const char*
+Plan_table::getPrintName() const
+{
+ return m_printName.c_str();
+}
+
+inline void
+Plan_table::setCname(const BaseString& cname)
+{
+ m_cname.assign(cname);
+ m_printName.assign(m_name);
+ if (! m_cname.empty()) {
+ m_printName.append(" ");
+ m_printName.append(m_cname);
+ }
+}
+
+inline const DictTable&
+Plan_table::dictTable() const
+{
+ ctx_assert(m_dictTable != 0);
+ return *m_dictTable;
+}
+
+inline unsigned
+Plan_table::indexCount() const
+{
+ ctx_assert(m_indexList.size() > 0);
+ return m_indexList.size() - 1;
+}
+
+inline const Plan_table::ColumnVector&
+Plan_table::exprColumns() const
+{
+ return m_exprColumns;
+}
+
+inline const Plan_table::ColumnVector&
+Plan_table::dmlColumns() const
+{
+ return m_dmlColumns;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_table_list.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_table_list.cpp
new file mode 100644
index 00000000000..ea9f4fdc26e
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_table_list.cpp
@@ -0,0 +1,53 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "Code_table_list.hpp"
+
+Plan_table_list::~Plan_table_list()
+{
+}
+
+Plan_base*
+Plan_table_list::analyze(Ctx& ctx, Ctl& ctl)
+{
+ // analyze the tables
+ for (unsigned i = 1, n = countTable(); i <= n; i++) {
+ Plan_table* table = getTable(i);
+ table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ }
+ // node was not replaced
+ return this;
+}
+
+Exec_base*
+Plan_table_list::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_table_list::print(Ctx& ctx)
+{
+ ctx.print(" [table_list");
+ for (unsigned i = 1, n = countTable(); i <= n; i++) {
+ Plan_base* a[] = { m_tableList[i] };
+ printList(ctx, a, 1);
+ }
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_table_list.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_table_list.hpp
new file mode 100644
index 00000000000..47989166cac
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_table_list.hpp
@@ -0,0 +1,73 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_table_list_hpp
+#define ODBC_CODEGEN_Code_table_list_hpp
+
+#include <common/common.hpp>
+#include "Code_base.hpp"
+#include "Code_table.hpp"
+
+/**
+ * @class Plan_table_list
+ * @brief List of tables in select statement
+ */
+class Plan_table_list : public Plan_base {
+public:
+ Plan_table_list(Plan_root* root);
+ virtual ~Plan_table_list();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ unsigned countTable() const;
+ void addTable(Plan_table* table);
+ Plan_table* getTable(unsigned i) const;
+protected:
+ friend class Plan_select;
+ TableVector m_tableList;
+};
+
+inline
+Plan_table_list::Plan_table_list(Plan_root* root) :
+ Plan_base(root),
+ m_tableList(1)
+{
+}
+
+// children
+
+inline unsigned
+Plan_table_list::countTable() const
+{
+ return m_tableList.size() - 1;
+}
+
+inline void
+Plan_table_list::addTable(Plan_table* table)
+{
+ ctx_assert(table != 0);
+ m_tableList.push_back(table);
+}
+
+inline Plan_table*
+Plan_table_list::getTable(unsigned i) const
+{
+ ctx_assert(1 <= i && i <= countTable() && m_tableList[i] != 0);
+ return m_tableList[i];
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_update.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_update.cpp
new file mode 100644
index 00000000000..0b33cd628b4
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_update.cpp
@@ -0,0 +1,246 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_update.hpp"
+#include "Code_update_lookup.hpp"
+#include "Code_update_index.hpp"
+#include "Code_update_scan.hpp"
+#include "Code_table.hpp"
+#include "Code_query_project.hpp"
+#include "Code_query_filter.hpp"
+#include "Code_query_scan.hpp"
+#include "Code_query_lookup.hpp"
+#include "Code_query_index.hpp"
+#include "Code_query_range.hpp"
+#include "Code_query_repeat.hpp"
+#include "Code_root.hpp"
+
+// Plan_update
+
+Plan_update::~Plan_update()
+{
+}
+
+Plan_base*
+Plan_update::analyze(Ctx& ctx, Ctl& ctl)
+{
+ stmtArea().stmtInfo().setName(Stmt_name_update);
+ // analyze the table
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ // get column and expression rows
+ ctx_assert(m_setRow != 0);
+ setDmlRow(m_setRow->m_dmlRow);
+ setExprRow(m_setRow->m_exprRow);
+ m_setRow = 0;
+ // implied by parse
+ ctx_assert(m_dmlRow->getSize() == m_exprRow->getSize());
+ // set name resolution scope
+ ctl.m_tableList.resize(1 + 1); // indexed from 1
+ ctl.m_tableList[1] = m_table;
+ // analyze the rows
+ m_dmlRow->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctl.m_dmlRow = m_dmlRow; // row type to convert to
+ ctl.m_const = true; // set to constants
+ m_exprRow->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ bool setConst = ctl.m_const;
+ ctl.m_dmlRow = 0;
+ Plan_dml* stmt = 0;
+ // top level query is a project
+ Plan_query_project* queryProject = new Plan_query_project(m_root);
+ m_root->saveNode(queryProject);
+ queryProject->setRow(m_exprRow);
+ if (m_pred != 0) {
+ // analyze the predicate
+ ctl.m_topand = true;
+ ctl.m_extra = false;
+ m_pred = static_cast<Plan_pred*>(m_pred->analyze(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_pred != 0);
+ // check for key match
+ Plan_table::Index* indexBest = 0;
+ for (unsigned i = 0; i <= m_table->indexCount(); i++) {
+ Plan_table::Index& index = m_table->m_indexList[i];
+ TableSet tsDone;
+ m_table->resolveSet(ctx, index, tsDone);
+ if (! ctx.ok())
+ return 0;
+ if (! index.m_keyFound)
+ continue;
+ // prefer smaller rank, less unused keys
+ int k;
+ (k = (indexBest == 0)) ||
+ (k = (indexBest->m_rank - index.m_rank)) ||
+ (k = (indexBest->m_keyCountUnused - index.m_keyCountUnused));
+ if (k > 0)
+ indexBest = &index;
+ }
+ if (indexBest != 0) {
+ const bool exactKey = indexBest->m_rank <= 1 ? m_table->exactKey(ctx, indexBest) : false;
+ const bool direct = setConst && ! ctl.m_extra && exactKey;
+ ctx_log3(("update direct=%d: const=%d extra=%d exact=%d", direct, setConst, ctl.m_extra, exactKey));
+ if (indexBest->m_rank == 0) {
+ // primary key
+ Plan_update_lookup* updateLookup = new Plan_update_lookup(m_root);
+ m_root->saveNode(updateLookup);
+ updateLookup->setTable(m_table);
+ updateLookup->setDmlRow(m_dmlRow);
+ if (direct) {
+ // constant values and exact key match
+ Plan_query_repeat* queryRepeat = new Plan_query_repeat(m_root, 1);
+ m_root->saveNode(queryRepeat);
+ queryProject->setQuery(queryRepeat);
+ } else {
+ // more conditions or non-constant values
+ Plan_query_lookup* queryLookup = new Plan_query_lookup(m_root);
+ m_root->saveNode(queryLookup);
+ Plan_query_filter* queryFilter = new Plan_query_filter(m_root);
+ m_root->saveNode(queryFilter);
+ queryLookup->setTable(m_table);
+ queryFilter->setQuery(queryLookup);
+ queryFilter->setPred(m_pred);
+ queryFilter->m_topTable = m_table;
+ queryProject->setQuery(queryFilter);
+ }
+ updateLookup->setQuery(queryProject);
+ stmt = updateLookup;
+ } else if (indexBest->m_rank == 1) {
+ // hash index
+ Plan_update_index* updateIndex = new Plan_update_index(m_root);
+ m_root->saveNode(updateIndex);
+ updateIndex->setTable(m_table, indexBest);
+ updateIndex->setDmlRow(m_dmlRow);
+ if (direct) {
+ // constant values and exact key match
+ Plan_query_repeat* queryRepeat = new Plan_query_repeat(m_root, 1);
+ m_root->saveNode(queryRepeat);
+ queryProject->setQuery(queryRepeat);
+ } else {
+ // more conditions or non-constant values
+ Plan_query_index* queryIndex = new Plan_query_index(m_root);
+ m_root->saveNode(queryIndex);
+ Plan_query_filter* queryFilter = new Plan_query_filter(m_root);
+ m_root->saveNode(queryFilter);
+ queryIndex->setTable(m_table, indexBest);
+ queryFilter->setQuery(queryIndex);
+ queryFilter->setPred(m_pred);
+ queryFilter->m_topTable = m_table;
+ queryProject->setQuery(queryFilter);
+ }
+ updateIndex->setQuery(queryProject);
+ stmt = updateIndex;
+ } else if (indexBest->m_rank == 2) {
+ // ordered index
+ Plan_update_scan* updateScan = new Plan_update_scan(m_root);
+ m_root->saveNode(updateScan);
+ updateScan->setTable(m_table);
+ updateScan->setDmlRow(m_dmlRow);
+ Plan_query_range* queryRange = new Plan_query_range(m_root);
+ m_root->saveNode(queryRange);
+ queryRange->setTable(m_table, indexBest);
+ queryRange->setExclusive();
+ Plan_query_filter* queryFilter = new Plan_query_filter(m_root);
+ m_root->saveNode(queryFilter);
+ queryFilter->setQuery(queryRange);
+ queryFilter->setPred(m_pred);
+ queryFilter->m_topTable = m_table;
+ // interpeter
+ const TableSet& ts2 = m_pred->noInterp();
+ ctx_assert(ts2.size() <= 1);
+ if (ts2.size() == 0) {
+ queryRange->setInterp(m_pred);
+ }
+ queryProject->setQuery(queryFilter);
+ updateScan->setQuery(queryProject);
+ stmt = updateScan;
+ } else {
+ ctx_assert(false);
+ }
+ } else {
+ // scan update with filter
+ Plan_update_scan* updateScan = new Plan_update_scan(m_root);
+ m_root->saveNode(updateScan);
+ updateScan->setTable(m_table);
+ updateScan->setDmlRow(m_dmlRow);
+ Plan_query_scan* queryScan = new Plan_query_scan(m_root);
+ m_root->saveNode(queryScan);
+ queryScan->setTable(m_table);
+ queryScan->setExclusive();
+ Plan_query_filter* queryFilter = new Plan_query_filter(m_root);
+ m_root->saveNode(queryFilter);
+ queryFilter->setQuery(queryScan);
+ queryFilter->setPred(m_pred);
+ queryFilter->m_topTable = m_table;
+ // interpeter
+ const TableSet& ts2 = m_pred->noInterp();
+ ctx_assert(ts2.size() <= 1);
+ if (ts2.size() == 0) {
+ queryScan->setInterp(m_pred);
+ }
+ queryProject->setQuery(queryFilter);
+ updateScan->setQuery(queryProject);
+ stmt = updateScan;
+ }
+ } else {
+ // scan update without filter
+ Plan_update_scan* updateScan = new Plan_update_scan(m_root);
+ m_root->saveNode(updateScan);
+ updateScan->setTable(m_table);
+ updateScan->setDmlRow(m_dmlRow);
+ Plan_query_scan* queryScan = new Plan_query_scan(m_root);
+ m_root->saveNode(queryScan);
+ queryScan->setTable(m_table);
+ queryScan->setExclusive();
+ queryProject->setQuery(queryScan);
+ updateScan->setQuery(queryProject);
+ stmt = updateScan;
+ }
+ // set base for column position offsets
+ m_table->m_resOff = 1;
+ return stmt;
+}
+
+void
+Plan_update::describe(Ctx& ctx)
+{
+ stmtArea().setFunction(ctx, "UPDATE WHERE", SQL_DIAG_UPDATE_WHERE);
+}
+
+Exec_base*
+Plan_update::codegen(Ctx& ctx, Ctl& ctl)
+{
+ ctx_assert(false);
+ return 0;
+}
+
+void
+Plan_update::print(Ctx& ctx)
+{
+ ctx.print(" [update");
+ Plan_base* a[] = { m_table, m_setRow, m_dmlRow, m_exprRow };
+ printList(ctx, a, 4);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_update.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_update.hpp
new file mode 100644
index 00000000000..380b651518b
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_update.hpp
@@ -0,0 +1,102 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_update_hpp
+#define ODBC_CODEGEN_Code_update_hpp
+
+#include <common/common.hpp>
+#include "Code_base.hpp"
+#include "Code_dml.hpp"
+#include "Code_set_row.hpp"
+#include "Code_table.hpp"
+#include "Code_pred.hpp"
+#include "Code_query.hpp"
+
+/**
+ * @class Plan_update
+ * @brief Update in PlanTree
+ */
+class Plan_update : public Plan_dml {
+public:
+ Plan_update(Plan_root* root);
+ virtual ~Plan_update();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ void setTable(Plan_table* table);
+ void setRow(Plan_set_row* setRow);
+ void setDmlRow(Plan_dml_row* dmlRow);
+ void setExprRow(Plan_expr_row* exprRow);
+ void setPred(Plan_pred* pred);
+protected:
+ Plan_table* m_table;
+ Plan_set_row* m_setRow;
+ Plan_dml_row* m_dmlRow;
+ Plan_expr_row* m_exprRow;
+ Plan_pred* m_pred;
+};
+
+inline
+Plan_update::Plan_update(Plan_root* root) :
+ Plan_dml(root),
+ m_table(0),
+ m_setRow(0),
+ m_dmlRow(0),
+ m_exprRow(0),
+ m_pred(0)
+{
+}
+
+// children
+
+inline void
+Plan_update::setTable(Plan_table* table)
+{
+ ctx_assert(table != 0);
+ m_table = table;
+}
+
+inline void
+Plan_update::setRow(Plan_set_row* setRow)
+{
+ ctx_assert(setRow != 0);
+ m_setRow = setRow;
+}
+
+inline void
+Plan_update::setDmlRow(Plan_dml_row* dmlRow)
+{
+ ctx_assert(dmlRow != 0);
+ m_dmlRow = dmlRow;
+}
+
+inline void
+Plan_update::setExprRow(Plan_expr_row* exprRow)
+{
+ ctx_assert(exprRow != 0);
+ m_exprRow = exprRow;
+}
+
+inline void
+Plan_update::setPred(Plan_pred* pred)
+{
+ ctx_assert(pred != 0);
+ m_pred = pred;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_update_index.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_update_index.cpp
new file mode 100644
index 00000000000..6f74db0d913
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_update_index.cpp
@@ -0,0 +1,196 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_dml_column.hpp"
+#include "Code_expr.hpp"
+#include "Code_update_index.hpp"
+#include "Code_table.hpp"
+#include "Code_root.hpp"
+
+// Plan_update_index
+
+Plan_update_index::~Plan_update_index()
+{
+}
+
+Plan_base*
+Plan_update_index::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctl.m_dmlRow = m_dmlRow; // row type to convert to
+ ctx_assert(m_query != 0);
+ m_query->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+void
+Plan_update_index::describe(Ctx& ctx)
+{
+ stmtArea().setFunction(ctx, "UPDATE WHERE", SQL_DIAG_UPDATE_WHERE);
+}
+
+Exec_base*
+Plan_update_index::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // generate code for the query
+ ctx_assert(m_query != 0);
+ Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execQuery != 0);
+ // set up
+ ctx_assert(m_table != 0 && m_index != 0);
+ const BaseString& tableName = m_table->getName();
+ ctx_assert(m_index->m_dictIndex != 0);
+ const DictIndex& dictIndex = *m_index->m_dictIndex;
+ const BaseString& indexName = dictIndex.getName();
+ const unsigned keyCount = m_index->m_keyCount;
+ const ColumnVector& columns = m_table->dmlColumns();
+ ctx_assert(columns.size() > 0);
+ const unsigned attrCount = columns.size() - 1;
+ // create the code
+ Exec_update_index::Code& code = *new Exec_update_index::Code(keyCount);
+ code.m_tableName = strcpy(new char[tableName.length() + 1], tableName.c_str());
+ code.m_indexName = strcpy(new char[indexName.length() + 1], indexName.c_str());
+ // key attributes
+ code.m_keyId = new NdbAttrId[1 + keyCount];
+ code.m_keyId[0] = (NdbAttrId)-1;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ const DictColumn* keyColumn = dictIndex.getColumn(k);
+ const SqlType& sqlType = keyColumn->sqlType();
+ SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
+ code.m_keySpecs.setEntry(k, sqlSpec);
+ code.m_keyId[k] = k - 1; // index column order
+ }
+ // matching expressions
+ ctx_assert(m_index->m_keyFound);
+ const ExprVector& keyEq = m_index->m_keyEq;
+ ctx_assert(keyEq.size() == 1 + keyCount);
+ code.m_keyMatch = new Exec_expr* [1 + keyCount];
+ code.m_keyMatch[0] = 0;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ Plan_expr* expr = keyEq[k];
+ Exec_expr* execExpr = static_cast<Exec_expr*>(expr->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execExpr != 0);
+ code.m_keyMatch[k] = execExpr;
+ }
+ // updated attributes
+ code.m_attrCount = attrCount;
+ code.m_attrId = new NdbAttrId[1 + attrCount];
+ code.m_attrId[0] = (NdbAttrId)-1;
+ for (unsigned i = 1; i <= attrCount; i++) {
+ Plan_column* column = columns[i];
+ ctx_assert(column != 0);
+ const DictColumn& dictColumn = column->dictColumn();
+ code.m_attrId[i] = dictColumn.getAttrId();
+ }
+ // create the exec
+ Exec_update_index* exec = new Exec_update_index(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ exec->setCode(code);
+ exec->setQuery(execQuery);
+ return exec;
+}
+
+void
+Plan_update_index::print(Ctx& ctx)
+{
+ ctx.print(" [update_index");
+ Plan_base* a[] = { m_table, m_query };
+ printList(ctx, a, sizeof(a)/sizeof(a[0]));
+ ctx.print("]");
+}
+
+// Exec_delete
+
+Exec_update_index::Code::~Code()
+{
+ delete[] m_tableName;
+ delete[] m_keyId;
+ delete[] m_keyMatch;
+ delete[] m_attrId;
+}
+
+Exec_update_index::Data::~Data()
+{
+}
+
+Exec_update_index::~Exec_update_index()
+{
+}
+
+void
+Exec_update_index::alloc(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ // allocate the subquery
+ ctx_assert(m_query != 0);
+ m_query->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // create data
+ Data& data = *new Data;
+ setData(data);
+ // allocate matching expressions
+ for (unsigned k = 1; k <= code.m_keyCount; k++) {
+ Exec_expr* expr = code.m_keyMatch[k];
+ ctx_assert(expr != 0);
+ expr->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ }
+}
+
+void
+Exec_update_index::close(Ctx& ctx)
+{
+ ctx_assert(m_query != 0);
+ m_query->close(ctx);
+}
+
+void
+Exec_update_index::print(Ctx& ctx)
+{
+ ctx.print(" [update_index");
+ if (m_code != 0) {
+ const Code& code = getCode();
+ ctx.print(" keyId=");
+ for (unsigned i = 1; i <= code.m_keyCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_keyId[i]);
+ }
+ ctx.print(" attrId=");
+ for (unsigned i = 1; i <= code.m_attrCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_attrId[i]);
+ }
+ }
+ Exec_base* a[] = { m_query };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_update_index.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_update_index.hpp
new file mode 100644
index 00000000000..bbad822650a
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_update_index.hpp
@@ -0,0 +1,171 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_update_index_hpp
+#define ODBC_CODEGEN_Code_update_index_hpp
+
+#include <common/common.hpp>
+#include "Code_base.hpp"
+#include "Code_dml.hpp"
+#include "Code_table.hpp"
+#include "Code_query.hpp"
+
+/**
+ * @class Plan_update_index
+ * @brief Update in PlanTree
+ */
+class Plan_update_index : public Plan_dml {
+public:
+ Plan_update_index(Plan_root* root);
+ virtual ~Plan_update_index();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx& ctx);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setTable(Plan_table* table, Plan_table::Index* index);
+ void setDmlRow(Plan_dml_row* dmlRow);
+ void setQuery(Plan_query* query);
+protected:
+ Plan_table* m_table;
+ Plan_table::Index* m_index;
+ Plan_dml_row* m_dmlRow;
+ Plan_query* m_query;
+};
+
+inline
+Plan_update_index::Plan_update_index(Plan_root* root) :
+ Plan_dml(root),
+ m_table(0),
+ m_dmlRow(0),
+ m_query(0)
+{
+}
+
+inline void
+Plan_update_index::setTable(Plan_table* table, Plan_table::Index* index)
+{
+ ctx_assert(table != 0 && index != 0 && index == &table->m_indexList[index->m_pos] && index->m_pos != 0);
+ m_table = table;
+ m_index = index;
+}
+
+inline void
+Plan_update_index::setDmlRow(Plan_dml_row* dmlRow)
+{
+ ctx_assert(dmlRow != 0);
+ m_dmlRow = dmlRow;
+}
+
+inline void
+Plan_update_index::setQuery(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+/**
+ * @class Exec_update_index
+ * @brief Insert in ExecTree
+ */
+class Exec_update_index : public Exec_dml {
+public:
+ class Code : public Exec_dml::Code {
+ public:
+ Code(unsigned keyCount);
+ virtual ~Code();
+ protected:
+ friend class Plan_update_index;
+ friend class Exec_update_index;
+ const char* m_tableName;
+ const char* m_indexName;
+ unsigned m_keyCount;
+ SqlSpecs m_keySpecs; // key types
+ NdbAttrId* m_keyId;
+ Exec_expr** m_keyMatch; // XXX pointers for now
+ unsigned m_attrCount;
+ NdbAttrId* m_attrId;
+ };
+ class Data : public Exec_dml::Data {
+ public:
+ Data();
+ virtual ~Data();
+ protected:
+ friend class Exec_update_index;
+ };
+ Exec_update_index(Exec_root* root);
+ virtual ~Exec_update_index();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setQuery(Exec_query* query);
+protected:
+ Exec_query* m_query;
+};
+
+inline
+Exec_update_index::Code::Code(unsigned keyCount) :
+ m_tableName(0),
+ m_indexName(0),
+ m_keyCount(keyCount),
+ m_keySpecs(keyCount),
+ m_keyId(0),
+ m_keyMatch(0),
+ m_attrCount(0),
+ m_attrId(0)
+{
+}
+
+inline
+Exec_update_index::Data::Data()
+{
+}
+
+inline
+Exec_update_index::Exec_update_index(Exec_root* root) :
+ Exec_dml(root),
+ m_query(0)
+{
+}
+
+// children
+
+inline const Exec_update_index::Code&
+Exec_update_index::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_update_index::Data&
+Exec_update_index::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_update_index::setQuery(Exec_query* query)
+{
+ ctx_assert(query != 0 && m_query == 0);
+ m_query = query;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_update_lookup.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_update_lookup.cpp
new file mode 100644
index 00000000000..7525fb72692
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_update_lookup.cpp
@@ -0,0 +1,194 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_dml_column.hpp"
+#include "Code_expr.hpp"
+#include "Code_update_lookup.hpp"
+#include "Code_table.hpp"
+#include "Code_root.hpp"
+
+// Plan_update_lookup
+
+Plan_update_lookup::~Plan_update_lookup()
+{
+}
+
+Plan_base*
+Plan_update_lookup::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctl.m_dmlRow = m_dmlRow; // row type to convert to
+ ctx_assert(m_query != 0);
+ m_query->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+void
+Plan_update_lookup::describe(Ctx& ctx)
+{
+ stmtArea().setFunction(ctx, "UPDATE WHERE", SQL_DIAG_UPDATE_WHERE);
+}
+
+Exec_base*
+Plan_update_lookup::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // generate code for the query
+ ctx_assert(m_query != 0);
+ Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execQuery != 0);
+ // set up
+ ctx_assert(m_table != 0);
+ const BaseString& tableName = m_table->getName();
+ const DictTable& dictTable = m_table->dictTable();
+ const unsigned keyCount = dictTable.keyCount();
+ const ColumnVector& columns = m_table->dmlColumns();
+ ctx_assert(columns.size() > 0);
+ const unsigned attrCount = columns.size() - 1;
+ // create the code
+ Exec_update_lookup::Code& code = *new Exec_update_lookup::Code(keyCount);
+ code.m_tableName = strcpy(new char[tableName.length() + 1], tableName.c_str());
+ // key attributes
+ code.m_keyId = new NdbAttrId[1 + keyCount];
+ code.m_keyId[0] = (NdbAttrId)-1;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ const DictColumn* keyColumn = dictTable.getKey(k);
+ const SqlType& sqlType = keyColumn->sqlType();
+ SqlSpec sqlSpec(sqlType, SqlSpec::Physical);
+ code.m_keySpecs.setEntry(k, sqlSpec);
+ code.m_keyId[k] = keyColumn->getAttrId();
+ }
+ // matching expressions
+ const Plan_table::Index& index = m_table->m_indexList[0];
+ ctx_assert(index.m_keyFound);
+ const ExprVector& keyEq = index.m_keyEq;
+ ctx_assert(keyEq.size() == 1 + keyCount);
+ code.m_keyMatch = new Exec_expr* [1 + keyCount];
+ code.m_keyMatch[0] = 0;
+ for (unsigned k = 1; k <= keyCount; k++) {
+ Plan_expr* expr = keyEq[k];
+ Exec_expr* execExpr = static_cast<Exec_expr*>(expr->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execExpr != 0);
+ code.m_keyMatch[k] = execExpr;
+ }
+ // updated attributes
+ code.m_attrCount = attrCount;
+ code.m_attrId = new NdbAttrId[1 + attrCount];
+ code.m_attrId[0] = (NdbAttrId)-1;
+ for (unsigned i = 1; i <= attrCount; i++) {
+ Plan_column* column = columns[i];
+ ctx_assert(column != 0);
+ const DictColumn& dictColumn = column->dictColumn();
+ code.m_attrId[i] = dictColumn.getAttrId();
+ }
+ // create the exec
+ Exec_update_lookup* exec = new Exec_update_lookup(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ exec->setCode(code);
+ exec->setQuery(execQuery);
+ return exec;
+}
+
+void
+Plan_update_lookup::print(Ctx& ctx)
+{
+ ctx.print(" [update_lookup");
+ Plan_base* a[] = { m_table, m_query };
+ printList(ctx, a, sizeof(a)/sizeof(a[0]));
+ ctx.print("]");
+}
+
+// Exec_delete
+
+Exec_update_lookup::Code::~Code()
+{
+ delete[] m_tableName;
+ delete[] m_keyId;
+ delete[] m_keyMatch;
+ delete[] m_attrId;
+}
+
+Exec_update_lookup::Data::~Data()
+{
+}
+
+Exec_update_lookup::~Exec_update_lookup()
+{
+}
+
+void
+Exec_update_lookup::alloc(Ctx& ctx, Ctl& ctl)
+{
+ const Code& code = getCode();
+ // allocate the subquery
+ ctx_assert(m_query != 0);
+ m_query->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // create data
+ Data& data = *new Data;
+ setData(data);
+ // allocate matching expressions
+ for (unsigned k = 1; k <= code.m_keyCount; k++) {
+ Exec_expr* expr = code.m_keyMatch[k];
+ ctx_assert(expr != 0);
+ expr->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ }
+}
+
+void
+Exec_update_lookup::close(Ctx& ctx)
+{
+ ctx_assert(m_query != 0);
+ m_query->close(ctx);
+}
+
+void
+Exec_update_lookup::print(Ctx& ctx)
+{
+ ctx.print(" [update_lookup");
+ if (m_code != 0) {
+ const Code& code = getCode();
+ ctx.print(" keyId=");
+ for (unsigned i = 1; i <= code.m_keyCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_keyId[i]);
+ }
+ ctx.print(" attrId=");
+ for (unsigned i = 1; i <= code.m_attrCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_attrId[i]);
+ }
+ }
+ Exec_base* a[] = { m_query };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_update_lookup.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_update_lookup.hpp
new file mode 100644
index 00000000000..fc4341880dd
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_update_lookup.hpp
@@ -0,0 +1,167 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_update_lookup_hpp
+#define ODBC_CODEGEN_Code_update_lookup_hpp
+
+#include <common/common.hpp>
+#include "Code_base.hpp"
+#include "Code_dml.hpp"
+#include "Code_table.hpp"
+#include "Code_query.hpp"
+
+/**
+ * @class Plan_update_lookup
+ * @brief Update in PlanTree
+ */
+class Plan_update_lookup : public Plan_dml {
+public:
+ Plan_update_lookup(Plan_root* root);
+ virtual ~Plan_update_lookup();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx& ctx);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setTable(Plan_table* table);
+ void setDmlRow(Plan_dml_row* dmlRow);
+ void setQuery(Plan_query* query);
+protected:
+ Plan_table* m_table;
+ Plan_dml_row* m_dmlRow;
+ Plan_query* m_query;
+};
+
+inline
+Plan_update_lookup::Plan_update_lookup(Plan_root* root) :
+ Plan_dml(root),
+ m_table(0),
+ m_dmlRow(0),
+ m_query(0)
+{
+}
+
+inline void
+Plan_update_lookup::setTable(Plan_table* table)
+{
+ ctx_assert(table != 0);
+ m_table = table;
+}
+
+inline void
+Plan_update_lookup::setDmlRow(Plan_dml_row* dmlRow)
+{
+ ctx_assert(dmlRow != 0);
+ m_dmlRow = dmlRow;
+}
+
+inline void
+Plan_update_lookup::setQuery(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+/**
+ * @class Exec_update_lookup
+ * @brief Insert in ExecTree
+ */
+class Exec_update_lookup : public Exec_dml {
+public:
+ class Code : public Exec_dml::Code {
+ public:
+ Code(unsigned keyCount);
+ virtual ~Code();
+ protected:
+ friend class Plan_update_lookup;
+ friend class Exec_update_lookup;
+ char* m_tableName;
+ unsigned m_keyCount;
+ SqlSpecs m_keySpecs; // key types
+ NdbAttrId* m_keyId;
+ Exec_expr** m_keyMatch; // XXX pointers for now
+ unsigned m_attrCount;
+ NdbAttrId* m_attrId;
+ };
+ class Data : public Exec_dml::Data {
+ public:
+ Data();
+ virtual ~Data();
+ protected:
+ friend class Exec_update_lookup;
+ };
+ Exec_update_lookup(Exec_root* root);
+ virtual ~Exec_update_lookup();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setQuery(Exec_query* query);
+protected:
+ Exec_query* m_query;
+};
+
+inline
+Exec_update_lookup::Code::Code(unsigned keyCount) :
+ m_tableName(0),
+ m_keyCount(keyCount),
+ m_keySpecs(keyCount),
+ m_keyId(0),
+ m_keyMatch(0),
+ m_attrCount(0),
+ m_attrId(0)
+{
+}
+
+inline
+Exec_update_lookup::Data::Data()
+{
+}
+
+inline
+Exec_update_lookup::Exec_update_lookup(Exec_root* root) :
+ Exec_dml(root),
+ m_query(0)
+{
+}
+
+// children
+
+inline const Exec_update_lookup::Code&
+Exec_update_lookup::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_update_lookup::Data&
+Exec_update_lookup::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_update_lookup::setQuery(Exec_query* query)
+{
+ ctx_assert(query != 0 && m_query == 0);
+ m_query = query;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_update_scan.cpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_update_scan.cpp
new file mode 100644
index 00000000000..9fac1728469
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_update_scan.cpp
@@ -0,0 +1,146 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/StmtArea.hpp>
+#include <dictionary/DictTable.hpp>
+#include <dictionary/DictColumn.hpp>
+#include "Code_dml_column.hpp"
+#include "Code_update_scan.hpp"
+#include "Code_table.hpp"
+#include "Code_root.hpp"
+
+// Plan_update_scan
+
+Plan_update_scan::~Plan_update_scan()
+{
+}
+
+Plan_base*
+Plan_update_scan::analyze(Ctx& ctx, Ctl& ctl)
+{
+ ctl.m_dmlRow = m_dmlRow; // row type to convert to
+ ctx_assert(m_query != 0);
+ m_query->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(m_table != 0);
+ m_table->analyze(ctx, ctl);
+ if (! ctx.ok())
+ return 0;
+ return this;
+}
+
+void
+Plan_update_scan::describe(Ctx& ctx)
+{
+ stmtArea().setFunction(ctx, "UPDATE WHERE", SQL_DIAG_UPDATE_WHERE);
+}
+
+Exec_base*
+Plan_update_scan::codegen(Ctx& ctx, Ctl& ctl)
+{
+ // generate code for the query
+ ctx_assert(m_query != 0);
+ Exec_query* execQuery = static_cast<Exec_query*>(m_query->codegen(ctx, ctl));
+ if (! ctx.ok())
+ return 0;
+ ctx_assert(execQuery != 0);
+ // set up
+ ctx_assert(m_table != 0);
+ const ColumnVector& columns = m_table->dmlColumns();
+ ctx_assert(columns.size() > 0);
+ const unsigned attrCount = columns.size() - 1;
+ // create the code
+ Exec_update_scan::Code& code = *new Exec_update_scan::Code();
+ // updated attributes
+ code.m_attrCount = attrCount;
+ code.m_attrId = new NdbAttrId[1 + attrCount];
+ code.m_attrId[0] = (NdbAttrId)-1;
+ for (unsigned i = 1; i <= attrCount; i++) {
+ Plan_column* column = columns[i];
+ ctx_assert(column != 0);
+ const DictColumn& dictColumn = column->dictColumn();
+ code.m_attrId[i] = dictColumn.getAttrId();
+ }
+ // create the exec
+ Exec_update_scan* exec = new Exec_update_scan(ctl.m_execRoot);
+ ctl.m_execRoot->saveNode(exec);
+ exec->setCode(code);
+ exec->setQuery(execQuery);
+ return exec;
+}
+
+void
+Plan_update_scan::print(Ctx& ctx)
+{
+ ctx.print(" [update_scan");
+ Plan_base* a[] = { m_table, m_query };
+ printList(ctx, a, sizeof(a)/sizeof(a[0]));
+ ctx.print("]");
+}
+
+// Exec_delete
+
+Exec_update_scan::Code::~Code()
+{
+ delete[] m_attrId;
+}
+
+Exec_update_scan::Data::~Data()
+{
+}
+
+Exec_update_scan::~Exec_update_scan()
+{
+}
+
+void
+Exec_update_scan::alloc(Ctx& ctx, Ctl& ctl)
+{
+ // allocate the subquery
+ ctx_assert(m_query != 0);
+ m_query->alloc(ctx, ctl);
+ if (! ctx.ok())
+ return;
+ // create data
+ Data& data = *new Data;
+ setData(data);
+}
+
+void
+Exec_update_scan::close(Ctx& ctx)
+{
+ ctx_assert(m_query != 0);
+ m_query->close(ctx);
+}
+
+void
+Exec_update_scan::print(Ctx& ctx)
+{
+ ctx.print(" [update_scan");
+ if (m_code != 0) {
+ const Code& code = getCode();
+ ctx.print(" attrId=");
+ for (unsigned i = 1; i <= code.m_attrCount; i++) {
+ if (i > 1)
+ ctx.print(",");
+ ctx.print("%u", (unsigned)code.m_attrId[i]);
+ }
+ }
+ Exec_base* a[] = { m_query };
+ printList(ctx, a, 1);
+ ctx.print("]");
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Code_update_scan.hpp b/storage/ndb/src/old_files/client/odbc/codegen/Code_update_scan.hpp
new file mode 100644
index 00000000000..d742883e561
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Code_update_scan.hpp
@@ -0,0 +1,160 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_Code_update_scan_hpp
+#define ODBC_CODEGEN_Code_update_scan_hpp
+
+#include <common/common.hpp>
+#include "Code_base.hpp"
+#include "Code_dml.hpp"
+#include "Code_table.hpp"
+#include "Code_pred.hpp"
+#include "Code_query.hpp"
+
+/**
+ * @class Plan_update_scan
+ * @brief Update in PlanTree
+ */
+class Plan_update_scan : public Plan_dml {
+public:
+ Plan_update_scan(Plan_root* root);
+ virtual ~Plan_update_scan();
+ Plan_base* analyze(Ctx& ctx, Ctl& ctl);
+ void describe(Ctx& ctx);
+ Exec_base* codegen(Ctx& ctx, Ctl& ctl);
+ void print(Ctx& ctx);
+ // children
+ void setTable(Plan_table* table);
+ void setDmlRow(Plan_dml_row* dmlRow);
+ void setQuery(Plan_query* query);
+protected:
+ Plan_table* m_table;
+ Plan_dml_row* m_dmlRow;
+ Plan_query* m_query;
+};
+
+inline
+Plan_update_scan::Plan_update_scan(Plan_root* root) :
+ Plan_dml(root),
+ m_table(0),
+ m_dmlRow(0),
+ m_query(0)
+{
+}
+
+// children
+
+inline void
+Plan_update_scan::setTable(Plan_table* table)
+{
+ ctx_assert(table != 0);
+ m_table = table;
+}
+
+inline void
+Plan_update_scan::setDmlRow(Plan_dml_row* dmlRow)
+{
+ ctx_assert(dmlRow != 0);
+ m_dmlRow = dmlRow;
+}
+
+inline void
+Plan_update_scan::setQuery(Plan_query* query)
+{
+ ctx_assert(query != 0);
+ m_query = query;
+}
+
+/**
+ * @class Exec_update_scan
+ * @brief Insert in ExecTree
+ */
+class Exec_update_scan : public Exec_dml {
+public:
+ class Code : public Exec_dml::Code {
+ public:
+ Code();
+ virtual ~Code();
+ protected:
+ friend class Plan_update_scan;
+ friend class Exec_update_scan;
+ unsigned m_attrCount;
+ NdbAttrId* m_attrId;
+ };
+ class Data : public Exec_dml::Data {
+ public:
+ Data();
+ virtual ~Data();
+ protected:
+ friend class Exec_update_scan;
+ };
+ Exec_update_scan(Exec_root* root);
+ virtual ~Exec_update_scan();
+ void alloc(Ctx& ctx, Ctl& ctl);
+ void execImpl(Ctx& ctx, Ctl& ctl);
+ void close(Ctx& ctx);
+ void print(Ctx& ctx);
+ // children
+ const Code& getCode() const;
+ Data& getData() const;
+ void setQuery(Exec_query* query);
+protected:
+ Exec_query* m_query;
+};
+
+inline
+Exec_update_scan::Code::Code() :
+ m_attrCount(0),
+ m_attrId(0)
+{
+}
+
+inline
+Exec_update_scan::Data::Data()
+{
+}
+
+inline
+Exec_update_scan::Exec_update_scan(Exec_root* root) :
+ Exec_dml(root),
+ m_query(0)
+{
+}
+
+// children
+
+inline const Exec_update_scan::Code&
+Exec_update_scan::getCode() const
+{
+ const Code* code = static_cast<const Code*>(m_code);
+ return *code;
+}
+
+inline Exec_update_scan::Data&
+Exec_update_scan::getData() const
+{
+ Data* data = static_cast<Data*>(m_data);
+ return *data;
+}
+
+inline void
+Exec_update_scan::setQuery(Exec_query* query)
+{
+ ctx_assert(query != 0 && m_query == 0);
+ m_query = query;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/Makefile b/storage/ndb/src/old_files/client/odbc/codegen/Makefile
new file mode 100644
index 00000000000..49e5439556d
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/Makefile
@@ -0,0 +1,104 @@
+include .defs.mk
+
+TYPE = *
+
+NONPIC_ARCHIVE = N
+
+PIC_ARCHIVE = Y
+
+ARCHIVE_TARGET = odbccodegen
+
+SOURCES = \
+ SimpleScan.lpp \
+ SimpleGram.ypp \
+ SimpleParser.cpp \
+ CodeGen.cpp \
+ Code_base.cpp \
+ Code_root.cpp \
+ Code_stmt.cpp \
+ Code_query.cpp \
+ Code_dml.cpp \
+ Code_ddl.cpp \
+ Code_select.cpp \
+ Code_pred.cpp \
+ Code_pred_op.cpp \
+ Code_comp_op.cpp \
+ Code_query_project.cpp \
+ Code_query_filter.cpp \
+ Code_query_join.cpp \
+ Code_query_lookup.cpp \
+ Code_query_index.cpp \
+ Code_query_scan.cpp \
+ Code_query_range.cpp \
+ Code_query_sys.cpp \
+ Code_query_repeat.cpp \
+ Code_query_count.cpp \
+ Code_query_sort.cpp \
+ Code_query_group.cpp \
+ Code_query_distinct.cpp \
+ Code_expr_row.cpp \
+ Code_expr.cpp \
+ Code_expr_op.cpp \
+ Code_expr_func.cpp \
+ Code_expr_conv.cpp \
+ Code_expr_column.cpp \
+ Code_expr_const.cpp \
+ Code_expr_param.cpp \
+ Code_update.cpp \
+ Code_update_lookup.cpp \
+ Code_update_index.cpp \
+ Code_update_scan.cpp \
+ Code_set_row.cpp \
+ Code_insert.cpp \
+ Code_dml_row.cpp \
+ Code_dml_column.cpp \
+ Code_delete.cpp \
+ Code_delete_lookup.cpp \
+ Code_delete_index.cpp \
+ Code_delete_scan.cpp \
+ Code_column.cpp \
+ Code_table_list.cpp \
+ Code_table.cpp \
+ Code_create_table.cpp \
+ Code_create_index.cpp \
+ Code_create_row.cpp \
+ Code_ddl_row.cpp \
+ Code_ddl_column.cpp \
+ Code_ddl_constr.cpp \
+ Code_idx_column.cpp \
+ Code_data_type.cpp \
+ Code_drop_table.cpp \
+ Code_drop_index.cpp
+
+ifeq ($(NDB_OS),WIN32)
+CCFLAGS += -I$(call fixpath,.)
+
+_libs:: FlexLexer.h unistd.h
+
+endif
+
+include ../Extra.mk
+include $(NDB_TOP)/Epilogue.mk
+
+ifeq ($(NDB_OS),LINUX)
+FLEXHACK = perl -i -pe 's/\bisatty\b/ouencunbwdb2y1bdc/g'
+BISONHACK = perl -i -pe 's/^\s*__attribute__\s*\(\(.*\)\)//'
+endif
+
+ifeq ($(NDB_OS),MACOSX)
+FLEXHACK = perl -i -pe 's/\bisatty\b/ouencunbwdb2y1bdc/g'
+BISONHACK = perl -i -pe 's/^\s*__attribute__\s*\(\(.*\)\)//'
+endif
+
+ifeq ($(NDB_OS),SOLARIS)
+BISONHACK = perl -i -pe 's/^\s*__attribute__\s*\(\(.*\)\)//'
+endif
+
+ifeq ($(NDB_OS),WIN32)
+unistd.h:
+ touch unistd.h
+
+FlexLexer.h:
+ cp /usr/include/FlexLexer.h .
+
+endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/SimpleGram.ypp b/storage/ndb/src/old_files/client/odbc/codegen/SimpleGram.ypp
new file mode 100644
index 00000000000..07d8017e5ed
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/SimpleGram.ypp
@@ -0,0 +1,1649 @@
+%{
+
+#include <NdbApi.hpp>
+#include <common/StmtArea.hpp>
+#include <common/DataRow.hpp>
+#include "CodeGen.hpp"
+#include <FlexLexer.h>
+#include "SimpleParser.hpp"
+
+/* redefine globals after headers */
+#define yyparse SimpleParser_yyparse
+#if YYDEBUG
+#define yydebug SimpleParser_yydebug
+#endif
+
+#define YYLEX_PARAM simpleParserPtr
+#define YYPARSE_PARAM simpleParserPtr
+#define simpleParser (*static_cast<SimpleParser*>(simpleParserPtr))
+
+static int yylex(YYSTYPE* lvalp, void* simpleParserPtr);
+
+#define yyerror(s) simpleParser.parseError(s)
+
+#if YYDEBUG
+// does not work in bison 1.75
+#undef stderr
+#define stderr 0
+#define YYFPRINTF simpleParser.ctx().print
+#endif
+
+// scanner states
+
+#define pushState(sc) simpleParser.pushState(sc)
+#define popState() simpleParser.popState()
+
+#define StateEval SimpleParser_stateEval
+#define StateType SimpleParser_stateType
+#define StatePhys SimpleParser_statePhys
+extern int SimpleParser_stateEval;
+extern int SimpleParser_stateType;
+extern int SimpleParser_statePhys;
+
+struct LimitPair { int off; int cnt; };
+
+struct PhysAttr { int storage; int logging; };
+
+%}
+
+%defines
+%pure-parser
+%verbose
+
+%union {
+ Plan_root* m_root;
+ Plan_stmt* m_stmt;
+ Plan_select* m_select;
+ Insert_op m_insert_op;
+ Plan_insert* m_insert;
+ Plan_update* m_update;
+ Plan_delete* m_delete;
+ Plan_create_table* m_create_table;
+ Plan_create_index* m_create_index;
+ NdbDictionary::Object::Type m_index_type;
+ Plan_create_row* m_create_row;
+ Plan_ddl_row* m_ddl_row;
+ Plan_ddl_column* m_ddl_column;
+ Plan_ddl_constr* m_ddl_constr;
+ Plan_idx_column* m_idx_column;
+ Plan_data_type* m_data_type;
+ Plan_drop_table* m_drop_table;
+ Plan_drop_index* m_drop_index;
+ Plan_set_row* m_set_row;
+ Plan_expr_row* m_expr_row;
+ bool m_asc_desc;
+ Plan_pred* m_pred;
+ Pred_op::Opcode m_pred_opcode;
+ Comp_op::Opcode m_comp_opcode;
+ Plan_expr* m_expr;
+ Expr_op::Opcode m_expr_opcode;
+ Plan_dml_row* m_dml_row;
+ Plan_dml_column* m_dml_column;
+ Plan_table* m_table;
+ Plan_table_list* m_table_list;
+ const char* m_string;
+ struct LimitPair* m_limit;
+ int m_signed_integer;
+ bool m_distinct;
+ struct PhysAttr* m_phys_attr;
+ NdbDictionary::Object::FragmentType m_storage_attr;
+ bool m_logging_attr;
+ SqlType::Type m_sql_type;
+}
+
+/* keywords */
+%token
+ T_AND
+ T_ASC
+ T_AUTO_INCREMENT
+ T_BIGINT
+ T_BINARY
+ T_BLOB
+ T_BY
+ T_CHAR
+ T_CLOB
+ T_CONSTRAINT
+ T_CREATE
+ T_DATETIME
+ T_DEFAULT
+ T_DELETE
+ T_DESC
+ T_DISTINCT
+ T_DOUBLE
+ T_DROP
+ T_FLOAT
+ T_FOREIGN
+ T_FROM
+ T_GROUP
+ T_HASH
+ T_HAVING
+ T_IN
+ T_INDEX
+ T_INSERT
+ T_INT
+ T_INTEGER
+ T_INTO
+ T_IS
+ T_KEY
+ T_LARGE
+ T_LIKE
+ T_LIMIT
+ T_LOGGING
+ T_LONGBLOB
+ T_LONGCLOB
+ T_MEDIUM
+ T_NOLOGGING
+ T_NOT
+ T_NULL
+ T_OFFSET
+ T_ON
+ T_OR
+ T_ORDER
+ T_PRECISION
+ T_PRIMARY
+ T_REAL
+ T_REFERENCES
+ T_ROWNUM
+ T_SELECT
+ T_SET
+ T_SINGLE
+ T_SMALL
+ T_SMALLINT
+ T_STORAGE
+ T_SYSDATE
+ T_TABLE
+ T_UNIQUE
+ T_UNSIGNED
+ T_UPDATE
+ T_VALUES
+ T_VARBINARY
+ T_VARCHAR
+ T_WHERE
+ T_WRITE
+
+/* identifiers and constants */
+%token
+ <m_string> T_IDENTIFIER
+ <m_string> T_LINTEGER
+ <m_string> T_LDECIMAL
+ <m_string> T_LREAL
+ <m_string> T_STRING
+
+/* expressions and predicates */
+%token
+ T_PLUS
+ T_MINUS
+ T_TIMES
+ T_DIVIDE
+ T_EQ
+ T_NOTEQ
+ T_LT
+ T_LTEQ
+ T_GT
+ T_GTEQ
+ T_QUES
+
+/* common special symbols */
+%token
+ T_PERIOD
+ T_COMMA
+ T_PARENLEFT
+ T_PARENRIGHT
+ T_ASTERISK
+ T_ASSIGN
+
+%type <m_root> root
+%type <m_stmt> stmt
+%type <m_select> stmt_select
+%type <m_insert> stmt_insert
+%type <m_insert_op> insert_op
+%type <m_update> stmt_update
+%type <m_delete> stmt_delete
+%type <m_create_table> create_table
+%type <m_create_index> create_index
+%type <m_index_type> index_type
+%type <m_create_row> create_row
+%type <m_ddl_column> create_column
+%type <m_ddl_constr> create_constr
+%type <m_idx_column> idx_column
+%type <m_data_type> data_type
+%type <m_ddl_row> ddl_row
+%type <m_ddl_column> ddl_column
+%type <m_drop_table> drop_table
+%type <m_drop_index> drop_index
+%type <m_asc_desc> asc_desc
+%type <m_set_row> set_row
+%type <m_expr_row> expr_row
+%type <m_expr_row> sort_row
+%type <m_pred> where_clause
+%type <m_expr_row> order_clause
+%type <m_pred> pred
+%type <m_pred> pred1
+%type <m_pred_opcode> pred1_op
+%type <m_pred> pred2
+%type <m_pred_opcode> pred2_op
+%type <m_pred> pred3
+%type <m_pred_opcode> pred3_op
+%type <m_pred> pred4
+%type <m_comp_opcode> comp_op
+%type <m_expr> expr
+%type <m_expr> expr1
+%type <m_expr_opcode> expr1_op
+%type <m_expr> expr2
+%type <m_expr_opcode> expr2_op
+%type <m_expr> expr3
+%type <m_expr_opcode> expr3_op
+%type <m_expr> expr4
+%type <m_expr> expr_column
+%type <m_dml_row> dml_row
+%type <m_dml_column> dml_column
+%type <m_expr_row> value_row
+%type <m_expr> value_expr
+%type <m_table> table
+%type <m_table_list> table_list
+%type <m_string> dot_identifier
+%type <m_limit> limit_clause
+%type <m_signed_integer> signed_integer
+%type <m_distinct> distinct_clause
+%type <m_expr_row> group_clause
+%type <m_pred> having_clause
+%type <m_phys_attr> phys_attr
+%type <m_phys_attr> phys_attr2
+%type <m_storage_attr> storage_attr
+%type <m_logging_attr> logging_attr
+%type <m_sql_type> blob_type
+
+%%
+
+root:
+ stmt
+ {
+ Plan_root* root = simpleParser.root();
+ root->setStmt($1);
+ }
+ ;
+stmt:
+ stmt_select
+ {
+ $$ = $1;
+ }
+ |
+ stmt_insert
+ {
+ $$ = $1;
+ }
+ |
+ stmt_update
+ {
+ $$ = $1;
+ }
+ |
+ stmt_delete
+ {
+ $$ = $1;
+ }
+ |
+ create_table
+ {
+ $$ = $1;
+ }
+ |
+ create_index
+ {
+ $$ = $1;
+ }
+ |
+ drop_table
+ {
+ $$ = $1;
+ }
+ |
+ drop_index
+ {
+ $$ = $1;
+ }
+ ;
+stmt_select:
+ T_SELECT distinct_clause expr_row T_FROM table_list where_clause group_clause having_clause order_clause limit_clause
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_select* stmt = new Plan_select(root);
+ root->saveNode(stmt);
+ stmt->setDistinct($2);
+ stmt->setRow($3);
+ stmt->setList($5);
+ if ($6 != 0)
+ stmt->setPred($6);
+ if ($7 != 0)
+ stmt->setGroup($7);
+ if ($8 != 0)
+ stmt->setHaving($8);
+ if ($9 != 0)
+ stmt->setSort($9);
+ if ($10 != 0) {
+ stmt->setLimit($10->off, $10->cnt);
+ delete $10;
+ }
+ $$ = stmt;
+ }
+ ;
+stmt_insert:
+ insert_op T_INTO table T_VALUES T_PARENLEFT value_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_insert* stmt = new Plan_insert(root, $1);
+ root->saveNode(stmt);
+ stmt->setTable($3);
+ stmt->setExprRow($6);
+ $$ = stmt;
+ }
+ |
+ insert_op T_INTO table T_PARENLEFT dml_row T_PARENRIGHT T_VALUES T_PARENLEFT value_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_insert* stmt = new Plan_insert(root, $1);
+ root->saveNode(stmt);
+ stmt->setTable($3);
+ stmt->setDmlRow($5);
+ stmt->setExprRow($9);
+ $$ = stmt;
+ }
+ |
+ insert_op T_INTO table stmt_select
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_insert* stmt = new Plan_insert(root, $1);
+ root->saveNode(stmt);
+ stmt->setTable($3);
+ stmt->setSelect($4);
+ $$ = stmt;
+ }
+ |
+ insert_op T_INTO table T_PARENLEFT dml_row T_PARENRIGHT stmt_select
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_insert* stmt = new Plan_insert(root, $1);
+ root->saveNode(stmt);
+ stmt->setTable($3);
+ stmt->setDmlRow($5);
+ stmt->setSelect($7);
+ $$ = stmt;
+ }
+ |
+ insert_op T_INTO table T_SET set_row
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_insert* stmt = new Plan_insert(root, $1);
+ root->saveNode(stmt);
+ stmt->setTable($3);
+ stmt->setMysqlRow($5);
+ $$ = stmt;
+ }
+ ;
+insert_op:
+ T_INSERT
+ {
+ $$ = Insert_op_insert;
+ }
+ |
+ T_WRITE
+ {
+ $$ = Insert_op_write;
+ }
+ ;
+stmt_update:
+ T_UPDATE table T_SET set_row where_clause
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_update* stmt = new Plan_update(root);
+ root->saveNode(stmt);
+ stmt->setTable($2);
+ stmt->setRow($4);
+ if ($5 != 0)
+ stmt->setPred($5);
+ $$ = stmt;
+ }
+ ;
+stmt_delete:
+ T_DELETE T_FROM table where_clause
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_delete* stmt = new Plan_delete(root);
+ root->saveNode(stmt);
+ stmt->setTable($3);
+ if ($4 != 0)
+ stmt->setPred($4);
+ $$ = stmt;
+ }
+ ;
+create_table:
+ T_CREATE T_TABLE dot_identifier T_PARENLEFT create_row T_PARENRIGHT phys_attr
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_create_table* stmt = new Plan_create_table(root, $3);
+ root->saveNode(stmt);
+ delete[] $3;
+ stmt->setCreateRow($5);
+ if ($7->storage != -1)
+ stmt->setFragmentType((NdbDictionary::Object::FragmentType)$7->storage);
+ if ($7->logging != -1)
+ stmt->setLogging($7->logging);
+ delete $7;
+ $$ = stmt;
+ }
+ ;
+create_row:
+ create_column
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_create_row* createRow = new Plan_create_row(root);
+ root->saveNode(createRow);
+ createRow->addColumn($1);
+ $$ = createRow;
+ }
+ |
+ create_constr
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_create_row* createRow = new Plan_create_row(root);
+ root->saveNode(createRow);
+ createRow->addConstr($1);
+ $$ = createRow;
+ }
+ |
+ create_row T_COMMA create_column
+ {
+ Plan_create_row* createRow = $1;
+ createRow->addColumn($3);
+ $$ = createRow;
+ }
+ |
+ create_row T_COMMA create_constr
+ {
+ Plan_create_row* createRow = $1;
+ createRow->addConstr($3);
+ $$ = createRow;
+ }
+ |
+ create_row T_COMMA create_ignore
+ {
+ $$ = $1;
+ }
+ ;
+create_column:
+ T_IDENTIFIER { pushState(StateType); } data_type { popState(); }
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_ddl_column* ddlColumn = new Plan_ddl_column(root, $1);
+ root->saveNode(ddlColumn);
+ delete[] $1;
+ ddlColumn->setType($3);
+ simpleParser.curr(ddlColumn);
+ }
+ create_column_rest
+ {
+ $$ = simpleParser.curr((Plan_ddl_column*)0);
+ }
+ ;
+data_type:
+ T_CHAR T_PARENLEFT T_LINTEGER T_PARENRIGHT dummy_binary
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(simpleParser.ctx(), SqlType::Char, atoi($3), true);
+ delete[] $3;
+ if (! simpleParser.ctx().ok()) {
+ YYABORT;
+ }
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_BINARY T_PARENLEFT T_LINTEGER T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(simpleParser.ctx(), SqlType::Binary, atoi($3), true);
+ delete[] $3;
+ if (! simpleParser.ctx().ok()) {
+ YYABORT;
+ }
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_VARCHAR T_PARENLEFT T_LINTEGER T_PARENRIGHT dummy_binary
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(simpleParser.ctx(), SqlType::Varchar, atoi($3), true);
+ delete[] $3;
+ if (! simpleParser.ctx().ok()) {
+ YYABORT;
+ }
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_VARBINARY T_PARENLEFT T_LINTEGER T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(simpleParser.ctx(), SqlType::Varbinary, atoi($3), true);
+ delete[] $3;
+ if (! simpleParser.ctx().ok()) {
+ YYABORT;
+ }
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_SMALLINT
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Smallint, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_INTEGER
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Integer, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_INT
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Integer, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_BIGINT
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Bigint, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_REAL
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Real, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_FLOAT
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Double, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_DOUBLE T_PRECISION
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Double, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ T_DATETIME
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType(SqlType::Datetime, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ |
+ blob_type
+ {
+ Plan_root* root = simpleParser.root();
+ SqlType sqlType($1, true);
+ Plan_data_type* dataType = new Plan_data_type(root, sqlType);
+ root->saveNode(dataType);
+ $$ = dataType;
+ }
+ ;
+dummy_binary:
+ /* empty */
+ |
+ T_BINARY
+ ;
+blob_type:
+ T_BLOB
+ {
+ $$ = SqlType::Blob;
+ }
+ |
+ T_LONGBLOB
+ {
+ $$ = SqlType::Blob;
+ }
+ |
+ T_CLOB
+ {
+ $$ = SqlType::Clob;
+ }
+ |
+ T_LONGCLOB
+ {
+ $$ = SqlType::Clob;
+ }
+ ;
+create_column_rest:
+ /* empty */
+ |
+ data_constr_list
+ ;
+data_constr_list:
+ data_constr
+ |
+ data_constr_list data_constr
+ ;
+data_constr:
+ T_NULL
+ |
+ T_NOT T_NULL
+ {
+ Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
+ ddlColumn->setNotNull();
+ }
+ |
+ T_UNSIGNED
+ {
+ Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
+ ddlColumn->setUnSigned();
+ }
+ |
+ T_PRIMARY T_KEY
+ {
+ Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
+ ddlColumn->setPrimaryKey();
+ }
+ |
+ T_AUTO_INCREMENT
+ {
+ Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
+ ddlColumn->setAutoIncrement();
+ }
+ |
+ T_DEFAULT expr
+ {
+ Plan_ddl_column* ddlColumn = simpleParser.curr((Plan_ddl_column*)0);
+ ddlColumn->setDefaultValue($2);
+ }
+ ;
+create_constr:
+ T_PRIMARY T_KEY T_PARENLEFT ddl_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_ddl_constr* ddlConstr = new Plan_ddl_constr(root);
+ root->saveNode(ddlConstr);
+ ddlConstr->setRow($4);
+ $$ = ddlConstr;
+ }
+ |
+ T_CONSTRAINT dot_identifier T_PRIMARY T_KEY T_PARENLEFT ddl_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_ddl_constr* ddlConstr = new Plan_ddl_constr(root);
+ root->saveNode(ddlConstr);
+ ddlConstr->setRow($6);
+ $$ = ddlConstr;
+ }
+ ;
+create_ignore:
+ T_INDEX dot_identifier T_PARENLEFT ddl_row T_PARENRIGHT
+ |
+ T_FOREIGN T_KEY T_PARENLEFT ddl_row T_PARENRIGHT T_REFERENCES dot_identifier T_PARENLEFT ddl_row T_PARENRIGHT
+ ;
+ddl_row:
+ ddl_column
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_ddl_row* ddlRow = new Plan_ddl_row(root);
+ root->saveNode(ddlRow);
+ ddlRow->addColumn($1);
+ $$ = ddlRow;
+ }
+ |
+ ddl_row T_COMMA ddl_column
+ {
+ Plan_ddl_row* ddlRow = $1;
+ ddlRow->addColumn($3);
+ $$ = ddlRow;
+ }
+ ;
+ddl_column:
+ T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_ddl_column* column = new Plan_ddl_column(root, $1);
+ root->saveNode(column);
+ delete[] $1;
+ $$ = column;
+ }
+ ;
+create_index:
+ T_CREATE index_type T_INDEX dot_identifier T_ON table
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_create_index* stmt = new Plan_create_index(root, $4);
+ root->saveNode(stmt);
+ delete[] $4;
+ stmt->setType($2);
+ stmt->setTable($6);
+ simpleParser.curr(stmt);
+ }
+ T_PARENLEFT idx_row T_PARENRIGHT phys_attr
+ {
+ $$ = simpleParser.curr((Plan_create_index*)0);
+ if ($11->storage != -1)
+ $$->setFragmentType((NdbDictionary::Object::FragmentType)$11->storage);
+ if ($11->logging != -1)
+ $$->setLogging($11->logging);
+ delete $11;
+ }
+ ;
+index_type:
+ T_HASH
+ {
+ $$ = NdbDictionary::Object::HashIndex;
+ }
+ |
+ T_UNIQUE T_HASH
+ {
+ $$ = NdbDictionary::Object::UniqueHashIndex;
+ }
+ |
+ /* empty */
+ {
+ $$ = NdbDictionary::Object::OrderedIndex;
+ }
+ |
+ T_UNIQUE
+ {
+ $$ = NdbDictionary::Object::UniqueOrderedIndex;
+ }
+ ;
+idx_row:
+ idx_column
+ {
+ }
+ |
+ idx_row T_COMMA idx_column
+ {
+ }
+ ;
+idx_column:
+ T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_idx_column* column = new Plan_idx_column(root, $1);
+ root->saveNode(column);
+ delete[] $1;
+ Plan_create_index* stmt = simpleParser.curr((Plan_create_index*)0);
+ stmt->addColumn(column);
+ }
+ ;
+phys_attr:
+ { pushState(StatePhys); } phys_attr2 { popState(); }
+ {
+ $$ = $2;
+ }
+ ;
+phys_attr2:
+ /* empty */
+ {
+ $$ = new PhysAttr();
+ $$->storage = $$->logging = -1;
+ }
+ |
+ phys_attr2 storage_attr
+ {
+ if ($1->storage != -1 && $1->storage != $2) {
+ simpleParser.ctx().pushStatus(Sqlstate::_42000, Error::Gen, "conflicting STORAGE clauses");
+ YYABORT;
+ }
+ $$->storage = $2;
+ }
+ |
+ phys_attr2 logging_attr
+ {
+ if ($1->logging != -1 && $1->logging != $2) {
+ simpleParser.ctx().pushStatus(Sqlstate::_42000, Error::Gen, "conflicting LOGGING clauses");
+ YYABORT;
+ }
+ $$->logging = $2;
+ }
+ ;
+logging_attr:
+ T_LOGGING
+ {
+ $$ = true;
+ }
+ |
+ T_NOLOGGING
+ {
+ $$ = false;
+ }
+ ;
+storage_attr:
+ T_STORAGE T_PARENLEFT T_SINGLE T_PARENRIGHT
+ {
+ $$ = NdbDictionary::Object::FragSingle;
+ }
+ |
+ T_STORAGE T_PARENLEFT T_SMALL T_PARENRIGHT
+ {
+ $$ = NdbDictionary::Object::FragAllSmall;
+ }
+ |
+ T_STORAGE T_PARENLEFT T_MEDIUM T_PARENRIGHT
+ {
+ $$ = NdbDictionary::Object::FragAllMedium;
+ }
+ |
+ T_STORAGE T_PARENLEFT T_LARGE T_PARENRIGHT
+ {
+ $$ = NdbDictionary::Object::FragAllLarge;
+ }
+ ;
+drop_table:
+ T_DROP T_TABLE dot_identifier
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_drop_table* stmt = new Plan_drop_table(root, $3);
+ root->saveNode(stmt);
+ delete[] $3;
+ $$ = stmt;
+ }
+ ;
+drop_index:
+ T_DROP T_INDEX dot_identifier
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_drop_index* stmt = new Plan_drop_index(root, $3);
+ root->saveNode(stmt);
+ delete[] $3;
+ $$ = stmt;
+ }
+ |
+ T_DROP T_INDEX dot_identifier T_ON dot_identifier
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_drop_index* stmt = new Plan_drop_index(root, $3, $5);
+ root->saveNode(stmt);
+ delete[] $3;
+ delete[] $5;
+ $$ = stmt;
+ }
+ ;
+distinct_clause:
+ /* empty */
+ {
+ $$ = false;
+ }
+ |
+ T_DISTINCT
+ {
+ $$ = true;
+ }
+ ;
+where_clause:
+ /* empty */
+ {
+ $$ = 0;
+ }
+ |
+ T_WHERE pred
+ {
+ $$ = $2;
+ }
+ ;
+group_clause:
+ /* empty */
+ {
+ $$ = 0;
+ }
+ |
+ T_GROUP T_BY value_row
+ {
+ $$ = $3;
+ }
+ ;
+having_clause:
+ /* empty */
+ {
+ $$ = 0;
+ }
+ |
+ T_HAVING pred
+ {
+ $$ = $2;
+ }
+ ;
+order_clause:
+ /* empty */
+ {
+ $$ = 0;
+ }
+ |
+ T_ORDER T_BY sort_row
+ {
+ $$ = $3;
+ }
+ ;
+limit_clause:
+ /* empty */
+ {
+ $$ = 0;
+ }
+ |
+ T_LIMIT signed_integer
+ {
+ LimitPair* p = new LimitPair;
+ p->off = 0;
+ p->cnt = $2;
+ $$ = p;
+ }
+ |
+ T_LIMIT signed_integer T_COMMA signed_integer
+ {
+ LimitPair* p = new LimitPair;
+ p->off = $2,
+ p->cnt = $4;
+ $$ = p;
+ }
+ |
+ T_LIMIT signed_integer T_OFFSET signed_integer
+ {
+ LimitPair* p = new LimitPair;
+ p->off = $4;
+ p->cnt = $2;
+ $$ = p;
+ }
+ ;
+signed_integer:
+ T_LINTEGER
+ {
+ $$ = atoi($1);
+ delete[] $1;
+ }
+ |
+ T_MINUS T_LINTEGER
+ {
+ $$ = (-1) * atoi($2);
+ delete[] $2;
+ }
+ ;
+set_row:
+ dml_column T_ASSIGN expr
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_set_row* row = new Plan_set_row(root);
+ root->saveNode(row);
+ row->addColumn($1);
+ row->addExpr($3);
+ $$ = row;
+ }
+ |
+ set_row T_COMMA dml_column T_ASSIGN expr
+ {
+ Plan_set_row* row = $1;
+ row->addColumn($3);
+ row->addExpr($5);
+ $$ = row;
+ }
+ ;
+dml_row:
+ dml_column
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_dml_row* row = new Plan_dml_row(root);
+ root->saveNode(row);
+ row->addColumn($1);
+ $$ = row;
+ }
+ |
+ dml_row T_COMMA dml_column
+ {
+ Plan_dml_row* row = $1;
+ row->addColumn($3);
+ $$ = row;
+ }
+ ;
+dml_column:
+ T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_dml_column* column = new Plan_dml_column(root, $1);
+ root->saveNode(column);
+ delete[] $1;
+ $$ = column;
+ }
+ ;
+value_row:
+ value_expr
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_row* row = new Plan_expr_row(root);
+ root->saveNode(row);
+ row->addExpr($1);
+ $$ = row;
+ }
+ |
+ value_row T_COMMA value_expr
+ {
+ Plan_expr_row* row = $1;
+ row->addExpr($3);
+ $$ = row;
+ }
+ ;
+value_expr:
+ expr
+ {
+ $$ = $1;
+ }
+ ;
+sort_row:
+ expr asc_desc
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_row* row = new Plan_expr_row(root);
+ root->saveNode(row);
+ row->addExpr($1, $2);
+ $$ = row;
+ }
+ |
+ sort_row T_COMMA expr asc_desc
+ {
+ Plan_expr_row* row = $1;
+ row->addExpr($3, $4);
+ $$ = row;
+ }
+ ;
+asc_desc:
+ /* empty */
+ {
+ $$ = true;
+ }
+ |
+ T_ASC
+ {
+ $$ = true;
+ }
+ |
+ T_DESC
+ {
+ $$ = false;
+ }
+ ;
+expr_row:
+ T_ASTERISK
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_row* row = new Plan_expr_row(root);
+ root->saveNode(row);
+ row->setAsterisk();
+ $$ = row;
+ }
+ |
+ T_TIMES /* XXX fix scanner state */
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_row* row = new Plan_expr_row(root);
+ root->saveNode(row);
+ row->setAsterisk();
+ $$ = row;
+ }
+ |
+ expr
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_row* row = new Plan_expr_row(root);
+ root->saveNode(row);
+ row->addExpr($1);
+ $$ = row;
+ }
+ |
+ expr T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_row* row = new Plan_expr_row(root);
+ root->saveNode(row);
+ row->addExpr($1, BaseString($2));
+ $$ = row;
+ }
+ |
+ expr_row T_COMMA expr
+ {
+ Plan_expr_row* row = $1;
+ row->addExpr($3);
+ $$ = row;
+ }
+ |
+ expr_row T_COMMA expr T_IDENTIFIER
+ {
+ Plan_expr_row* row = $1;
+ row->addExpr($3, BaseString($4));
+ $$ = row;
+ }
+ ;
+pred:
+ { pushState(StateEval); } pred1 { popState(); }
+ {
+ $$ = $2;
+ }
+ ;
+pred1:
+ pred2
+ {
+ $$ = $1;
+ }
+ |
+ pred1 pred1_op pred2
+ {
+ Plan_root* root = simpleParser.root();
+ Pred_op op($2);
+ Plan_pred_op* pred = new Plan_pred_op(root, op);
+ root->saveNode(pred);
+ pred->setPred(1, $1);
+ pred->setPred(2, $3);
+ $$ = pred;
+ }
+ ;
+pred1_op:
+ T_OR
+ {
+ $$ = Pred_op::Or;
+ }
+ ;
+pred2:
+ pred3
+ {
+ $$ = $1;
+ }
+ |
+ pred2 pred2_op pred3
+ {
+ Plan_root* root = simpleParser.root();
+ Pred_op op($2);
+ Plan_pred_op* pred = new Plan_pred_op(root, op);
+ root->saveNode(pred);
+ pred->setPred(1, $1);
+ pred->setPred(2, $3);
+ $$ = pred;
+ }
+ ;
+pred2_op:
+ T_AND
+ {
+ $$ = Pred_op::And;
+ }
+ ;
+pred3:
+ pred4
+ {
+ $$ = $1;
+ }
+ |
+ pred3_op pred3
+ {
+ Plan_root* root = simpleParser.root();
+ Pred_op op($1);
+ Plan_pred_op* pred = new Plan_pred_op(root, op);
+ root->saveNode(pred);
+ pred->setPred(1, $2);
+ $$ = pred;
+ }
+ ;
+pred3_op:
+ T_NOT
+ {
+ $$ = Pred_op::Not;
+ }
+ ;
+pred4:
+ T_PARENLEFT pred1 T_PARENRIGHT
+ {
+ $$ = $2;
+ }
+ |
+ expr1 comp_op expr1
+ {
+ Plan_root* root = simpleParser.root();
+ Comp_op op($2);
+ Plan_comp_op* comp = new Plan_comp_op(root, op);
+ root->saveNode(comp);
+ comp->setExpr(1, $1);
+ comp->setExpr(2, $3);
+ $$ = comp;
+ }
+ |
+ expr1 T_IS T_NULL
+ {
+ Plan_root* root = simpleParser.root();
+ Comp_op op(Comp_op::Isnull);
+ Plan_comp_op* comp = new Plan_comp_op(root, op);
+ root->saveNode(comp);
+ comp->setExpr(1, $1);
+ $$ = comp;
+ }
+ |
+ expr1 T_IS T_NOT T_NULL
+ {
+ Plan_root* root = simpleParser.root();
+ Comp_op op(Comp_op::Isnotnull);
+ Plan_comp_op* comp = new Plan_comp_op(root, op);
+ root->saveNode(comp);
+ comp->setExpr(1, $1);
+ $$ = comp;
+ }
+ |
+ expr1 T_IN T_PARENLEFT value_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_pred* predOut = 0; // hack directly into Or of Eq
+ Plan_expr* exprLeft = $1;
+ Plan_expr_row* row = $4;
+ for (unsigned i = row->getSize(); i >= 1; i--) {
+ Plan_expr* exprRight = row->getExpr(i);
+ Plan_comp_op* comp = new Plan_comp_op(root, Comp_op::Eq);
+ root->saveNode(comp);
+ comp->setExpr(1, exprLeft);
+ comp->setExpr(2, exprRight);
+ if (predOut == 0) {
+ predOut = comp;
+ } else {
+ Plan_pred_op* pred = new Plan_pred_op(root, Pred_op::Or);
+ root->saveNode(pred);
+ pred->setPred(1, predOut);
+ pred->setPred(2, comp);
+ predOut = pred;
+ }
+ }
+ $$ = predOut;
+ }
+ |
+ expr1 T_NOT T_IN T_PARENLEFT value_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_pred* predOut = 0; // hack directly into And of Noteq
+ Plan_expr* exprLeft = $1;
+ Plan_expr_row* row = $5;
+ for (unsigned i = row->getSize(); i >= 1; i--) {
+ Plan_expr* exprRight = row->getExpr(i);
+ Plan_comp_op* comp = new Plan_comp_op(root, Comp_op::Noteq);
+ root->saveNode(comp);
+ comp->setExpr(1, exprLeft);
+ comp->setExpr(2, exprRight);
+ if (predOut == 0) {
+ predOut = comp;
+ } else {
+ Plan_pred_op* pred = new Plan_pred_op(root, Pred_op::And);
+ root->saveNode(pred);
+ pred->setPred(1, predOut);
+ pred->setPred(2, comp);
+ predOut = pred;
+ }
+ }
+ $$ = predOut;
+ }
+ ;
+comp_op:
+ T_EQ
+ {
+ $$ = Comp_op::Eq;
+ }
+ |
+ T_NOTEQ
+ {
+ $$ = Comp_op::Noteq;
+ }
+ |
+ T_LT
+ {
+ $$ = Comp_op::Lt;
+ }
+ |
+ T_LTEQ
+ {
+ $$ = Comp_op::Lteq;
+ }
+ |
+ T_GT
+ {
+ $$ = Comp_op::Gt;
+ }
+ |
+ T_GTEQ
+ {
+ $$ = Comp_op::Gteq;
+ }
+ |
+ T_LIKE
+ {
+ $$ = Comp_op::Like;
+ }
+ |
+ T_NOT T_LIKE
+ {
+ $$ = Comp_op::Notlike;
+ }
+ ;
+expr:
+ { pushState(StateEval); } expr1 { popState(); }
+ {
+ $$ = $2;
+ }
+ ;
+expr1:
+ expr2
+ {
+ $$ = $1;
+ }
+ |
+ expr1 expr1_op expr2
+ {
+ Plan_root* root = simpleParser.root();
+ Expr_op op($2);
+ Plan_expr_op* expr = new Plan_expr_op(root, op);
+ root->saveNode(expr);
+ expr->setExpr(1, $1);
+ expr->setExpr(2, $3);
+ $$ = expr;
+ }
+ ;
+expr1_op:
+ T_PLUS
+ {
+ $$ = Expr_op::Add;
+ }
+ |
+ T_MINUS
+ {
+ $$ = Expr_op::Subtract;
+ }
+ ;
+expr2:
+ expr3
+ {
+ $$ = $1;
+ }
+ |
+ expr2 expr2_op expr3
+ {
+ Plan_root* root = simpleParser.root();
+ Expr_op op($2);
+ Plan_expr_op* expr = new Plan_expr_op(root, op);
+ root->saveNode(expr);
+ expr->setExpr(1, $1);
+ expr->setExpr(2, $3);
+ $$ = expr;
+ }
+ ;
+expr2_op:
+ T_TIMES
+ {
+ $$ = Expr_op::Multiply;
+ }
+ |
+ T_DIVIDE
+ {
+ $$ = Expr_op::Divide;
+ }
+ ;
+expr3:
+ expr4
+ {
+ $$ = $1;
+ }
+ |
+ expr3_op expr3
+ {
+ Plan_root* root = simpleParser.root();
+ Expr_op op($1);
+ Plan_expr_op* expr = new Plan_expr_op(root, op);
+ root->saveNode(expr);
+ expr->setExpr(1, $2);
+ $$ = expr;
+ }
+ ;
+expr3_op:
+ T_PLUS
+ {
+ $$ = Expr_op::Plus;
+ }
+ |
+ T_MINUS
+ {
+ $$ = Expr_op::Minus;
+ }
+ ;
+expr4:
+ T_PARENLEFT expr1 T_PARENRIGHT
+ {
+ $$ = $2;
+ }
+ |
+ T_IDENTIFIER T_PARENLEFT expr_row T_PARENRIGHT
+ {
+ Plan_root* root = simpleParser.root();
+ const Expr_func& spec = Expr_func::find($1);
+ if (spec.m_name == 0) {
+ simpleParser.ctx().pushStatus(Sqlstate::_42000, Error::Gen, "unknown function %s", $1);
+ delete[] $1;
+ YYABORT;
+ }
+ Plan_expr_func* func = new Plan_expr_func(root, spec);
+ root->saveNode(func);
+ delete[] $1;
+ func->setArgs($3);
+ $$ = func;
+ }
+ |
+ T_ROWNUM
+ {
+ Plan_root* root = simpleParser.root();
+ const Expr_func& spec = Expr_func::find("ROWNUM");
+ ctx_assert(spec.m_name != 0);
+ Plan_expr_func* func = new Plan_expr_func(root, spec);
+ root->saveNode(func);
+ func->setArgs(0);
+ $$ = func;
+ }
+ |
+ T_SYSDATE
+ {
+ Plan_root* root = simpleParser.root();
+ const Expr_func& spec = Expr_func::find("SYSDATE");
+ ctx_assert(spec.m_name != 0);
+ Plan_expr_func* func = new Plan_expr_func(root, spec);
+ root->saveNode(func);
+ func->setArgs(0);
+ $$ = func;
+ }
+ |
+ expr_column
+ {
+ $$ = $1;
+ }
+ |
+ T_STRING
+ {
+ Plan_root* root = simpleParser.root();
+ LexType lexType(LexType::Char);
+ Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1);
+ root->saveNode(expr);
+ delete[] $1;
+ $$ = expr;
+ }
+ |
+ T_LINTEGER
+ {
+ Plan_root* root = simpleParser.root();
+ LexType lexType(LexType::Integer);
+ Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1);
+ root->saveNode(expr);
+ delete[] $1;
+ $$ = expr;
+ }
+ |
+ T_LDECIMAL
+ {
+ Plan_root* root = simpleParser.root();
+ LexType lexType(LexType::Float);
+ Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1);
+ root->saveNode(expr);
+ delete[] $1;
+ $$ = expr;
+ }
+ |
+ T_LREAL
+ {
+ Plan_root* root = simpleParser.root();
+ LexType lexType(LexType::Float);
+ Plan_expr_const* expr = new Plan_expr_const(root, lexType, $1);
+ root->saveNode(expr);
+ delete[] $1;
+ $$ = expr;
+ }
+ |
+ T_NULL
+ {
+ Plan_root* root = simpleParser.root();
+ LexType lexType(LexType::Null);
+ Plan_expr_const* expr = new Plan_expr_const(root, lexType, "");
+ root->saveNode(expr);
+ $$ = expr;
+ }
+ |
+ T_QUES
+ {
+ Plan_root* root = simpleParser.root();
+ unsigned paramNumber = simpleParser.paramNumber();
+ ctx_assert(paramNumber != 0);
+ Plan_expr_param* expr = new Plan_expr_param(root, paramNumber);
+ root->saveNode(expr);
+ $$ = expr;
+ }
+ ;
+expr_column:
+ T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_column* column = new Plan_expr_column(root, $1);
+ root->saveNode(column);
+ delete[] $1;
+ $$ = column;
+ }
+ |
+ T_IDENTIFIER T_PERIOD T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_expr_column* column = new Plan_expr_column(root, $3);
+ root->saveNode(column);
+ delete[] $3;
+ column->setCname($1);
+ $$ = column;
+ }
+ |
+ T_IDENTIFIER T_PERIOD T_IDENTIFIER T_PERIOD T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ BaseString str;
+ str.append($1);
+ str.append(".");
+ str.append($3);
+ delete[] $1;
+ delete[] $3;
+ Plan_expr_column* column = new Plan_expr_column(root, $5);
+ root->saveNode(column);
+ delete[] $5;
+ column->setCname(str);
+ $$ = column;
+ }
+ ;
+table_list:
+ table
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_table_list* tableList = new Plan_table_list(root);
+ root->saveNode(tableList);
+ tableList->addTable($1);
+ $$ = tableList;
+ }
+ |
+ table_list T_COMMA table
+ {
+ Plan_table_list* tableList = $1;
+ tableList->addTable($3);
+ $$ = tableList;
+ }
+ ;
+table:
+ dot_identifier
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_table* table = new Plan_table(root, $1);
+ root->saveNode(table);
+ delete[] $1;
+ $$ = table;
+ }
+ |
+ dot_identifier T_IDENTIFIER
+ {
+ Plan_root* root = simpleParser.root();
+ Plan_table* table = new Plan_table(root, $1);
+ root->saveNode(table);
+ delete[] $1;
+ table->setCname($2);
+ delete[] $2;
+ $$ = table;
+ }
+ ;
+dot_identifier:
+ T_IDENTIFIER
+ {
+ $$ = $1;
+ }
+ |
+ T_IDENTIFIER T_PERIOD T_IDENTIFIER
+ {
+ char* s = new char[strlen($1) + 1 + strlen($3) + 1];
+ strcpy(s, $1);
+ strcat(s, ".");
+ strcat(s, $3);
+ delete[] $1;
+ delete[] $3;
+ $$ = s;
+ }
+ ;
+
+%%
+
+static int
+yylex(YYSTYPE* lvalp, void* simpleParserPtr)
+{
+ int ret = simpleParser.yylex();
+ *lvalp = simpleParser.yylval();
+ return ret;
+}
+
+/* vim: set filetype=yacc: */
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/SimpleParser.cpp b/storage/ndb/src/old_files/client/odbc/codegen/SimpleParser.cpp
new file mode 100644
index 00000000000..a2418f49e37
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/SimpleParser.cpp
@@ -0,0 +1,96 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <common/common.hpp>
+#include <NdbMutex.h>
+#include <common/StmtArea.hpp>
+#include <FlexLexer.h>
+#include "SimpleParser.hpp"
+
+SimpleParser::~SimpleParser()
+{
+}
+
+#ifdef NDB_WIN32
+static NdbMutex & parse_mutex = * NdbMutex_Create();
+#else
+static NdbMutex parse_mutex = NDB_MUTEX_INITIALIZER;
+#endif
+
+void
+SimpleParser::yyparse()
+{
+ Ctx& ctx = this->ctx();
+ NdbMutex_Lock(&parse_mutex);
+ ctx_log2(("parse: %s", stmtArea().sqlText().c_str()));
+#if YYDEBUG
+ SimpleParser_yydebug = (m_ctx.logLevel() >= 5);
+#endif
+ SimpleParser_yyparse((void*)this);
+ NdbMutex_Unlock(&parse_mutex);
+}
+
+void
+SimpleParser::pushState(int sc)
+{
+ yy_push_state(sc);
+ m_stacksize++;
+}
+
+void
+SimpleParser::popState()
+{
+ ctx_assert(m_stacksize > 0);
+ yy_pop_state();
+ m_stacksize--;
+}
+
+void
+SimpleParser::parseError(const char* msg)
+{
+ ctx().pushStatus(Sqlstate::_42000, Error::Gen, "%s at '%*s' position %u", msg, yyleng, yytext, m_parsePos - yyleng);
+}
+
+int
+SimpleParser::LexerInput(char* buf, int max_size)
+{
+ const BaseString& text = stmtArea().sqlText();
+ int n = 0;
+ const char* const t = text.c_str();
+ const unsigned m = text.length();
+ while (n < max_size && m_textPos < m) {
+ buf[n++] = t[m_textPos++];
+ m_parsePos++; // XXX simple hack
+ break;
+ }
+ return n;
+}
+
+// XXX just a catch-all (scanner should match all input)
+void
+SimpleParser::LexerOutput(const char* buf, int size)
+{
+ if (! ctx().ok())
+ return;
+ const char* msg = "unrecognized input";
+ ctx().pushStatus(Sqlstate::_42000, Error::Gen, "%s at '%*s' position %u", msg, size, buf, m_parsePos);
+}
+
+void
+SimpleParser::LexerError(const char* msg)
+{
+ ctx().pushStatus(Sqlstate::_42000, Error::Gen, "%s at '%*s' position %u", msg, yyleng, yytext, m_parsePos);
+}
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/SimpleParser.hpp b/storage/ndb/src/old_files/client/odbc/codegen/SimpleParser.hpp
new file mode 100644
index 00000000000..abadae8f905
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/SimpleParser.hpp
@@ -0,0 +1,161 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef ODBC_CODEGEN_SimpleParser_hpp
+#define ODBC_CODEGEN_SimpleParser_hpp
+
+#include <common/common.hpp>
+#include "Code_root.hpp"
+#include "Code_stmt.hpp"
+#include "Code_select.hpp"
+#include "Code_pred.hpp"
+#include "Code_pred_op.hpp"
+#include "Code_comp_op.hpp"
+#include "Code_expr_row.hpp"
+#include "Code_expr.hpp"
+#include "Code_expr_op.hpp"
+#include "Code_expr_func.hpp"
+#include "Code_expr_column.hpp"
+#include "Code_expr_const.hpp"
+#include "Code_expr_param.hpp"
+#include "Code_update.hpp"
+#include "Code_set_row.hpp"
+#include "Code_insert.hpp"
+#include "Code_dml_row.hpp"
+#include "Code_dml_column.hpp"
+#include "Code_delete.hpp"
+#include "Code_table_list.hpp"
+#include "Code_table.hpp"
+#include "Code_create_table.hpp"
+#include "Code_create_index.hpp"
+#include "Code_ddl_row.hpp"
+#include "Code_ddl_column.hpp"
+#include "Code_ddl_constr.hpp"
+#include "Code_data_type.hpp"
+#include "Code_drop_table.hpp"
+#include "Code_drop_index.hpp"
+
+#include "SimpleGram.tab.hpp"
+
+class StmtArea;
+class Plan_root;
+
+class SimpleParser : public yyFlexLexer {
+public:
+ SimpleParser(Ctx& ctx, StmtArea& stmtArea, Plan_root* root);
+ ~SimpleParser();
+ Ctx& ctx();
+ StmtArea& stmtArea();
+ Plan_root* root();
+ void yyparse(); // calls real yyparse
+ int yylex(); // generated by flex
+ YYSTYPE yylval();
+ void pushState(int sc); // push start condition
+ void popState(); // pop start condition
+ unsigned paramNumber() const;
+ void parseError(const char* msg);
+ // parser helpers - to avoid creating new Plan tree types
+ Plan_ddl_column* curr(Plan_ddl_column* p);
+ Plan_create_index* curr(Plan_create_index* p);
+protected:
+ virtual int LexerInput(char* buf, int max_size);
+ virtual void LexerOutput(const char* buf, int size);
+ virtual void LexerError(const char* msg);
+private:
+ Ctx& m_ctx;
+ StmtArea& m_stmtArea;
+ Plan_root* const m_root;
+ unsigned m_textPos; // position in sql text
+ unsigned m_parsePos; // parse position, to report error
+ YYSTYPE m_yylval; // token value
+ BaseString m_string; // storage for edited string token
+ unsigned m_stacksize; // state stack size
+ unsigned m_paramNumber; // parameter number
+ // parser helpers
+ Plan_ddl_column* m_ddl_column;
+ Plan_create_index* m_create_index;
+};
+
+extern int SimpleParser_yyparse(void* simpleParserPtr);
+#if YYDEBUG
+extern int SimpleParser_yydebug;
+#endif
+
+inline
+SimpleParser::SimpleParser(Ctx& ctx, StmtArea& stmtArea, Plan_root* root) :
+ m_ctx(ctx),
+ m_stmtArea(stmtArea),
+ m_root(root),
+ m_textPos(0),
+ m_parsePos(0),
+ m_stacksize(0),
+ m_paramNumber(0),
+ // parser helpers
+ m_ddl_column(0)
+{
+}
+
+inline Ctx&
+SimpleParser::ctx()
+{
+ return m_ctx;
+}
+
+inline StmtArea&
+SimpleParser::stmtArea()
+{
+ return m_stmtArea;
+}
+
+inline Plan_root*
+SimpleParser::root()
+{
+ return m_root;
+}
+
+inline YYSTYPE
+SimpleParser::yylval()
+{
+ return m_yylval;
+}
+
+inline unsigned
+SimpleParser::paramNumber() const
+{
+ return m_paramNumber;
+}
+
+// parser helpers
+
+inline Plan_ddl_column*
+SimpleParser::curr(Plan_ddl_column* p)
+{
+ if (p != 0)
+ m_ddl_column = p;
+ ctx_assert(m_ddl_column != 0);
+ return m_ddl_column;
+}
+
+inline Plan_create_index*
+SimpleParser::curr(Plan_create_index* p)
+{
+ if (p != 0)
+ m_create_index = p;
+ ctx_assert(m_create_index != 0);
+ return m_create_index;
+}
+
+#endif
diff --git a/storage/ndb/src/old_files/client/odbc/codegen/SimpleScan.lpp b/storage/ndb/src/old_files/client/odbc/codegen/SimpleScan.lpp
new file mode 100644
index 00000000000..29aa876f669
--- /dev/null
+++ b/storage/ndb/src/old_files/client/odbc/codegen/SimpleScan.lpp
@@ -0,0 +1,243 @@
+%{
+#include <ctype.h>
+#include "SimpleParser.hpp"
+
+struct SqlKeyword {
+ const char* m_name;
+ int m_value;
+ int m_state;
+ static const SqlKeyword* find(Ctx& ctx, const char* name, int state);
+};
+
+%}
+
+%option c++
+%option yyclass="SimpleParser"
+%option stack
+%option noyywrap
+
+space [\040\t\n\r\f]
+digit [0-9]
+letter [A-Za-z_]
+special ("$")
+identifier ({letter}({letter}|{digit}|{special})*)
+integer {digit}++
+decimal (({digit}*\.{digit}+)|({digit}+\.{digit}*))
+real ((({digit}*\.{digit}+)|({digit}+\.{digit}*)|({digit}+))([Ee][-+]?{digit}+))
+
+%s StateEval
+%s StateType
+%s StatePhys
+%x StateString
+%x StateQuoted
+
+%%
+
+{space} {
+ }
+{identifier} {
+ const SqlKeyword* key = SqlKeyword::find(m_ctx, (char*)yytext, YYSTATE);
+ if (key != 0)
+ return key->m_value;
+ for (unsigned char* a = (unsigned char*)yytext; *a != 0; a++) {
+ if (islower(*a))
+ *a = toupper(*a);
+ }
+ m_yylval.m_string = strcpy(new char[yyleng + 1], yytext);
+ return T_IDENTIFIER;
+ }
+{integer} {
+ m_yylval.m_string = strcpy(new char[yyleng + 1], yytext);
+ return T_LINTEGER;
+ }
+{decimal} {
+ m_yylval.m_string = strcpy(new char[yyleng + 1], yytext);
+ return T_LDECIMAL;
+ }
+{real} {
+ m_yylval.m_string = strcpy(new char[yyleng + 1], yytext);
+ return T_LREAL;
+ }
+"--".* {
+ }
+"/*" {
+ int c = 0, d;
+ while (1) {
+ d = c;
+ if ((c = yyinput()) == EOF) {
+ parseError("unterminated comment");
+ yyterminate();
+ }
+ if (d == '*' && c == '/')
+ break;
+ }
+ }
+<StateEval>{
+"+" return T_PLUS;
+"-" return T_MINUS;
+"*" return T_TIMES;
+"/" return T_DIVIDE;
+"=" return T_EQ;
+"!=" return T_NOTEQ;
+"^=" return T_NOTEQ;
+"<>" return T_NOTEQ;
+"<" return T_LT;
+"<=" return T_LTEQ;
+">" return T_GT;
+">=" return T_GTEQ;
+"?" m_paramNumber++; return T_QUES;
+}
+
+"." return T_PERIOD;
+"," return T_COMMA;
+"(" return T_PARENLEFT;
+")" return T_PARENRIGHT;
+"*" return T_ASTERISK;
+"=" return T_ASSIGN;
+
+"'" {
+ pushState(StateString);
+ m_string.assign("");
+ }
+<StateString>{
+[^']* {
+ m_string.append(yytext);
+ }
+"''" {
+ m_string.append("'");
+ }
+"'" {
+ m_yylval.m_string = strcpy(new char[m_string.length() + 1], m_string.c_str());
+ popState();
+ return T_STRING;
+ }
+}
+
+\" {
+ pushState(StateQuoted);
+ m_string.assign("");
+ }
+<StateQuoted>{
+[^"]* {
+ m_string.append(yytext);
+ }
+\\\" {
+ m_string.append("\"");
+ }
+\" {
+ m_yylval.m_string = strcpy(new char[m_string.length() + 1], m_string.c_str());
+ popState();
+ return T_IDENTIFIER;
+ }
+}
+
+%%
+
+// scan states
+int SimpleParser_stateEval = StateEval;
+int SimpleParser_stateType = StateType;
+int SimpleParser_statePhys = StatePhys;
+
+// keep sorted
+
+static const SqlKeyword sqlKeyword[] = {
+ { "AND", T_AND, -1 },
+ { "ASC", T_ASC, -1 },
+ { "AUTO_INCREMENT", T_AUTO_INCREMENT, -1 },
+ { "BIGINT", T_BIGINT, StateType },
+ { "BINARY", T_BINARY, StateType },
+ { "BLOB", T_BLOB, StateType },
+ { "BY", T_BY, -1 },
+ { "CHAR", T_CHAR, StateType },
+ { "CLOB", T_CLOB, StateType },
+ { "CONSTRAINT", T_CONSTRAINT, -1 },
+ { "CREATE", T_CREATE, -1 },
+ { "DATETIME", T_DATETIME, StateType },
+ { "DEFAULT", T_DEFAULT, -1 },
+ { "DELETE", T_DELETE, -1 },
+ { "DESC", T_DESC, -1 },
+ { "DISTINCT", T_DISTINCT, -1 },
+ { "DOUBLE", T_DOUBLE, StateType },
+ { "DROP", T_DROP, -1 },
+ { "FLOAT", T_FLOAT, StateType },
+ { "FOREIGN", T_FOREIGN, -1 },
+ { "FROM", T_FROM, -1 },
+ { "GROUP", T_GROUP, -1 },
+ { "HASH", T_HASH, -1 },
+ { "HAVING", T_HAVING, -1 },
+ { "IN", T_IN, -1 },
+ { "INDEX", T_INDEX, -1 },
+ { "INSERT", T_INSERT, -1 },
+ { "INT", T_INT, StateType },
+ { "INTEGER", T_INTEGER, StateType },
+ { "INTO", T_INTO, -1 },
+ { "IS", T_IS, -1 },
+ { "KEY", T_KEY, -1 },
+ { "LARGE", T_LARGE, StatePhys },
+ { "LIKE", T_LIKE, -1 },
+ { "LIMIT", T_LIMIT, -1 },
+ { "LOGGING", T_LOGGING, StatePhys },
+ { "LONGBLOB", T_LONGBLOB, StateType },
+ { "LONGCLOB", T_LONGCLOB, StateType },
+ { "MEDIUM", T_MEDIUM, StatePhys },
+ { "NOLOGGING", T_NOLOGGING, StatePhys },
+ { "NOT", T_NOT, -1 },
+ { "NULL", T_NULL, -1 },
+ { "OFFSET", T_OFFSET, -1 },
+ { "ON", T_ON, -1 },
+ { "OR", T_OR, -1 },
+ { "ORDER", T_ORDER, -1 },
+ { "PRECISION", T_PRECISION, StateType },
+ { "PRIMARY", T_PRIMARY, -1 },
+ { "REAL", T_REAL, StateType },
+ { "REFERENCES", T_REFERENCES, -1 },
+ { "ROWNUM", T_ROWNUM, -1 },
+ { "SELECT", T_SELECT, -1 },
+ { "SET", T_SET, -1 },
+ { "SINGLE", T_SINGLE, StatePhys },
+ { "SMALL", T_SMALL, StatePhys },
+ { "SMALLINT", T_SMALLINT, StateType },
+ { "STORAGE", T_STORAGE, StatePhys },
+ { "SYSDATE", T_SYSDATE, -1 },
+ { "TABLE", T_TABLE, -1 },
+ { "UNIQUE", T_UNIQUE, -1 },
+ { "UNSIGNED", T_UNSIGNED, -1 },
+ { "UPDATE", T_UPDATE, -1 },
+ { "VALUES", T_VALUES, -1 },
+ { "VARBINARY", T_VARBINARY, StateType },
+ { "VARCHAR", T_VARCHAR, StateType },
+ { "WHERE", T_WHERE, -1 },
+ { "WRITE", T_WRITE, -1 }
+};
+
+static const unsigned sqlKeywordCount = sizeof(sqlKeyword) / sizeof(sqlKeyword[0]);
+
+const SqlKeyword*
+SqlKeyword::find(Ctx& ctx, const char* name, int state)
+{
+ ctx_log4(("find keyword '%s' lex state = %d", name, state));
+ const unsigned maxlen = 99;
+ char buf[maxlen + 1];
+ char* a = buf;
+ const char* b = name;
+ while (*b != 0) {
+ if (a >= buf + maxlen) // will not be found
+ break;
+ char c = *b++;
+ if ('a' <= c && c <= 'z') // locale independent
+ c -= 'a' - 'A';
+ *a++ = c;
+ }
+ *a = 0;
+ for (unsigned i = 0; i < sqlKeywordCount; i++) {
+ const SqlKeyword* key = &sqlKeyword[i];
+ if (strcmp(key->m_name, buf) == 0) {
+ if (key->m_state != -1 && key->m_state != state)
+ return 0;
+ return key;
+ }
+ }
+ return 0;
+}
+
+/* vim: set filetype=lex: */