| 1 | /* |
| 2 | Copyright (c) 2009, 2011, Monty Program Ab |
| 3 | |
| 4 | This program is free software; you can redistribute it and/or modify |
| 5 | it under the terms of the GNU General Public License as published by |
| 6 | the Free Software Foundation; version 2 of the License. |
| 7 | |
| 8 | This program is distributed in the hope that it will be useful, |
| 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 | GNU General Public License for more details. |
| 12 | |
| 13 | You should have received a copy of the GNU General Public License |
| 14 | along with this program; if not, write to the Free Software |
| 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ |
| 16 | |
| 17 | /** |
| 18 | @file |
| 19 | |
| 20 | @brief |
| 21 | Table Elimination Module |
| 22 | |
| 23 | @defgroup Table_Elimination Table Elimination Module |
| 24 | @{ |
| 25 | */ |
| 26 | |
| 27 | #ifdef USE_PRAGMA_IMPLEMENTATION |
| 28 | #pragma implementation // gcc: Class implementation |
| 29 | #endif |
| 30 | |
| 31 | #include "mariadb.h" |
| 32 | #include "my_bit.h" |
| 33 | #include "sql_select.h" |
| 34 | |
| 35 | /* |
| 36 | OVERVIEW |
| 37 | ======== |
| 38 | |
| 39 | This file contains table elimination module. The idea behind table |
| 40 | elimination is as follows: suppose we have a left join |
| 41 | |
| 42 | SELECT * FROM t1 LEFT JOIN |
| 43 | (t2 JOIN t3) ON t2.primary_key=t1.col AND |
| 44 | t2.primary_key=t2.col |
| 45 | WHERE ... |
| 46 | |
| 47 | such that |
| 48 | * columns of the inner tables are not used anywhere ouside the outer join |
| 49 | (not in WHERE, not in GROUP/ORDER BY clause, not in select list etc etc), |
| 50 | * inner side of the outer join is guaranteed to produce at most one matching |
| 51 | record combination for each record combination of outer tables. |
| 52 | |
| 53 | then the inner side of the outer join can be removed from the query, as it |
| 54 | will always produce only one record combination (either real or |
| 55 | null-complemented one) and we don't care about what that record combination |
| 56 | is. |
| 57 | |
| 58 | |
| 59 | MODULE INTERFACE |
| 60 | ================ |
| 61 | |
| 62 | The module has one entry point - the eliminate_tables() function, which one |
| 63 | needs to call (once) at some point before join optimization. |
| 64 | eliminate_tables() operates over the JOIN structures. Logically, it |
| 65 | removes the inner tables of an outer join operation together with the |
| 66 | operation itself. Physically, it changes the following members: |
| 67 | |
| 68 | * Eliminated tables are marked as constant and moved to the front of the |
| 69 | join order. |
| 70 | |
| 71 | * In addition to this, they are recorded in JOIN::eliminated_tables bitmap. |
| 72 | |
| 73 | * Items that became disused because they were in the ON expression of an |
| 74 | eliminated outer join are notified by means of the Item tree walk which |
| 75 | calls Item::mark_as_eliminated_processor for every item |
| 76 | - At the moment the only Item that cares whether it was eliminated is |
| 77 | Item_subselect with its Item_subselect::eliminated flag which is used |
| 78 | by EXPLAIN code to check if the subquery should be shown in EXPLAIN. |
| 79 | |
| 80 | Table elimination is redone on every PS re-execution. |
| 81 | |
| 82 | |
| 83 | TABLE ELIMINATION ALGORITHM FOR ONE OUTER JOIN |
| 84 | ============================================== |
| 85 | |
| 86 | As described above, we can remove inner side of an outer join if it is |
| 87 | |
| 88 | 1. not referred to from any other parts of the query |
| 89 | 2. always produces one matching record combination. |
| 90 | |
| 91 | We check #1 by doing a recursive descent down the join->join_list while |
| 92 | maintaining a union of used_tables() attribute of all Item expressions in |
| 93 | other parts of the query. When we encounter an outer join, we check if the |
| 94 | bitmap of tables on its inner side has intersection with tables that are used |
| 95 | elsewhere. No intersection means that inner side of the outer join could |
| 96 | potentially be eliminated. |
| 97 | |
| 98 | In order to check #2, one needs to prove that inner side of an outer join |
| 99 | is functionally dependent on the outside. The proof is constructed from |
| 100 | functional dependencies of intermediate objects: |
| 101 | |
| 102 | - Inner side of outer join is functionally dependent when each of its tables |
| 103 | are functionally dependent. (We assume a table is functionally dependent |
| 104 | when its dependencies allow to uniquely identify one table record, or no |
| 105 | records). |
| 106 | |
| 107 | - Table is functionally dependent when it has got a unique key whose columns |
| 108 | are functionally dependent. |
| 109 | |
| 110 | - A column is functionally dependent when we could locate an AND-part of a |
| 111 | certain ON clause in form |
| 112 | |
| 113 | tblX.columnY= expr |
| 114 | |
| 115 | where expr is functionally depdendent. expr is functionally dependent when |
| 116 | all columns that it refers to are functionally dependent. |
| 117 | |
| 118 | These relationships are modeled as a bipartite directed graph that has |
| 119 | dependencies as edges and two kinds of nodes: |
| 120 | |
| 121 | Value nodes: |
| 122 | - Table column values (each is a value of tblX.columnY) |
| 123 | - Table values (each node represents a table inside the join nest we're |
| 124 | trying to eliminate). |
| 125 | A value has one attribute, it is either bound (i.e. functionally dependent) |
| 126 | or not. |
| 127 | |
| 128 | Module nodes: |
| 129 | - Modules representing tblX.colY=expr equalities. Equality module has |
| 130 | = incoming edges from columns used in expr |
| 131 | = outgoing edge to tblX.colY column. |
| 132 | - Nodes representing unique keys. Unique key has |
| 133 | = incoming edges from key component value modules |
| 134 | = outgoing edge to key's table module |
| 135 | - Inner side of outer join module. Outer join module has |
| 136 | = incoming edges from table value modules |
| 137 | = No outgoing edges. Once we reach it, we know we can eliminate the |
| 138 | outer join. |
| 139 | A module may depend on multiple values, and hence its primary attribute is |
| 140 | the number of its arguments that are not bound. |
| 141 | |
| 142 | The algorithm starts with equality nodes that don't have any incoming edges |
| 143 | (their expressions are either constant or depend only on tables that are |
| 144 | outside of the outer join in question) and performns a breadth-first |
| 145 | traversal. If we reach the outer join nest node, it means outer join is |
| 146 | functionally dependent and can be eliminated. Otherwise it cannot be |
| 147 | eliminated. |
| 148 | |
| 149 | HANDLING MULTIPLE NESTED OUTER JOINS |
| 150 | ==================================== |
| 151 | |
| 152 | Outer joins that are not nested one within another are eliminated |
| 153 | independently. For nested outer joins we have the following considerations: |
| 154 | |
| 155 | 1. ON expressions from children outer joins must be taken into account |
| 156 | |
| 157 | Consider this example: |
| 158 | |
| 159 | SELECT t0.* |
| 160 | FROM |
| 161 | t0 |
| 162 | LEFT JOIN |
| 163 | (t1 LEFT JOIN t2 ON t2.primary_key=t1.col1) |
| 164 | ON |
| 165 | t1.primary_key=t0.col AND t2.col1=t1.col2 |
| 166 | |
| 167 | Here we cannot eliminate the "... LEFT JOIN t2 ON ..." part alone because the |
| 168 | ON clause of top level outer join has references to table t2. |
| 169 | We can eliminate the entire "... LEFT JOIN (t1 LEFT JOIN t2) ON .." part, |
| 170 | but in order to do that, we must look at both ON expressions. |
| 171 | |
| 172 | 2. ON expressions of parent outer joins are useless. |
| 173 | Consider an example: |
| 174 | |
| 175 | SELECT t0.* |
| 176 | FROM |
| 177 | t0 |
| 178 | LEFT JOIN |
| 179 | (t1 LEFT JOIN t2 ON some_expr) |
| 180 | ON |
| 181 | t2.primary_key=t1.col -- (*) |
| 182 | |
| 183 | Here the uppermost ON expression has a clause that gives us functional |
| 184 | dependency of table t2 on t1 and hence could be used to eliminate the |
| 185 | "... LEFT JOIN t2 ON..." part. |
| 186 | However, we would not actually encounter this situation, because before the |
| 187 | table elimination we run simplify_joins(), which, among other things, upon |
| 188 | seeing a functional dependency condition like (*) will convert the outer join |
| 189 | of |
| 190 | |
| 191 | "... LEFT JOIN t2 ON ..." |
| 192 | |
| 193 | into inner join and thus make table elimination not to consider eliminating |
| 194 | table t2. |
| 195 | */ |
| 196 | |
| 197 | class Dep_value; |
| 198 | class Dep_value_field; |
| 199 | class Dep_value_table; |
| 200 | |
| 201 | |
| 202 | class Dep_module; |
| 203 | class Dep_module_expr; |
| 204 | class Dep_module_goal; |
| 205 | class Dep_module_key; |
| 206 | |
| 207 | class Dep_analysis_context; |
| 208 | |
| 209 | |
| 210 | /* |
| 211 | A value, something that can be bound or not bound. One can also iterate over |
| 212 | unbound modules that depend on this value |
| 213 | */ |
| 214 | |
| 215 | class Dep_value : public Sql_alloc |
| 216 | { |
| 217 | public: |
| 218 | Dep_value(): bound(FALSE) {} |
| 219 | virtual ~Dep_value(){} /* purecov: inspected */ /* stop compiler warnings */ |
| 220 | |
| 221 | bool is_bound() { return bound; } |
| 222 | void make_bound() { bound= TRUE; } |
| 223 | |
| 224 | /* Iteration over unbound modules that depend on this value */ |
| 225 | typedef char *Iterator; |
| 226 | virtual Iterator init_unbound_modules_iter(char *buf)=0; |
| 227 | virtual Dep_module* get_next_unbound_module(Dep_analysis_context *dac, |
| 228 | Iterator iter) = 0; |
| 229 | static const size_t iterator_size; |
| 230 | protected: |
| 231 | bool bound; |
| 232 | }; |
| 233 | |
| 234 | |
| 235 | /* |
| 236 | A table field value. There is exactly only one such object for any tblX.fieldY |
| 237 | - the field depends on its table and equalities |
| 238 | - expressions that use the field are its dependencies |
| 239 | */ |
| 240 | |
| 241 | class Dep_value_field : public Dep_value |
| 242 | { |
| 243 | public: |
| 244 | Dep_value_field(Dep_value_table *table_arg, Field *field_arg) : |
| 245 | table(table_arg), field(field_arg) |
| 246 | {} |
| 247 | |
| 248 | Dep_value_table *table; /* Table this field is from */ |
| 249 | Field *field; /* Field this object is representing */ |
| 250 | |
| 251 | /* Iteration over unbound modules that are our dependencies */ |
| 252 | Iterator init_unbound_modules_iter(char *buf); |
| 253 | Dep_module* get_next_unbound_module(Dep_analysis_context *dac, |
| 254 | Iterator iter); |
| 255 | |
| 256 | void make_unbound_modules_iter_skip_keys(Iterator iter); |
| 257 | |
| 258 | static const size_t iterator_size; |
| 259 | private: |
| 260 | /* |
| 261 | Field_deps that belong to one table form a linked list, ordered by |
| 262 | field_index |
| 263 | */ |
| 264 | Dep_value_field *next_table_field; |
| 265 | |
| 266 | /* |
| 267 | Offset to bits in Dep_analysis_context::expr_deps (see comment to that |
| 268 | member for semantics of the bits). |
| 269 | */ |
| 270 | uint bitmap_offset; |
| 271 | |
| 272 | class Module_iter |
| 273 | { |
| 274 | public: |
| 275 | /* if not null, return this and advance */ |
| 276 | Dep_module_key *key_dep; |
| 277 | /* Otherwise, this and advance */ |
| 278 | uint equality_no; |
| 279 | }; |
| 280 | friend class Dep_analysis_context; |
| 281 | friend class Field_dependency_recorder; |
| 282 | friend class Dep_value_table; |
| 283 | }; |
| 284 | |
| 285 | const size_t Dep_value_field::iterator_size= |
| 286 | ALIGN_SIZE(sizeof(Dep_value_field::Module_iter)); |
| 287 | |
| 288 | |
| 289 | /* |
| 290 | A table value. There is one Dep_value_table object for every table that can |
| 291 | potentially be eliminated. |
| 292 | |
| 293 | Table becomes bound as soon as some of its unique keys becomes bound |
| 294 | Once the table is bound: |
| 295 | - all of its fields are bound |
| 296 | - its embedding outer join has one less unknown argument |
| 297 | */ |
| 298 | |
| 299 | class Dep_value_table : public Dep_value |
| 300 | { |
| 301 | public: |
| 302 | Dep_value_table(TABLE *table_arg) : |
| 303 | table(table_arg), fields(NULL), keys(NULL) |
| 304 | {} |
| 305 | TABLE *table; /* Table this object is representing */ |
| 306 | /* Ordered list of fields that belong to this table */ |
| 307 | Dep_value_field *fields; |
| 308 | Dep_module_key *keys; /* Ordered list of Unique keys in this table */ |
| 309 | |
| 310 | /* Iteration over unbound modules that are our dependencies */ |
| 311 | Iterator init_unbound_modules_iter(char *buf); |
| 312 | Dep_module* get_next_unbound_module(Dep_analysis_context *dac, |
| 313 | Iterator iter); |
| 314 | static const size_t iterator_size; |
| 315 | private: |
| 316 | class Module_iter |
| 317 | { |
| 318 | public: |
| 319 | /* Space for field iterator */ |
| 320 | char buf[Dep_value_field::iterator_size]; |
| 321 | /* !NULL <=> iterating over depdenent modules of this field */ |
| 322 | Dep_value_field *field_dep; |
| 323 | bool returned_goal; |
| 324 | }; |
| 325 | }; |
| 326 | |
| 327 | |
| 328 | const size_t Dep_value_table::iterator_size= |
| 329 | ALIGN_SIZE(sizeof(Dep_value_table::Module_iter)); |
| 330 | |
| 331 | const size_t Dep_value::iterator_size= |
| 332 | MY_MAX(Dep_value_table::iterator_size, Dep_value_field::iterator_size); |
| 333 | |
| 334 | |
| 335 | /* |
| 336 | A 'module'. Module has unsatisfied dependencies, number of whose is stored in |
| 337 | unbound_args. Modules also can be linked together in a list. |
| 338 | */ |
| 339 | |
| 340 | class Dep_module : public Sql_alloc |
| 341 | { |
| 342 | public: |
| 343 | virtual ~Dep_module(){} /* purecov: inspected */ /* stop compiler warnings */ |
| 344 | |
| 345 | /* Mark as bound. Currently is non-virtual and does nothing */ |
| 346 | void make_bound() {}; |
| 347 | |
| 348 | /* |
| 349 | The final module will return TRUE here. When we see that TRUE was returned, |
| 350 | that will mean that functional dependency check succeeded. |
| 351 | */ |
| 352 | virtual bool is_final () { return FALSE; } |
| 353 | |
| 354 | /* |
| 355 | Increment number of bound arguments. this is expected to change |
| 356 | is_applicable() from false to true after sufficient set of arguments is |
| 357 | bound. |
| 358 | */ |
| 359 | void touch() { unbound_args--; } |
| 360 | bool is_applicable() { return !MY_TEST(unbound_args); } |
| 361 | |
| 362 | /* Iteration over values that */ |
| 363 | typedef char *Iterator; |
| 364 | virtual Iterator init_unbound_values_iter(char *buf)=0; |
| 365 | virtual Dep_value* get_next_unbound_value(Dep_analysis_context *dac, |
| 366 | Iterator iter)=0; |
| 367 | static const size_t iterator_size; |
| 368 | protected: |
| 369 | uint unbound_args; |
| 370 | |
| 371 | Dep_module() : unbound_args(0) {} |
| 372 | /* to bump unbound_args when constructing depedendencies */ |
| 373 | friend class Field_dependency_recorder; |
| 374 | friend class Dep_analysis_context; |
| 375 | }; |
| 376 | |
| 377 | |
| 378 | /* |
| 379 | This represents either |
| 380 | - "tbl.column= expr" equality dependency, i.e. tbl.column depends on fields |
| 381 | used in the expression, or |
| 382 | - tbl1.col1=tbl2.col2=... multi-equality. |
| 383 | */ |
| 384 | |
| 385 | class Dep_module_expr : public Dep_module |
| 386 | { |
| 387 | public: |
| 388 | Dep_value_field *field; |
| 389 | Item *expr; |
| 390 | |
| 391 | List<Dep_value_field> *mult_equal_fields; |
| 392 | /* Used during condition analysis only, similar to KEYUSE::level */ |
| 393 | uint level; |
| 394 | |
| 395 | Iterator init_unbound_values_iter(char *buf); |
| 396 | Dep_value* get_next_unbound_value(Dep_analysis_context *dac, Iterator iter); |
| 397 | static const size_t iterator_size; |
| 398 | private: |
| 399 | class Value_iter |
| 400 | { |
| 401 | public: |
| 402 | Dep_value_field *field; |
| 403 | List_iterator<Dep_value_field> it; |
| 404 | }; |
| 405 | }; |
| 406 | |
| 407 | const size_t Dep_module_expr::iterator_size= |
| 408 | ALIGN_SIZE(sizeof(Dep_module_expr::Value_iter)); |
| 409 | |
| 410 | |
| 411 | /* |
| 412 | A Unique key module |
| 413 | - Unique key has all of its components as arguments |
| 414 | - Once unique key is bound, its table value is known |
| 415 | */ |
| 416 | |
| 417 | class Dep_module_key: public Dep_module |
| 418 | { |
| 419 | public: |
| 420 | Dep_module_key(Dep_value_table *table_arg, uint keyno_arg, uint n_parts_arg) : |
| 421 | table(table_arg), keyno(keyno_arg), next_table_key(NULL) |
| 422 | { |
| 423 | unbound_args= n_parts_arg; |
| 424 | } |
| 425 | Dep_value_table *table; /* Table this key is from */ |
| 426 | uint keyno; /* The index we're representing */ |
| 427 | /* Unique keys form a linked list, ordered by keyno */ |
| 428 | Dep_module_key *next_table_key; |
| 429 | |
| 430 | Iterator init_unbound_values_iter(char *buf); |
| 431 | Dep_value* get_next_unbound_value(Dep_analysis_context *dac, Iterator iter); |
| 432 | static const size_t iterator_size; |
| 433 | private: |
| 434 | class Value_iter |
| 435 | { |
| 436 | public: |
| 437 | Dep_value_table *table; |
| 438 | }; |
| 439 | }; |
| 440 | |
| 441 | const size_t Dep_module_key::iterator_size= |
| 442 | ALIGN_SIZE(sizeof(Dep_module_key::Value_iter)); |
| 443 | |
| 444 | const size_t Dep_module::iterator_size= |
| 445 | MY_MAX(Dep_module_expr::iterator_size, Dep_module_key::iterator_size); |
| 446 | |
| 447 | |
| 448 | /* |
| 449 | A module that represents outer join that we're trying to eliminate. If we |
| 450 | manage to declare this module to be bound, then outer join can be eliminated. |
| 451 | */ |
| 452 | |
| 453 | class Dep_module_goal: public Dep_module |
| 454 | { |
| 455 | public: |
| 456 | Dep_module_goal(uint n_children) |
| 457 | { |
| 458 | unbound_args= n_children; |
| 459 | } |
| 460 | bool is_final() { return TRUE; } |
| 461 | /* |
| 462 | This is the goal module, so the running wave algorithm should terminate |
| 463 | once it sees that this module is applicable and should never try to apply |
| 464 | it, hence no use for unbound value iterator implementation. |
| 465 | */ |
| 466 | Iterator init_unbound_values_iter(char *buf) |
| 467 | { |
| 468 | DBUG_ASSERT(0); |
| 469 | return NULL; |
| 470 | } |
| 471 | Dep_value* get_next_unbound_value(Dep_analysis_context *dac, Iterator iter) |
| 472 | { |
| 473 | DBUG_ASSERT(0); |
| 474 | return NULL; |
| 475 | } |
| 476 | }; |
| 477 | |
| 478 | |
| 479 | /* |
| 480 | Functional dependency analyzer context |
| 481 | */ |
| 482 | class Dep_analysis_context |
| 483 | { |
| 484 | public: |
| 485 | bool setup_equality_modules_deps(List<Dep_module> *bound_modules); |
| 486 | bool run_wave(List<Dep_module> *new_bound_modules); |
| 487 | |
| 488 | /* Tables that we're looking at eliminating */ |
| 489 | table_map usable_tables; |
| 490 | |
| 491 | /* Array of equality dependencies */ |
| 492 | Dep_module_expr *equality_mods; |
| 493 | uint n_equality_mods; /* Number of elements in the array */ |
| 494 | uint n_equality_mods_alloced; |
| 495 | |
| 496 | /* tablenr -> Dep_value_table* mapping. */ |
| 497 | Dep_value_table *table_deps[MAX_KEY]; |
| 498 | |
| 499 | /* Element for the outer join we're attempting to eliminate */ |
| 500 | Dep_module_goal *outer_join_dep; |
| 501 | |
| 502 | /* |
| 503 | Bitmap of how expressions depend on bits. Given a Dep_value_field object, |
| 504 | one can check bitmap_is_set(expr_deps, field_val->bitmap_offset + expr_no) |
| 505 | to see if expression equality_mods[expr_no] depends on the given field. |
| 506 | */ |
| 507 | MY_BITMAP expr_deps; |
| 508 | |
| 509 | Dep_value_table *create_table_value(TABLE *table); |
| 510 | Dep_value_field *get_field_value(Field *field); |
| 511 | |
| 512 | #ifndef DBUG_OFF |
| 513 | void dbug_print_deps(); |
| 514 | #endif |
| 515 | }; |
| 516 | |
| 517 | |
| 518 | void eliminate_tables(JOIN *join); |
| 519 | |
| 520 | static bool |
| 521 | eliminate_tables_for_list(JOIN *join, |
| 522 | List<TABLE_LIST> *join_list, |
| 523 | table_map tables_in_list, |
| 524 | Item *on_expr, |
| 525 | table_map tables_used_elsewhere); |
| 526 | static |
| 527 | bool check_func_dependency(JOIN *join, |
| 528 | table_map dep_tables, |
| 529 | List_iterator<TABLE_LIST> *it, |
| 530 | TABLE_LIST *oj_tbl, |
| 531 | Item* cond); |
| 532 | static |
| 533 | void build_eq_mods_for_cond(THD *thd, Dep_analysis_context *dac, |
| 534 | Dep_module_expr **eq_mod, uint *and_level, |
| 535 | Item *cond); |
| 536 | static |
| 537 | void check_equality(Dep_analysis_context *dac, Dep_module_expr **eq_mod, |
| 538 | uint and_level, Item_bool_func *cond, |
| 539 | Item *left, Item *right); |
| 540 | static |
| 541 | Dep_module_expr *merge_eq_mods(Dep_module_expr *start, |
| 542 | Dep_module_expr *new_fields, |
| 543 | Dep_module_expr *end, uint and_level); |
| 544 | static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl); |
| 545 | static |
| 546 | void add_module_expr(Dep_analysis_context *dac, Dep_module_expr **eq_mod, |
| 547 | uint and_level, Dep_value_field *field_val, Item *right, |
| 548 | List<Dep_value_field>* mult_equal_fields); |
| 549 | |
| 550 | |
| 551 | /*****************************************************************************/ |
| 552 | |
| 553 | /* |
| 554 | Perform table elimination |
| 555 | |
| 556 | SYNOPSIS |
| 557 | eliminate_tables() |
| 558 | join Join to work on |
| 559 | |
| 560 | DESCRIPTION |
| 561 | This is the entry point for table elimination. Grep for MODULE INTERFACE |
| 562 | section in this file for calling convention. |
| 563 | |
| 564 | The idea behind table elimination is that if we have an outer join: |
| 565 | |
| 566 | SELECT * FROM t1 LEFT JOIN |
| 567 | (t2 JOIN t3) ON t2.primary_key=t1.col AND |
| 568 | t3.primary_key=t2.col |
| 569 | such that |
| 570 | |
| 571 | 1. columns of the inner tables are not used anywhere ouside the outer |
| 572 | join (not in WHERE, not in GROUP/ORDER BY clause, not in select list |
| 573 | etc etc), and |
| 574 | 2. inner side of the outer join is guaranteed to produce at most one |
| 575 | record combination for each record combination of outer tables. |
| 576 | |
| 577 | then the inner side of the outer join can be removed from the query. |
| 578 | This is because it will always produce one matching record (either a |
| 579 | real match or a NULL-complemented record combination), and since there |
| 580 | are no references to columns of the inner tables anywhere, it doesn't |
| 581 | matter which record combination it was. |
| 582 | |
| 583 | This function primary handles checking #1. It collects a bitmap of |
| 584 | tables that are not used in select list/GROUP BY/ORDER BY/HAVING/etc and |
| 585 | thus can possibly be eliminated. |
| 586 | |
| 587 | After this, if #1 is met, the function calls eliminate_tables_for_list() |
| 588 | that checks #2. |
| 589 | |
| 590 | SIDE EFFECTS |
| 591 | See the OVERVIEW section at the top of this file. |
| 592 | |
| 593 | */ |
| 594 | |
| 595 | void eliminate_tables(JOIN *join) |
| 596 | { |
| 597 | THD* thd= join->thd; |
| 598 | Item *item; |
| 599 | table_map used_tables; |
| 600 | DBUG_ENTER("eliminate_tables" ); |
| 601 | |
| 602 | DBUG_ASSERT(join->eliminated_tables == 0); |
| 603 | |
| 604 | /* If there are no outer joins, we have nothing to eliminate: */ |
| 605 | if (!join->outer_join) |
| 606 | DBUG_VOID_RETURN; |
| 607 | |
| 608 | if (!optimizer_flag(thd, OPTIMIZER_SWITCH_TABLE_ELIMINATION)) |
| 609 | DBUG_VOID_RETURN; /* purecov: inspected */ |
| 610 | |
| 611 | /* Find the tables that are referred to from WHERE/HAVING */ |
| 612 | used_tables= (join->conds? join->conds->used_tables() : 0) | |
| 613 | (join->having? join->having->used_tables() : 0); |
| 614 | |
| 615 | /* |
| 616 | For "INSERT ... SELECT ... ON DUPLICATE KEY UPDATE column = val" |
| 617 | we should also take into account tables mentioned in "val". |
| 618 | */ |
| 619 | if (join->thd->lex->sql_command == SQLCOM_INSERT_SELECT && |
| 620 | join->select_lex == &thd->lex->select_lex) |
| 621 | { |
| 622 | List_iterator<Item> val_it(thd->lex->value_list); |
| 623 | while ((item= val_it++)) |
| 624 | { |
| 625 | DBUG_ASSERT(item->fixed); |
| 626 | used_tables |= item->used_tables(); |
| 627 | } |
| 628 | } |
| 629 | |
| 630 | /* Add tables referred to from the select list */ |
| 631 | List_iterator<Item> it(join->fields_list); |
| 632 | while ((item= it++)) |
| 633 | used_tables |= item->used_tables(); |
| 634 | |
| 635 | /* Add tables referred to from ORDER BY and GROUP BY lists */ |
| 636 | ORDER *all_lists[]= { join->order, join->group_list}; |
| 637 | for (int i=0; i < 2; i++) |
| 638 | { |
| 639 | for (ORDER *cur_list= all_lists[i]; cur_list; cur_list= cur_list->next) |
| 640 | used_tables |= (*(cur_list->item))->used_tables(); |
| 641 | } |
| 642 | |
| 643 | if (join->select_lex == &thd->lex->select_lex) |
| 644 | { |
| 645 | |
| 646 | /* Multi-table UPDATE: don't eliminate tables referred from SET statement */ |
| 647 | if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI) |
| 648 | { |
| 649 | /* Multi-table UPDATE and DELETE: don't eliminate the tables we modify: */ |
| 650 | used_tables |= thd->table_map_for_update; |
| 651 | List_iterator<Item> it2(thd->lex->value_list); |
| 652 | while ((item= it2++)) |
| 653 | used_tables |= item->used_tables(); |
| 654 | } |
| 655 | |
| 656 | if (thd->lex->sql_command == SQLCOM_DELETE_MULTI) |
| 657 | { |
| 658 | TABLE_LIST *tbl; |
| 659 | for (tbl= (TABLE_LIST*)thd->lex->auxiliary_table_list.first; |
| 660 | tbl; tbl= tbl->next_local) |
| 661 | { |
| 662 | used_tables |= tbl->table->map; |
| 663 | } |
| 664 | } |
| 665 | } |
| 666 | |
| 667 | table_map all_tables= join->all_tables_map(); |
| 668 | if (all_tables & ~used_tables) |
| 669 | { |
| 670 | /* There are some tables that we probably could eliminate. Try it. */ |
| 671 | eliminate_tables_for_list(join, join->join_list, all_tables, NULL, |
| 672 | used_tables); |
| 673 | } |
| 674 | DBUG_VOID_RETURN; |
| 675 | } |
| 676 | |
| 677 | |
| 678 | /* |
| 679 | Perform table elimination in a given join list |
| 680 | |
| 681 | SYNOPSIS |
| 682 | eliminate_tables_for_list() |
| 683 | join The join we're working on |
| 684 | join_list Join list to eliminate tables from (and if |
| 685 | on_expr !=NULL, then try eliminating join_list |
| 686 | itself) |
| 687 | list_tables Bitmap of tables embedded in the join_list. |
| 688 | on_expr ON expression, if the join list is the inner side |
| 689 | of an outer join. |
| 690 | NULL means it's not an outer join but rather a |
| 691 | top-level join list. |
| 692 | tables_used_elsewhere Bitmap of tables that are referred to from |
| 693 | somewhere outside of the join list (e.g. |
| 694 | select list, HAVING, other ON expressions, etc). |
| 695 | |
| 696 | DESCRIPTION |
| 697 | Perform table elimination in a given join list: |
| 698 | - First, walk through join list members and try doing table elimination for |
| 699 | them. |
| 700 | - Then, if the join list itself is an inner side of outer join |
| 701 | (on_expr!=NULL), then try to eliminate the entire join list. |
| 702 | |
| 703 | See "HANDLING MULTIPLE NESTED OUTER JOINS" section at the top of this file |
| 704 | for more detailed description and justification. |
| 705 | |
| 706 | RETURN |
| 707 | TRUE The entire join list eliminated |
| 708 | FALSE Join list wasn't eliminated (but some of its child outer joins |
| 709 | possibly were) |
| 710 | */ |
| 711 | |
| 712 | static bool |
| 713 | eliminate_tables_for_list(JOIN *join, List<TABLE_LIST> *join_list, |
| 714 | table_map list_tables, Item *on_expr, |
| 715 | table_map tables_used_elsewhere) |
| 716 | { |
| 717 | TABLE_LIST *tbl; |
| 718 | List_iterator<TABLE_LIST> it(*join_list); |
| 719 | table_map tables_used_on_left= 0; |
| 720 | bool all_eliminated= TRUE; |
| 721 | |
| 722 | while ((tbl= it++)) |
| 723 | { |
| 724 | if (tbl->on_expr) |
| 725 | { |
| 726 | table_map outside_used_tables= tables_used_elsewhere | |
| 727 | tables_used_on_left; |
| 728 | if (on_expr) |
| 729 | outside_used_tables |= on_expr->used_tables(); |
| 730 | if (tbl->nested_join) |
| 731 | { |
| 732 | /* This is "... LEFT JOIN (join_nest) ON cond" */ |
| 733 | if (eliminate_tables_for_list(join, |
| 734 | &tbl->nested_join->join_list, |
| 735 | tbl->nested_join->used_tables, |
| 736 | tbl->on_expr, |
| 737 | outside_used_tables)) |
| 738 | { |
| 739 | mark_as_eliminated(join, tbl); |
| 740 | } |
| 741 | else |
| 742 | all_eliminated= FALSE; |
| 743 | } |
| 744 | else |
| 745 | { |
| 746 | /* This is "... LEFT JOIN tbl ON cond" */ |
| 747 | if (!(tbl->table->map & outside_used_tables) && |
| 748 | check_func_dependency(join, tbl->table->map, NULL, tbl, |
| 749 | tbl->on_expr)) |
| 750 | { |
| 751 | mark_as_eliminated(join, tbl); |
| 752 | } |
| 753 | else |
| 754 | all_eliminated= FALSE; |
| 755 | } |
| 756 | tables_used_on_left |= tbl->on_expr->used_tables(); |
| 757 | } |
| 758 | else |
| 759 | { |
| 760 | DBUG_ASSERT(!tbl->nested_join || tbl->sj_on_expr); |
| 761 | //psergey-todo: is the following really correct or we'll need to descend |
| 762 | //down all ON clauses: ? |
| 763 | if (tbl->sj_on_expr) |
| 764 | tables_used_on_left |= tbl->sj_on_expr->used_tables(); |
| 765 | } |
| 766 | } |
| 767 | |
| 768 | /* Try eliminating the nest we're called for */ |
| 769 | if (all_eliminated && on_expr && !(list_tables & tables_used_elsewhere)) |
| 770 | { |
| 771 | it.rewind(); |
| 772 | return check_func_dependency(join, list_tables & ~join->eliminated_tables, |
| 773 | &it, NULL, on_expr); |
| 774 | } |
| 775 | return FALSE; /* not eliminated */ |
| 776 | } |
| 777 | |
| 778 | |
| 779 | /* |
| 780 | Check if given condition makes given set of tables functionally dependent |
| 781 | |
| 782 | SYNOPSIS |
| 783 | check_func_dependency() |
| 784 | join Join we're procesing |
| 785 | dep_tables Tables that we check to be functionally dependent (on |
| 786 | everything else) |
| 787 | it Iterator that enumerates these tables, or NULL if we're |
| 788 | checking one single table and it is specified in oj_tbl |
| 789 | parameter. |
| 790 | oj_tbl NULL, or one single table that we're checking |
| 791 | cond Condition to use to prove functional dependency |
| 792 | |
| 793 | DESCRIPTION |
| 794 | Check if we can use given condition to infer that the set of given tables |
| 795 | is functionally dependent on everything else. |
| 796 | |
| 797 | RETURN |
| 798 | TRUE - Yes, functionally dependent |
| 799 | FALSE - No, or error |
| 800 | */ |
| 801 | |
| 802 | static |
| 803 | bool check_func_dependency(JOIN *join, |
| 804 | table_map dep_tables, |
| 805 | List_iterator<TABLE_LIST> *it, |
| 806 | TABLE_LIST *oj_tbl, |
| 807 | Item* cond) |
| 808 | { |
| 809 | Dep_analysis_context dac; |
| 810 | |
| 811 | /* |
| 812 | Pre-alloc some Dep_module_expr structures. We don't need this to be |
| 813 | guaranteed upper bound. |
| 814 | */ |
| 815 | dac.n_equality_mods_alloced= |
| 816 | join->thd->lex->current_select->max_equal_elems + |
| 817 | (join->thd->lex->current_select->cond_count+1)*2 + |
| 818 | join->thd->lex->current_select->between_count; |
| 819 | |
| 820 | bzero(dac.table_deps, sizeof(dac.table_deps)); |
| 821 | if (!(dac.equality_mods= new Dep_module_expr[dac.n_equality_mods_alloced])) |
| 822 | return FALSE; /* purecov: inspected */ |
| 823 | |
| 824 | Dep_module_expr* last_eq_mod= dac.equality_mods; |
| 825 | |
| 826 | /* Create Dep_value_table objects for all tables we're trying to eliminate */ |
| 827 | if (oj_tbl) |
| 828 | { |
| 829 | if (!dac.create_table_value(oj_tbl->table)) |
| 830 | return FALSE; /* purecov: inspected */ |
| 831 | } |
| 832 | else |
| 833 | { |
| 834 | TABLE_LIST *tbl; |
| 835 | while ((tbl= (*it)++)) |
| 836 | { |
| 837 | if (tbl->table && (tbl->table->map & dep_tables)) |
| 838 | { |
| 839 | if (!dac.create_table_value(tbl->table)) |
| 840 | return FALSE; /* purecov: inspected */ |
| 841 | } |
| 842 | } |
| 843 | } |
| 844 | dac.usable_tables= dep_tables; |
| 845 | |
| 846 | /* |
| 847 | Analyze the the ON expression and create Dep_module_expr objects and |
| 848 | Dep_value_field objects for the used fields. |
| 849 | */ |
| 850 | uint and_level=0; |
| 851 | build_eq_mods_for_cond(join->thd, &dac, &last_eq_mod, &and_level, cond); |
| 852 | if (!(dac.n_equality_mods= (uint)(last_eq_mod - dac.equality_mods))) |
| 853 | return FALSE; /* No useful conditions */ |
| 854 | |
| 855 | List<Dep_module> bound_modules; |
| 856 | |
| 857 | if (!(dac.outer_join_dep= new Dep_module_goal(my_count_bits(dep_tables))) || |
| 858 | dac.setup_equality_modules_deps(&bound_modules)) |
| 859 | { |
| 860 | return FALSE; /* OOM, default to non-dependent */ /* purecov: inspected */ |
| 861 | } |
| 862 | |
| 863 | DBUG_EXECUTE("test" , dac.dbug_print_deps(); ); |
| 864 | |
| 865 | return dac.run_wave(&bound_modules); |
| 866 | } |
| 867 | |
| 868 | |
| 869 | /* |
| 870 | Running wave functional dependency check algorithm |
| 871 | |
| 872 | SYNOPSIS |
| 873 | Dep_analysis_context::run_wave() |
| 874 | new_bound_modules List of bound modules to start the running wave from. |
| 875 | The list is destroyed during execution |
| 876 | |
| 877 | DESCRIPTION |
| 878 | This function uses running wave algorithm to check if the join nest is |
| 879 | functionally-dependent. |
| 880 | We start from provided list of bound modules, and then run the wave across |
| 881 | dependency edges, trying the reach the Dep_module_goal module. If we manage |
| 882 | to reach it, then the join nest is functionally-dependent, otherwise it is |
| 883 | not. |
| 884 | |
| 885 | RETURN |
| 886 | TRUE Yes, functionally dependent |
| 887 | FALSE No. |
| 888 | */ |
| 889 | |
| 890 | bool Dep_analysis_context::run_wave(List<Dep_module> *new_bound_modules) |
| 891 | { |
| 892 | List<Dep_value> new_bound_values; |
| 893 | |
| 894 | Dep_value *value; |
| 895 | Dep_module *module; |
| 896 | |
| 897 | while (!new_bound_modules->is_empty()) |
| 898 | { |
| 899 | /* |
| 900 | The "wave" is in new_bound_modules list. Iterate over values that can be |
| 901 | reached from these modules but are not yet bound, and collect the next |
| 902 | wave generation in new_bound_values list. |
| 903 | */ |
| 904 | List_iterator<Dep_module> modules_it(*new_bound_modules); |
| 905 | while ((module= modules_it++)) |
| 906 | { |
| 907 | char iter_buf[Dep_module::iterator_size + ALIGN_MAX_UNIT]; |
| 908 | Dep_module::Iterator iter; |
| 909 | iter= module->init_unbound_values_iter(iter_buf); |
| 910 | while ((value= module->get_next_unbound_value(this, iter))) |
| 911 | { |
| 912 | if (!value->is_bound()) |
| 913 | { |
| 914 | value->make_bound(); |
| 915 | new_bound_values.push_back(value); |
| 916 | } |
| 917 | } |
| 918 | } |
| 919 | new_bound_modules->empty(); |
| 920 | |
| 921 | /* |
| 922 | Now walk over list of values we've just found to be bound and check which |
| 923 | unbound modules can be reached from them. If there are some modules that |
| 924 | became bound, collect them in new_bound_modules list. |
| 925 | */ |
| 926 | List_iterator<Dep_value> value_it(new_bound_values); |
| 927 | while ((value= value_it++)) |
| 928 | { |
| 929 | char iter_buf[Dep_value::iterator_size + ALIGN_MAX_UNIT]; |
| 930 | Dep_value::Iterator iter; |
| 931 | iter= value->init_unbound_modules_iter(iter_buf); |
| 932 | while ((module= value->get_next_unbound_module(this, iter))) |
| 933 | { |
| 934 | module->touch(); |
| 935 | if (!module->is_applicable()) |
| 936 | continue; |
| 937 | if (module->is_final()) |
| 938 | return TRUE; /* Functionally dependent */ |
| 939 | module->make_bound(); |
| 940 | new_bound_modules->push_back(module); |
| 941 | } |
| 942 | } |
| 943 | new_bound_values.empty(); |
| 944 | } |
| 945 | return FALSE; |
| 946 | } |
| 947 | |
| 948 | |
| 949 | /* |
| 950 | This is used to analyze expressions in "tbl.col=expr" dependencies so |
| 951 | that we can figure out which fields the expression depends on. |
| 952 | */ |
| 953 | |
| 954 | class Field_dependency_recorder : public Field_enumerator |
| 955 | { |
| 956 | public: |
| 957 | Field_dependency_recorder(Dep_analysis_context *ctx_arg): ctx(ctx_arg) |
| 958 | {} |
| 959 | |
| 960 | void visit_field(Item_field *item) |
| 961 | { |
| 962 | Field *field= item->field; |
| 963 | Dep_value_table *tbl_dep; |
| 964 | if ((tbl_dep= ctx->table_deps[field->table->tablenr])) |
| 965 | { |
| 966 | for (Dep_value_field *field_dep= tbl_dep->fields; field_dep; |
| 967 | field_dep= field_dep->next_table_field) |
| 968 | { |
| 969 | if (field->field_index == field_dep->field->field_index) |
| 970 | { |
| 971 | uint offs= field_dep->bitmap_offset + expr_offset; |
| 972 | if (!bitmap_is_set(&ctx->expr_deps, offs)) |
| 973 | ctx->equality_mods[expr_offset].unbound_args++; |
| 974 | bitmap_set_bit(&ctx->expr_deps, offs); |
| 975 | return; |
| 976 | } |
| 977 | } |
| 978 | /* |
| 979 | We got here if didn't find this field. It's not a part of |
| 980 | a unique key, and/or there is no field=expr element for it. |
| 981 | Bump the dependency anyway, this will signal that this dependency |
| 982 | cannot be satisfied. |
| 983 | */ |
| 984 | ctx->equality_mods[expr_offset].unbound_args++; |
| 985 | } |
| 986 | else |
| 987 | visited_other_tables= TRUE; |
| 988 | } |
| 989 | |
| 990 | Dep_analysis_context *ctx; |
| 991 | /* Offset of the expression we're processing in the dependency bitmap */ |
| 992 | uint expr_offset; |
| 993 | |
| 994 | bool visited_other_tables; |
| 995 | }; |
| 996 | |
| 997 | |
| 998 | |
| 999 | |
| 1000 | /* |
| 1001 | Setup inbound dependency relationships for tbl.col=expr equalities |
| 1002 | |
| 1003 | SYNOPSIS |
| 1004 | setup_equality_modules_deps() |
| 1005 | bound_deps_list Put here modules that were found not to depend on |
| 1006 | any non-bound columns. |
| 1007 | |
| 1008 | DESCRIPTION |
| 1009 | Setup inbound dependency relationships for tbl.col=expr equalities: |
| 1010 | - allocate a bitmap where we store such dependencies |
| 1011 | - for each "tbl.col=expr" equality, analyze the expr part and find out |
| 1012 | which fields it refers to and set appropriate dependencies. |
| 1013 | |
| 1014 | RETURN |
| 1015 | FALSE OK |
| 1016 | TRUE Out of memory |
| 1017 | */ |
| 1018 | |
| 1019 | bool Dep_analysis_context::setup_equality_modules_deps(List<Dep_module> |
| 1020 | *bound_modules) |
| 1021 | { |
| 1022 | THD *thd= current_thd; |
| 1023 | DBUG_ENTER("setup_equality_modules_deps" ); |
| 1024 | |
| 1025 | /* |
| 1026 | Count Dep_value_field objects and assign each of them a unique |
| 1027 | bitmap_offset value. |
| 1028 | */ |
| 1029 | uint offset= 0; |
| 1030 | for (Dep_value_table **tbl_dep= table_deps; |
| 1031 | tbl_dep < table_deps + MAX_TABLES; |
| 1032 | tbl_dep++) |
| 1033 | { |
| 1034 | if (*tbl_dep) |
| 1035 | { |
| 1036 | for (Dep_value_field *field_dep= (*tbl_dep)->fields; |
| 1037 | field_dep; |
| 1038 | field_dep= field_dep->next_table_field) |
| 1039 | { |
| 1040 | field_dep->bitmap_offset= offset; |
| 1041 | offset += n_equality_mods; |
| 1042 | } |
| 1043 | } |
| 1044 | } |
| 1045 | |
| 1046 | void *buf; |
| 1047 | if (!(buf= thd->alloc(bitmap_buffer_size(offset))) || |
| 1048 | my_bitmap_init(&expr_deps, (my_bitmap_map*)buf, offset, FALSE)) |
| 1049 | { |
| 1050 | DBUG_RETURN(TRUE); /* purecov: inspected */ |
| 1051 | } |
| 1052 | bitmap_clear_all(&expr_deps); |
| 1053 | |
| 1054 | /* |
| 1055 | Analyze all "field=expr" dependencies, and have expr_deps encode |
| 1056 | dependencies of expressions from fields. |
| 1057 | |
| 1058 | Also collect a linked list of equalities that are bound. |
| 1059 | */ |
| 1060 | Field_dependency_recorder deps_recorder(this); |
| 1061 | for (Dep_module_expr *eq_mod= equality_mods; |
| 1062 | eq_mod < equality_mods + n_equality_mods; |
| 1063 | eq_mod++) |
| 1064 | { |
| 1065 | deps_recorder.expr_offset= (uint)(eq_mod - equality_mods); |
| 1066 | deps_recorder.visited_other_tables= FALSE; |
| 1067 | eq_mod->unbound_args= 0; |
| 1068 | |
| 1069 | if (eq_mod->field) |
| 1070 | { |
| 1071 | /* Regular tbl.col=expr(tblX1.col1, tblY1.col2, ...) */ |
| 1072 | eq_mod->expr->walk(&Item::enumerate_field_refs_processor, FALSE, |
| 1073 | &deps_recorder); |
| 1074 | } |
| 1075 | else |
| 1076 | { |
| 1077 | /* It's a multi-equality */ |
| 1078 | eq_mod->unbound_args= !MY_TEST(eq_mod->expr); |
| 1079 | List_iterator<Dep_value_field> it(*eq_mod->mult_equal_fields); |
| 1080 | Dep_value_field* field_val; |
| 1081 | while ((field_val= it++)) |
| 1082 | { |
| 1083 | uint offs= (uint)(field_val->bitmap_offset + eq_mod - equality_mods); |
| 1084 | bitmap_set_bit(&expr_deps, offs); |
| 1085 | } |
| 1086 | } |
| 1087 | |
| 1088 | if (!eq_mod->unbound_args) |
| 1089 | bound_modules->push_back(eq_mod, thd->mem_root); |
| 1090 | } |
| 1091 | |
| 1092 | DBUG_RETURN(FALSE); |
| 1093 | } |
| 1094 | |
| 1095 | |
| 1096 | /* |
| 1097 | Ordering that we're using whenever we need to maintain a no-duplicates list |
| 1098 | of field value objects. |
| 1099 | */ |
| 1100 | |
| 1101 | static |
| 1102 | int compare_field_values(Dep_value_field *a, Dep_value_field *b, void *unused) |
| 1103 | { |
| 1104 | uint a_ratio= a->field->table->tablenr*MAX_FIELDS + |
| 1105 | a->field->field_index; |
| 1106 | |
| 1107 | uint b_ratio= b->field->table->tablenr*MAX_FIELDS + |
| 1108 | b->field->field_index; |
| 1109 | return (a_ratio < b_ratio)? 1 : ((a_ratio == b_ratio)? 0 : -1); |
| 1110 | } |
| 1111 | |
| 1112 | |
| 1113 | /* |
| 1114 | Produce Dep_module_expr elements for given condition. |
| 1115 | |
| 1116 | SYNOPSIS |
| 1117 | build_eq_mods_for_cond() |
| 1118 | ctx Table elimination context |
| 1119 | eq_mod INOUT Put produced equality conditions here |
| 1120 | and_level INOUT AND-level (like in add_key_fields) |
| 1121 | cond Condition to process |
| 1122 | |
| 1123 | DESCRIPTION |
| 1124 | Analyze the given condition and produce an array of Dep_module_expr |
| 1125 | dependencies from it. The idea of analysis is as follows: |
| 1126 | There are useful equalities that have form |
| 1127 | |
| 1128 | eliminable_tbl.field = expr (denote as useful_equality) |
| 1129 | |
| 1130 | The condition is composed of useful equalities and other conditions that |
| 1131 | are combined together with AND and OR operators. We process the condition |
| 1132 | in recursive fashion according to these basic rules: |
| 1133 | |
| 1134 | useful_equality1 AND useful_equality2 -> make array of two |
| 1135 | Dep_module_expr objects |
| 1136 | |
| 1137 | useful_equality AND other_cond -> discard other_cond |
| 1138 | |
| 1139 | useful_equality OR other_cond -> discard everything |
| 1140 | |
| 1141 | useful_equality1 OR useful_equality2 -> check if both sides of OR are the |
| 1142 | same equality. If yes, that's the |
| 1143 | result, otherwise discard |
| 1144 | everything. |
| 1145 | |
| 1146 | The rules are used to map the condition into an array Dep_module_expr |
| 1147 | elements. The array will specify functional dependencies that logically |
| 1148 | follow from the condition. |
| 1149 | |
| 1150 | SEE ALSO |
| 1151 | This function is modeled after add_key_fields() |
| 1152 | */ |
| 1153 | |
| 1154 | static |
| 1155 | void build_eq_mods_for_cond(THD *thd, Dep_analysis_context *ctx, |
| 1156 | Dep_module_expr **eq_mod, |
| 1157 | uint *and_level, Item *cond) |
| 1158 | { |
| 1159 | if (cond->type() == Item_func::COND_ITEM) |
| 1160 | { |
| 1161 | List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list()); |
| 1162 | size_t orig_offset= *eq_mod - ctx->equality_mods; |
| 1163 | |
| 1164 | /* AND/OR */ |
| 1165 | if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC) |
| 1166 | { |
| 1167 | Item *item; |
| 1168 | while ((item=li++)) |
| 1169 | build_eq_mods_for_cond(thd, ctx, eq_mod, and_level, item); |
| 1170 | |
| 1171 | for (Dep_module_expr *mod_exp= ctx->equality_mods + orig_offset; |
| 1172 | mod_exp != *eq_mod ; mod_exp++) |
| 1173 | { |
| 1174 | mod_exp->level= *and_level; |
| 1175 | } |
| 1176 | } |
| 1177 | else |
| 1178 | { |
| 1179 | Item *item; |
| 1180 | (*and_level)++; |
| 1181 | build_eq_mods_for_cond(thd, ctx, eq_mod, and_level, li++); |
| 1182 | while ((item=li++)) |
| 1183 | { |
| 1184 | Dep_module_expr *start_key_fields= *eq_mod; |
| 1185 | (*and_level)++; |
| 1186 | build_eq_mods_for_cond(thd, ctx, eq_mod, and_level, item); |
| 1187 | *eq_mod= merge_eq_mods(ctx->equality_mods + orig_offset, |
| 1188 | start_key_fields, *eq_mod, |
| 1189 | ++(*and_level)); |
| 1190 | } |
| 1191 | } |
| 1192 | return; |
| 1193 | } |
| 1194 | |
| 1195 | if (cond->type() != Item::FUNC_ITEM) |
| 1196 | return; |
| 1197 | |
| 1198 | Item_func *cond_func= (Item_func*) cond; |
| 1199 | Item **args= cond_func->arguments(); |
| 1200 | |
| 1201 | switch (cond_func->functype()) { |
| 1202 | case Item_func::BETWEEN: |
| 1203 | { |
| 1204 | Item *fld; |
| 1205 | Item_func_between *func= (Item_func_between *) cond_func; |
| 1206 | if (!func->negated && |
| 1207 | (fld= args[0]->real_item())->type() == Item::FIELD_ITEM && |
| 1208 | args[1]->eq(args[2], ((Item_field*)fld)->field->binary())) |
| 1209 | { |
| 1210 | check_equality(ctx, eq_mod, *and_level, func, args[0], args[1]); |
| 1211 | check_equality(ctx, eq_mod, *and_level, func, args[1], args[0]); |
| 1212 | } |
| 1213 | break; |
| 1214 | } |
| 1215 | case Item_func::EQ_FUNC: |
| 1216 | case Item_func::EQUAL_FUNC: |
| 1217 | { |
| 1218 | Item_bool_rowready_func2 *func= (Item_bool_rowready_func2*) cond_func; |
| 1219 | check_equality(ctx, eq_mod, *and_level, func, args[0], args[1]); |
| 1220 | check_equality(ctx, eq_mod, *and_level, func, args[1], args[0]); |
| 1221 | break; |
| 1222 | } |
| 1223 | case Item_func::ISNULL_FUNC: |
| 1224 | { |
| 1225 | Item *tmp=new (thd->mem_root) Item_null(thd); |
| 1226 | if (tmp) |
| 1227 | check_equality(ctx, eq_mod, *and_level, |
| 1228 | (Item_func_isnull*) cond_func, args[0], tmp); |
| 1229 | break; |
| 1230 | } |
| 1231 | case Item_func::MULT_EQUAL_FUNC: |
| 1232 | { |
| 1233 | /* |
| 1234 | The condition is a |
| 1235 | |
| 1236 | tbl1.field1 = tbl2.field2 = tbl3.field3 [= const_expr] |
| 1237 | |
| 1238 | multiple-equality. Do two things: |
| 1239 | - Collect List<Dep_value_field> of tblX.colY where tblX is one of the |
| 1240 | tables we're trying to eliminate. |
| 1241 | - rembember if there was a bound value, either const_expr or tblY.colZ |
| 1242 | swher tblY is not a table that we're trying to eliminate. |
| 1243 | Store all collected information in a Dep_module_expr object. |
| 1244 | */ |
| 1245 | Item_equal *item_equal= (Item_equal*)cond; |
| 1246 | List<Dep_value_field> *fvl; |
| 1247 | if (!(fvl= new List<Dep_value_field>)) |
| 1248 | break; /* purecov: inspected */ |
| 1249 | |
| 1250 | Item_equal_fields_iterator it(*item_equal); |
| 1251 | Item *item; |
| 1252 | Item *bound_item= item_equal->get_const(); |
| 1253 | while ((item= it++)) |
| 1254 | { |
| 1255 | Field *equal_field= it.get_curr_field(); |
| 1256 | if ((item->used_tables() & ctx->usable_tables)) |
| 1257 | { |
| 1258 | Dep_value_field *field_val; |
| 1259 | if ((field_val= ctx->get_field_value(equal_field))) |
| 1260 | fvl->push_back(field_val, thd->mem_root); |
| 1261 | } |
| 1262 | else |
| 1263 | { |
| 1264 | if (!bound_item) |
| 1265 | bound_item= item; |
| 1266 | } |
| 1267 | } |
| 1268 | /* |
| 1269 | Multiple equality is only useful if it includes at least one field from |
| 1270 | the table that we could potentially eliminate: |
| 1271 | */ |
| 1272 | if (fvl->elements) |
| 1273 | { |
| 1274 | |
| 1275 | bubble_sort<Dep_value_field>(fvl, compare_field_values, NULL); |
| 1276 | add_module_expr(ctx, eq_mod, *and_level, NULL, bound_item, fvl); |
| 1277 | } |
| 1278 | break; |
| 1279 | } |
| 1280 | default: |
| 1281 | break; |
| 1282 | } |
| 1283 | } |
| 1284 | |
| 1285 | |
| 1286 | /* |
| 1287 | Perform an OR operation on two (adjacent) Dep_module_expr arrays. |
| 1288 | |
| 1289 | SYNOPSIS |
| 1290 | merge_eq_mods() |
| 1291 | start Start of left OR-part |
| 1292 | new_fields Start of right OR-part |
| 1293 | end End of right OR-part |
| 1294 | and_level AND-level (like in add_key_fields) |
| 1295 | |
| 1296 | DESCRIPTION |
| 1297 | This function is invoked for two adjacent arrays of Dep_module_expr elements: |
| 1298 | |
| 1299 | $LEFT_PART $RIGHT_PART |
| 1300 | +-----------------------+-----------------------+ |
| 1301 | start new_fields end |
| 1302 | |
| 1303 | The goal is to produce an array which would correspond to the combined |
| 1304 | |
| 1305 | $LEFT_PART OR $RIGHT_PART |
| 1306 | |
| 1307 | condition. This is achieved as follows: First, we apply distrubutive law: |
| 1308 | |
| 1309 | (fdep_A_1 AND fdep_A_2 AND ...) OR (fdep_B_1 AND fdep_B_2 AND ...) = |
| 1310 | |
| 1311 | = AND_ij (fdep_A_[i] OR fdep_B_[j]) |
| 1312 | |
| 1313 | Then we walk over the obtained "fdep_A_[i] OR fdep_B_[j]" pairs, and |
| 1314 | - Discard those that that have left and right part referring to different |
| 1315 | columns. We can't infer anything useful from "col1=expr1 OR col2=expr2". |
| 1316 | - When left and right parts refer to the same column, we check if they are |
| 1317 | essentially the same. |
| 1318 | = If they are the same, we keep one copy |
| 1319 | "t.col=expr OR t.col=expr" -> "t.col=expr |
| 1320 | = if they are different , then we discard both |
| 1321 | "t.col=expr1 OR t.col=expr2" -> (nothing useful) |
| 1322 | |
| 1323 | (no per-table or for-index FUNC_DEPS exist yet at this phase). |
| 1324 | |
| 1325 | See also merge_key_fields(). |
| 1326 | |
| 1327 | RETURN |
| 1328 | End of the result array |
| 1329 | */ |
| 1330 | |
| 1331 | static |
| 1332 | Dep_module_expr *merge_eq_mods(Dep_module_expr *start, |
| 1333 | Dep_module_expr *new_fields, |
| 1334 | Dep_module_expr *end, uint and_level) |
| 1335 | { |
| 1336 | if (start == new_fields) |
| 1337 | return start; /* (nothing) OR (...) -> (nothing) */ |
| 1338 | if (new_fields == end) |
| 1339 | return start; /* (...) OR (nothing) -> (nothing) */ |
| 1340 | |
| 1341 | Dep_module_expr *first_free= new_fields; |
| 1342 | |
| 1343 | for (; new_fields != end ; new_fields++) |
| 1344 | { |
| 1345 | for (Dep_module_expr *old=start ; old != first_free ; old++) |
| 1346 | { |
| 1347 | if (old->field == new_fields->field) |
| 1348 | { |
| 1349 | if (!old->field) |
| 1350 | { |
| 1351 | /* |
| 1352 | OR-ing two multiple equalities. We must compute an intersection of |
| 1353 | used fields, and check the constants according to these rules: |
| 1354 | |
| 1355 | a=b=c=d OR a=c=e=f -> a=c (compute intersection) |
| 1356 | a=const1 OR a=b -> (nothing) |
| 1357 | a=const1 OR a=const1 -> a=const1 |
| 1358 | a=const1 OR a=const2 -> (nothing) |
| 1359 | |
| 1360 | If we're performing an OR operation over multiple equalities, e.g. |
| 1361 | |
| 1362 | (a=b=c AND p=q) OR (a=b AND v=z) |
| 1363 | |
| 1364 | then we'll need to try combining each equality with each. ANDed |
| 1365 | equalities are guaranteed to be disjoint, so we'll only get one |
| 1366 | hit. |
| 1367 | */ |
| 1368 | Field *eq_field= old->mult_equal_fields->head()->field; |
| 1369 | if (old->expr && new_fields->expr && |
| 1370 | old->expr->eq_by_collation(new_fields->expr, eq_field->binary(), |
| 1371 | eq_field->charset())) |
| 1372 | { |
| 1373 | /* Ok, keep */ |
| 1374 | } |
| 1375 | else |
| 1376 | { |
| 1377 | /* no single constant/bound item. */ |
| 1378 | old->expr= NULL; |
| 1379 | } |
| 1380 | |
| 1381 | List <Dep_value_field> *fv; |
| 1382 | if (!(fv= new List<Dep_value_field>)) |
| 1383 | break; /* purecov: inspected */ |
| 1384 | |
| 1385 | List_iterator<Dep_value_field> it1(*old->mult_equal_fields); |
| 1386 | List_iterator<Dep_value_field> it2(*new_fields->mult_equal_fields); |
| 1387 | Dep_value_field *lfield= it1++; |
| 1388 | Dep_value_field *rfield= it2++; |
| 1389 | /* Intersect two ordered lists */ |
| 1390 | while (lfield && rfield) |
| 1391 | { |
| 1392 | if (lfield == rfield) |
| 1393 | { |
| 1394 | fv->push_back(lfield); |
| 1395 | lfield=it1++; |
| 1396 | rfield=it2++; |
| 1397 | } |
| 1398 | else |
| 1399 | { |
| 1400 | if (compare_field_values(lfield, rfield, NULL) < 0) |
| 1401 | lfield= it1++; |
| 1402 | else |
| 1403 | rfield= it2++; |
| 1404 | } |
| 1405 | } |
| 1406 | |
| 1407 | if (fv->elements + MY_TEST(old->expr) > 1) |
| 1408 | { |
| 1409 | old->mult_equal_fields= fv; |
| 1410 | old->level= and_level; |
| 1411 | } |
| 1412 | } |
| 1413 | else if (!new_fields->expr->const_item()) |
| 1414 | { |
| 1415 | /* |
| 1416 | If the value matches, we can use the key reference. |
| 1417 | If not, we keep it until we have examined all new values |
| 1418 | */ |
| 1419 | if (old->expr->eq(new_fields->expr, |
| 1420 | old->field->field->binary())) |
| 1421 | { |
| 1422 | old->level= and_level; |
| 1423 | } |
| 1424 | } |
| 1425 | else if (old->expr->eq_by_collation(new_fields->expr, |
| 1426 | old->field->field->binary(), |
| 1427 | old->field->field->charset())) |
| 1428 | { |
| 1429 | old->level= and_level; |
| 1430 | } |
| 1431 | else |
| 1432 | { |
| 1433 | /* The expressions are different. */ |
| 1434 | if (old == --first_free) // If last item |
| 1435 | break; |
| 1436 | *old= *first_free; // Remove old value |
| 1437 | old--; // Retry this value |
| 1438 | } |
| 1439 | } |
| 1440 | } |
| 1441 | } |
| 1442 | |
| 1443 | /* |
| 1444 | Ok, the results are within the [start, first_free) range, and the useful |
| 1445 | elements have level==and_level. Now, remove all unusable elements: |
| 1446 | */ |
| 1447 | for (Dep_module_expr *old=start ; old != first_free ;) |
| 1448 | { |
| 1449 | if (old->level != and_level) |
| 1450 | { // Not used in all levels |
| 1451 | if (old == --first_free) |
| 1452 | break; |
| 1453 | *old= *first_free; // Remove old value |
| 1454 | continue; |
| 1455 | } |
| 1456 | old++; |
| 1457 | } |
| 1458 | return first_free; |
| 1459 | } |
| 1460 | |
| 1461 | |
| 1462 | /* |
| 1463 | Add an Dep_module_expr element for left=right condition |
| 1464 | |
| 1465 | SYNOPSIS |
| 1466 | check_equality() |
| 1467 | fda Table elimination context |
| 1468 | eq_mod INOUT Store created Dep_module_expr here and increment ptr if |
| 1469 | you do so |
| 1470 | and_level AND-level (like in add_key_fields) |
| 1471 | cond Condition we've inferred the left=right equality from. |
| 1472 | left Left expression |
| 1473 | right Right expression |
| 1474 | usable_tables Create Dep_module_expr only if Left_expression's table |
| 1475 | belongs to this set. |
| 1476 | |
| 1477 | DESCRIPTION |
| 1478 | Check if the passed left=right equality is such that |
| 1479 | - 'left' is an Item_field referring to a field in a table we're checking |
| 1480 | to be functionally depdendent, |
| 1481 | - the equality allows to conclude that 'left' expression is functionally |
| 1482 | dependent on the 'right', |
| 1483 | and if so, create an Dep_module_expr object. |
| 1484 | */ |
| 1485 | |
| 1486 | static |
| 1487 | void check_equality(Dep_analysis_context *ctx, Dep_module_expr **eq_mod, |
| 1488 | uint and_level, Item_bool_func *cond, |
| 1489 | Item *left, Item *right) |
| 1490 | { |
| 1491 | if ((left->used_tables() & ctx->usable_tables) && |
| 1492 | !(right->used_tables() & RAND_TABLE_BIT) && |
| 1493 | left->real_item()->type() == Item::FIELD_ITEM) |
| 1494 | { |
| 1495 | Field *field= ((Item_field*)left->real_item())->field; |
| 1496 | if (!field->can_optimize_outer_join_table_elimination(cond, right)) |
| 1497 | return; |
| 1498 | Dep_value_field *field_val; |
| 1499 | if ((field_val= ctx->get_field_value(field))) |
| 1500 | add_module_expr(ctx, eq_mod, and_level, field_val, right, NULL); |
| 1501 | } |
| 1502 | } |
| 1503 | |
| 1504 | |
| 1505 | /* |
| 1506 | Add a Dep_module_expr object with the specified parameters. |
| 1507 | |
| 1508 | DESCRIPTION |
| 1509 | Add a Dep_module_expr object with the specified parameters. Re-allocate |
| 1510 | the ctx->equality_mods array if it has no space left. |
| 1511 | */ |
| 1512 | |
| 1513 | static |
| 1514 | void add_module_expr(Dep_analysis_context *ctx, Dep_module_expr **eq_mod, |
| 1515 | uint and_level, Dep_value_field *field_val, |
| 1516 | Item *right, List<Dep_value_field>* mult_equal_fields) |
| 1517 | { |
| 1518 | if (*eq_mod == ctx->equality_mods + ctx->n_equality_mods_alloced) |
| 1519 | { |
| 1520 | /* |
| 1521 | We've filled the entire equality_mods array. Replace it with a bigger |
| 1522 | one. We do it somewhat inefficiently but it doesn't matter. |
| 1523 | */ |
| 1524 | /* purecov: begin inspected */ |
| 1525 | Dep_module_expr *new_arr; |
| 1526 | if (!(new_arr= new Dep_module_expr[ctx->n_equality_mods_alloced *2])) |
| 1527 | return; |
| 1528 | ctx->n_equality_mods_alloced *= 2; |
| 1529 | for (int i= 0; i < *eq_mod - ctx->equality_mods; i++) |
| 1530 | new_arr[i]= ctx->equality_mods[i]; |
| 1531 | |
| 1532 | ctx->equality_mods= new_arr; |
| 1533 | *eq_mod= new_arr + (*eq_mod - ctx->equality_mods); |
| 1534 | /* purecov: end */ |
| 1535 | } |
| 1536 | |
| 1537 | (*eq_mod)->field= field_val; |
| 1538 | (*eq_mod)->expr= right; |
| 1539 | (*eq_mod)->level= and_level; |
| 1540 | (*eq_mod)->mult_equal_fields= mult_equal_fields; |
| 1541 | (*eq_mod)++; |
| 1542 | } |
| 1543 | |
| 1544 | |
| 1545 | /* |
| 1546 | Create a Dep_value_table object for the given table |
| 1547 | |
| 1548 | SYNOPSIS |
| 1549 | Dep_analysis_context::create_table_value() |
| 1550 | table Table to create object for |
| 1551 | |
| 1552 | DESCRIPTION |
| 1553 | Create a Dep_value_table object for the given table. Also create |
| 1554 | Dep_module_key objects for all unique keys in the table. |
| 1555 | |
| 1556 | RETURN |
| 1557 | Created table value object |
| 1558 | NULL if out of memory |
| 1559 | */ |
| 1560 | |
| 1561 | Dep_value_table *Dep_analysis_context::create_table_value(TABLE *table) |
| 1562 | { |
| 1563 | Dep_value_table *tbl_dep; |
| 1564 | if (!(tbl_dep= new Dep_value_table(table))) |
| 1565 | return NULL; /* purecov: inspected */ |
| 1566 | |
| 1567 | Dep_module_key **key_list= &(tbl_dep->keys); |
| 1568 | /* Add dependencies for unique keys */ |
| 1569 | for (uint i=0; i < table->s->keys; i++) |
| 1570 | { |
| 1571 | KEY *key= table->key_info + i; |
| 1572 | if (key->flags & HA_NOSAME) |
| 1573 | { |
| 1574 | Dep_module_key *key_dep; |
| 1575 | if (!(key_dep= new Dep_module_key(tbl_dep, i, key->user_defined_key_parts))) |
| 1576 | return NULL; |
| 1577 | *key_list= key_dep; |
| 1578 | key_list= &(key_dep->next_table_key); |
| 1579 | } |
| 1580 | } |
| 1581 | return table_deps[table->tablenr]= tbl_dep; |
| 1582 | } |
| 1583 | |
| 1584 | |
| 1585 | /* |
| 1586 | Get a Dep_value_field object for the given field, creating it if necessary |
| 1587 | |
| 1588 | SYNOPSIS |
| 1589 | Dep_analysis_context::get_field_value() |
| 1590 | field Field to create object for |
| 1591 | |
| 1592 | DESCRIPTION |
| 1593 | Get a Dep_value_field object for the given field. First, we search for it |
| 1594 | in the list of Dep_value_field objects we have already created. If we don't |
| 1595 | find it, we create a new Dep_value_field and put it into the list of field |
| 1596 | objects we have for the table. |
| 1597 | |
| 1598 | RETURN |
| 1599 | Created field value object |
| 1600 | NULL if out of memory |
| 1601 | */ |
| 1602 | |
| 1603 | Dep_value_field *Dep_analysis_context::get_field_value(Field *field) |
| 1604 | { |
| 1605 | TABLE *table= field->table; |
| 1606 | Dep_value_table *tbl_dep= table_deps[table->tablenr]; |
| 1607 | |
| 1608 | /* Try finding the field in field list */ |
| 1609 | Dep_value_field **pfield= &(tbl_dep->fields); |
| 1610 | while (*pfield && (*pfield)->field->field_index < field->field_index) |
| 1611 | { |
| 1612 | pfield= &((*pfield)->next_table_field); |
| 1613 | } |
| 1614 | if (*pfield && (*pfield)->field->field_index == field->field_index) |
| 1615 | return *pfield; |
| 1616 | |
| 1617 | /* Create the field and insert it in the list */ |
| 1618 | Dep_value_field *new_field= new Dep_value_field(tbl_dep, field); |
| 1619 | new_field->next_table_field= *pfield; |
| 1620 | *pfield= new_field; |
| 1621 | |
| 1622 | return new_field; |
| 1623 | } |
| 1624 | |
| 1625 | |
| 1626 | /* |
| 1627 | Iteration over unbound modules that are our dependencies. |
| 1628 | for those we have: |
| 1629 | - dependendencies of our fields |
| 1630 | - outer join we're in |
| 1631 | */ |
| 1632 | char *Dep_value_table::init_unbound_modules_iter(char *buf) |
| 1633 | { |
| 1634 | Module_iter *iter= ALIGN_PTR(my_ptrdiff_t(buf), Module_iter); |
| 1635 | iter->field_dep= fields; |
| 1636 | if (fields) |
| 1637 | { |
| 1638 | fields->init_unbound_modules_iter(iter->buf); |
| 1639 | fields->make_unbound_modules_iter_skip_keys(iter->buf); |
| 1640 | } |
| 1641 | iter->returned_goal= FALSE; |
| 1642 | return (char*)iter; |
| 1643 | } |
| 1644 | |
| 1645 | |
| 1646 | Dep_module* |
| 1647 | Dep_value_table::get_next_unbound_module(Dep_analysis_context *dac, |
| 1648 | char *iter) |
| 1649 | { |
| 1650 | Module_iter *di= (Module_iter*)iter; |
| 1651 | while (di->field_dep) |
| 1652 | { |
| 1653 | Dep_module *res; |
| 1654 | if ((res= di->field_dep->get_next_unbound_module(dac, di->buf))) |
| 1655 | return res; |
| 1656 | if ((di->field_dep= di->field_dep->next_table_field)) |
| 1657 | { |
| 1658 | char *field_iter= ((Module_iter*)iter)->buf; |
| 1659 | di->field_dep->init_unbound_modules_iter(field_iter); |
| 1660 | di->field_dep->make_unbound_modules_iter_skip_keys(field_iter); |
| 1661 | } |
| 1662 | } |
| 1663 | |
| 1664 | if (!di->returned_goal) |
| 1665 | { |
| 1666 | di->returned_goal= TRUE; |
| 1667 | return dac->outer_join_dep; |
| 1668 | } |
| 1669 | return NULL; |
| 1670 | } |
| 1671 | |
| 1672 | |
| 1673 | char *Dep_module_expr::init_unbound_values_iter(char *buf) |
| 1674 | { |
| 1675 | Value_iter *iter= ALIGN_PTR(my_ptrdiff_t(buf), Value_iter); |
| 1676 | iter->field= field; |
| 1677 | if (!field) |
| 1678 | { |
| 1679 | new (&iter->it) List_iterator<Dep_value_field>(*mult_equal_fields); |
| 1680 | } |
| 1681 | return (char*)iter; |
| 1682 | } |
| 1683 | |
| 1684 | |
| 1685 | Dep_value* Dep_module_expr::get_next_unbound_value(Dep_analysis_context *dac, |
| 1686 | char *buf) |
| 1687 | { |
| 1688 | Dep_value *res; |
| 1689 | if (field) |
| 1690 | { |
| 1691 | res= ((Value_iter*)buf)->field; |
| 1692 | ((Value_iter*)buf)->field= NULL; |
| 1693 | return (!res || res->is_bound())? NULL : res; |
| 1694 | } |
| 1695 | else |
| 1696 | { |
| 1697 | while ((res= ((Value_iter*)buf)->it++)) |
| 1698 | { |
| 1699 | if (!res->is_bound()) |
| 1700 | return res; |
| 1701 | } |
| 1702 | return NULL; |
| 1703 | } |
| 1704 | } |
| 1705 | |
| 1706 | |
| 1707 | char *Dep_module_key::init_unbound_values_iter(char *buf) |
| 1708 | { |
| 1709 | Value_iter *iter= ALIGN_PTR(my_ptrdiff_t(buf), Value_iter); |
| 1710 | iter->table= table; |
| 1711 | return (char*)iter; |
| 1712 | } |
| 1713 | |
| 1714 | |
| 1715 | Dep_value* Dep_module_key::get_next_unbound_value(Dep_analysis_context *dac, |
| 1716 | Dep_module::Iterator iter) |
| 1717 | { |
| 1718 | Dep_value* res= ((Value_iter*)iter)->table; |
| 1719 | ((Value_iter*)iter)->table= NULL; |
| 1720 | return res; |
| 1721 | } |
| 1722 | |
| 1723 | |
| 1724 | Dep_value::Iterator Dep_value_field::init_unbound_modules_iter(char *buf) |
| 1725 | { |
| 1726 | Module_iter *iter= ALIGN_PTR(my_ptrdiff_t(buf), Module_iter); |
| 1727 | iter->key_dep= table->keys; |
| 1728 | iter->equality_no= 0; |
| 1729 | return (char*)iter; |
| 1730 | } |
| 1731 | |
| 1732 | |
| 1733 | void |
| 1734 | Dep_value_field::make_unbound_modules_iter_skip_keys(Dep_value::Iterator iter) |
| 1735 | { |
| 1736 | ((Module_iter*)iter)->key_dep= NULL; |
| 1737 | } |
| 1738 | |
| 1739 | |
| 1740 | Dep_module* Dep_value_field::get_next_unbound_module(Dep_analysis_context *dac, |
| 1741 | Dep_value::Iterator iter) |
| 1742 | { |
| 1743 | Module_iter *di= (Module_iter*)iter; |
| 1744 | Dep_module_key *key_dep= di->key_dep; |
| 1745 | |
| 1746 | /* |
| 1747 | First, enumerate all unique keys that are |
| 1748 | - not yet applicable |
| 1749 | - have this field as a part of them |
| 1750 | */ |
| 1751 | while (key_dep && (key_dep->is_applicable() || |
| 1752 | !field->part_of_key_not_clustered.is_set(key_dep->keyno))) |
| 1753 | { |
| 1754 | key_dep= key_dep->next_table_key; |
| 1755 | } |
| 1756 | |
| 1757 | if (key_dep) |
| 1758 | { |
| 1759 | di->key_dep= key_dep->next_table_key; |
| 1760 | return key_dep; |
| 1761 | } |
| 1762 | else |
| 1763 | di->key_dep= NULL; |
| 1764 | |
| 1765 | /* |
| 1766 | Then walk through [multi]equalities and find those that |
| 1767 | - depend on this field |
| 1768 | - and are not bound yet. |
| 1769 | */ |
| 1770 | uint eq_no= di->equality_no; |
| 1771 | while (eq_no < dac->n_equality_mods && |
| 1772 | (!bitmap_is_set(&dac->expr_deps, bitmap_offset + eq_no) || |
| 1773 | dac->equality_mods[eq_no].is_applicable())) |
| 1774 | { |
| 1775 | eq_no++; |
| 1776 | } |
| 1777 | |
| 1778 | if (eq_no < dac->n_equality_mods) |
| 1779 | { |
| 1780 | di->equality_no= eq_no+1; |
| 1781 | return &dac->equality_mods[eq_no]; |
| 1782 | } |
| 1783 | return NULL; |
| 1784 | } |
| 1785 | |
| 1786 | |
| 1787 | /* |
| 1788 | Mark one table or the whole join nest as eliminated. |
| 1789 | */ |
| 1790 | |
| 1791 | static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl) |
| 1792 | { |
| 1793 | TABLE *table; |
| 1794 | /* |
| 1795 | NOTE: there are TABLE_LIST object that have |
| 1796 | tbl->table!= NULL && tbl->nested_join!=NULL and |
| 1797 | tbl->table == tbl->nested_join->join_list->element(..)->table |
| 1798 | */ |
| 1799 | if (tbl->nested_join) |
| 1800 | { |
| 1801 | TABLE_LIST *child; |
| 1802 | List_iterator<TABLE_LIST> it(tbl->nested_join->join_list); |
| 1803 | while ((child= it++)) |
| 1804 | mark_as_eliminated(join, child); |
| 1805 | } |
| 1806 | else if ((table= tbl->table)) |
| 1807 | { |
| 1808 | JOIN_TAB *tab= tbl->table->reginfo.join_tab; |
| 1809 | if (!(join->const_table_map & tab->table->map)) |
| 1810 | { |
| 1811 | DBUG_PRINT("info" , ("Eliminated table %s" , table->alias.c_ptr())); |
| 1812 | tab->type= JT_CONST; |
| 1813 | tab->table->const_table= 1; |
| 1814 | join->eliminated_tables |= table->map; |
| 1815 | join->const_table_map|= table->map; |
| 1816 | set_position(join, join->const_tables++, tab, (KEYUSE*)0); |
| 1817 | } |
| 1818 | } |
| 1819 | |
| 1820 | if (tbl->on_expr) |
| 1821 | tbl->on_expr->walk(&Item::mark_as_eliminated_processor, FALSE, NULL); |
| 1822 | } |
| 1823 | |
| 1824 | |
| 1825 | #ifndef DBUG_OFF |
| 1826 | /* purecov: begin inspected */ |
| 1827 | void Dep_analysis_context::dbug_print_deps() |
| 1828 | { |
| 1829 | DBUG_ENTER("dbug_print_deps" ); |
| 1830 | DBUG_LOCK_FILE; |
| 1831 | |
| 1832 | fprintf(DBUG_FILE,"deps {\n" ); |
| 1833 | |
| 1834 | /* Start with printing equalities */ |
| 1835 | for (Dep_module_expr *eq_mod= equality_mods; |
| 1836 | eq_mod != equality_mods + n_equality_mods; eq_mod++) |
| 1837 | { |
| 1838 | char buf[128]; |
| 1839 | String str(buf, sizeof(buf), &my_charset_bin); |
| 1840 | str.length(0); |
| 1841 | eq_mod->expr->print(&str, QT_ORDINARY); |
| 1842 | if (eq_mod->field) |
| 1843 | { |
| 1844 | fprintf(DBUG_FILE, " equality%ld: %s -> %s.%s\n" , |
| 1845 | (long)(eq_mod - equality_mods), |
| 1846 | str.c_ptr(), |
| 1847 | eq_mod->field->table->table->alias.c_ptr(), |
| 1848 | eq_mod->field->field->field_name.str); |
| 1849 | } |
| 1850 | else |
| 1851 | { |
| 1852 | fprintf(DBUG_FILE, " equality%ld: multi-equality" , |
| 1853 | (long)(eq_mod - equality_mods)); |
| 1854 | } |
| 1855 | } |
| 1856 | fprintf(DBUG_FILE,"\n" ); |
| 1857 | |
| 1858 | /* Then tables and their fields */ |
| 1859 | for (uint i=0; i < MAX_TABLES; i++) |
| 1860 | { |
| 1861 | Dep_value_table *table_dep; |
| 1862 | if ((table_dep= table_deps[i])) |
| 1863 | { |
| 1864 | /* Print table */ |
| 1865 | fprintf(DBUG_FILE, " table %s\n" , table_dep->table->alias.c_ptr()); |
| 1866 | /* Print fields */ |
| 1867 | for (Dep_value_field *field_dep= table_dep->fields; field_dep; |
| 1868 | field_dep= field_dep->next_table_field) |
| 1869 | { |
| 1870 | fprintf(DBUG_FILE, " field %s.%s ->" , |
| 1871 | table_dep->table->alias.c_ptr(), |
| 1872 | field_dep->field->field_name.str); |
| 1873 | uint ofs= field_dep->bitmap_offset; |
| 1874 | for (uint bit= ofs; bit < ofs + n_equality_mods; bit++) |
| 1875 | { |
| 1876 | if (bitmap_is_set(&expr_deps, bit)) |
| 1877 | fprintf(DBUG_FILE, " equality%d " , bit - ofs); |
| 1878 | } |
| 1879 | fprintf(DBUG_FILE, "\n" ); |
| 1880 | } |
| 1881 | } |
| 1882 | } |
| 1883 | fprintf(DBUG_FILE,"\n}\n" ); |
| 1884 | DBUG_UNLOCK_FILE; |
| 1885 | DBUG_VOID_RETURN; |
| 1886 | } |
| 1887 | /* purecov: end */ |
| 1888 | |
| 1889 | #endif |
| 1890 | /** |
| 1891 | @} (end of group Table_Elimination) |
| 1892 | */ |
| 1893 | |
| 1894 | |