~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/plugin/table_function.cc

  • Committer: Stewart Smith
  • Date: 2010-08-12 16:48:46 UTC
  • mto: This revision was merged to the branch mainline in revision 1707.
  • Revision ID: stewart@flamingspork.com-20100812164846-s9bhy47g60bvqs41
bug lp:611379 Equivalent queries with Impossible where return different results

The following two equivalent queries return different results in maria 5.2 and 5.3 (and identical results in mysql 5.5.5) :

SELECT SUM( DISTINCT table1 .`pk` ) FROM B table1 STRAIGHT_JOIN ( BB table2 JOIN CC ON table2 .`col_varchar_key` ) ON table2 .`pk` ;

SELECT * FROM ( SELECT SUM( DISTINCT table1 .`pk` ) FROM B table1 STRAIGHT_JOIN ( BB table2 JOIN CC ON table2 .`col_varchar_key` ) ON table2 .`pk` );

MariaDB returns 0 on the second query and NULL on the first, whereas MySQL returns NULL on both. In MariaDB, both EXPLAIN plans agree that "Impossible WHERE noticed after reading const tables"



We have some slightly different output in drizzle:

main.bug_lp611379 [ fail ]
drizzletest: At line 9: query 'explain select * from (select sum(distinct t1.a) from t1,t2 where t1.a=t2.a)
as t' failed: 1048: Column 'sum(distinct t1.a)' cannot be null

but the fix gets us the correct query results, although with slightly different execution plans.



This fix is directly ported from MariaDB.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
#include <config.h>
 
20
#include "config.h"
21
21
 
22
 
#include <drizzled/current_session.h>
23
 
#include <drizzled/gettext.h>
24
 
#include <drizzled/global_charset_info.h>
25
22
#include <drizzled/plugin/table_function.h>
26
 
#include <drizzled/session.h>
27
 
#include <drizzled/show.h>
28
23
#include <drizzled/table_function_container.h>
 
24
#include <drizzled/gettext.h>
 
25
#include "drizzled/global_charset_info.h"
 
26
#include "drizzled/session.h"
 
27
#include "drizzled/current_session.h"
29
28
 
30
29
#include <vector>
31
30
 
 
31
using namespace std;
 
32
 
32
33
namespace drizzled
33
34
{
34
35
 
36
37
 
37
38
void plugin::TableFunction::init()
38
39
{
39
 
  drizzled::message::table::init(proto, getTableLabel(), identifier.getSchemaName(), "FunctionEngine");
 
40
  drizzled::message::Engine *engine;
 
41
  drizzled::message::Table::TableOptions *table_options;
 
42
 
 
43
  proto.set_name(getTableLabel());
 
44
  proto.set_schema(identifier.getSchemaName());
40
45
  proto.set_type(drizzled::message::Table::FUNCTION);
41
46
  proto.set_creation_timestamp(0);
42
47
  proto.set_update_timestamp(0);
43
48
 
44
 
  proto.mutable_options()->set_dont_replicate(true);
 
49
  table_options= proto.mutable_options();
 
50
  table_options->set_collation_id(default_charset_info->number);
 
51
  table_options->set_collation(default_charset_info->name);
 
52
 
 
53
  engine= proto.mutable_engine();
 
54
  engine->set_name("FunctionEngine");
45
55
}
46
56
 
47
57
bool plugin::TableFunction::addPlugin(plugin::TableFunction *tool)
51
61
  return false;
52
62
}
53
63
 
54
 
plugin::TableFunction *plugin::TableFunction::getFunction(const std::string &arg)
 
64
plugin::TableFunction *plugin::TableFunction::getFunction(const string &arg)
55
65
{
56
66
  return table_functions.getFunction(arg);
57
67
}
58
68
 
59
 
void plugin::TableFunction::getNames(const std::string &arg,
60
 
                                     std::set<std::string> &set_of_names)
 
69
void plugin::TableFunction::getNames(const string &arg,
 
70
                                     set<std::string> &set_of_names)
61
71
{
62
72
  table_functions.getNames(arg, set_of_names);
63
73
}
95
105
  field_options= field->mutable_options();
96
106
  field_constraints= field->mutable_constraints();
97
107
  field_options->set_default_null(is_default_null);
98
 
  field_constraints->set_is_notnull(not is_default_null);
 
108
  field_constraints->set_is_nullable(is_default_null);
99
109
 
100
110
  switch (type) 
101
111
  {
 
112
  default:
 
113
  case TableFunction::BOOLEAN: // Currently BOOLEAN always has a value
 
114
    field_length= 5;
 
115
    field_options->set_default_null(false);
 
116
    field_constraints->set_is_nullable(false);
102
117
  case TableFunction::STRING:
103
 
    {
104
 
      drizzled::message::Table::Field::StringFieldOptions *string_field_options;
105
 
      if (field_length >= TABLE_FUNCTION_BLOB_SIZE)
106
 
      {
107
 
        field->set_type(drizzled::message::Table::Field::BLOB);
108
 
        string_field_options= field->mutable_string_options();
109
 
        string_field_options->set_collation_id(default_charset_info->number);
110
 
        string_field_options->set_collation(default_charset_info->name);
111
 
      }
112
 
      else
113
 
      {
114
 
        field->set_type(drizzled::message::Table::Field::VARCHAR);
115
 
        string_field_options= field->mutable_string_options();
116
 
        string_field_options->set_length(field_length);
117
 
      }
118
 
    }
 
118
  {
 
119
    drizzled::message::Table::Field::StringFieldOptions *string_field_options;
 
120
    field->set_type(drizzled::message::Table::Field::VARCHAR);
 
121
 
 
122
    string_field_options= field->mutable_string_options();
 
123
    string_field_options->set_length(field_length);
 
124
  }
119
125
    break;
120
126
  case TableFunction::VARBINARY:
121
 
    {
122
 
      drizzled::message::Table::Field::StringFieldOptions *string_field_options;
123
 
      field->set_type(drizzled::message::Table::Field::VARCHAR);
 
127
  {
 
128
    drizzled::message::Table::Field::StringFieldOptions *string_field_options;
 
129
    field->set_type(drizzled::message::Table::Field::VARCHAR);
124
130
 
125
 
      string_field_options= field->mutable_string_options();
126
 
      string_field_options->set_length(field_length);
127
 
      string_field_options->set_collation(my_charset_bin.csname);
128
 
      string_field_options->set_collation_id(my_charset_bin.number);
129
 
    }
130
 
    break;
131
 
  case TableFunction::NUMBER:
132
 
    field->set_type(drizzled::message::Table::Field::BIGINT);
133
 
    break;
134
 
  case TableFunction::SIZE:
135
 
    field->set_type(drizzled::message::Table::Field::BIGINT);
136
 
    field_constraints->set_is_unsigned(true);
137
 
    break;
138
 
  case TableFunction::BOOLEAN: // Currently BOOLEAN always has a value
139
 
    field->set_type(drizzled::message::Table::Field::BOOLEAN);
140
 
    field_constraints->set_is_unsigned(true);
 
131
    string_field_options= field->mutable_string_options();
 
132
    string_field_options->set_length(field_length);
 
133
    string_field_options->set_collation(my_charset_bin.csname);
 
134
    string_field_options->set_collation_id(my_charset_bin.number);
 
135
  }
 
136
    break;
 
137
  case TableFunction::NUMBER: // Currently NUMBER always has a value
 
138
    field->set_type(drizzled::message::Table::Field::BIGINT);
141
139
    break;
142
140
  }
143
141
}
187
185
  assert(arg);
188
186
  length= length ? length : strlen(arg);
189
187
 
190
 
  if ((*columns_iterator)->char_length() < length)
191
 
    length= (*columns_iterator)->char_length();
192
 
 
193
188
  (*columns_iterator)->store(arg, length, scs);
194
189
  (*columns_iterator)->set_notnull();
195
190
  columns_iterator++;
197
192
 
198
193
void plugin::TableFunction::Generator::push()
199
194
{
200
 
  /* Only accept NULLs */
201
 
  assert((*columns_iterator)->maybe_null());
 
195
#if 0 // @note this needs to be rewritten such that a drizzled::Field object can determine if it should ever be null
 
196
  assert((*columns_iterator)->getTable()->getShare()->getTableProto()->field((*columns_iterator)->getTable()->getFields() - columns_iterator).constraints().is_nullable());
 
197
#endif
202
198
  (*columns_iterator)->set_null();
203
199
  columns_iterator++;
204
200
}
224
220
 
225
221
bool plugin::TableFunction::Generator::isWild(const std::string &predicate)
226
222
{
227
 
  if (not getSession().getLex()->wild)
 
223
  if (not getSession().lex->wild)
228
224
    return false;
229
225
 
230
226
  bool match= wild_case_compare(system_charset_info,
231
227
                                predicate.c_str(),
232
 
                                getSession().getLex()->wild->ptr());
 
228
                                getSession().lex->wild->ptr());
233
229
 
234
230
  return match;
235
231
}