On Tue, Feb 22, 2011 at 06:03:38PM +0300, Sergey Petrunya wrote:
On Tue, Feb 22, 2011 at 05:24:37PM +0300, Sergey Petrunya wrote:
Hi Monty,
Please find attached the complete patch of MWL#90 for review. The tree with
the code is on launchpad/buildbot:
https://code.launchpad.net/~maria-captains/maria/5.3-subqueries-mwl90
http://buildbot.askmonty.org/buildbot/grid?branch=5.3-subqueries-mwl90
Please find below dgcov coverage report for the tree. My summary is that
uncovered parts are
- error handling
- handling of semi-joins together with outer joins (a known bug/problem area)
- make_in_exists_conversion() which serves as a fallback in case we've failed
to convert the subquery to [merged] semi-join. I think I should be able to
come up with a test for this.
-- dgcov.out file starts --
File: sql/item_subselect.cc
-------------------------------------------------------------------------------
| 505: 3844: uint len= my_snprintf(buf, sizeof(buf), "", subquery_id);
| -: 3845: char *name;
| 505: 3846: if (!(name= (char*)thd->alloc(len + 1)))
| #####: 3847: DBUG_RETURN(TRUE);
| 505: 3848: memcpy(name, buf, len+1);
| -: 3849:
. 505: 3850: if (!(result= new select_materialize_with_stats))
File: sql/item_subselect.h
-------------------------------------------------------------------------------
. -: 536: THD * get_thd() { return thd; }
. -: 537: virtual int prepare()= 0;
. -: 538: virtual void fix_length_and_dec(Item_cache** row)= 0;
| #####: 539: virtual int optimize() { DBUG_ASSERT(0); return 0; }
. -: 540: /*
. -: 541: Execute the engine
. -: 542:
File: sql/opt_subselect.cc
-------------------------------------------------------------------------------
| -: 527:*/
| -: 528:
| -: 529:static
| #####: 530:bool make_in_exists_conversion(THD *thd, JOIN *join, Item_in_subselect *item)
| -: 531:{
| #####: 532: DBUG_ENTER("make_in_exists_conversion");
| #####: 533: JOIN *child_join= item->unit->first_select()->join;
| -: 534: Item_subselect::trans_res res;
| #####: 535: item->changed= 0;
| #####: 536: item->fixed= 0;
| -: 537:
| #####: 538: SELECT_LEX *save_select_lex= thd->lex->current_select;
| #####: 539: thd->lex->current_select= item->unit->first_select();
| -: 540:
| #####: 541: res= item->select_transformer(child_join);
| -: 542:
| #####: 543: thd->lex->current_select= save_select_lex;
| -: 544:
| #####: 545: if (res == Item_subselect::RES_ERROR)
| #####: 546: DBUG_RETURN(TRUE);
| -: 547:
| #####: 548: item->changed= 1;
| #####: 549: item->fixed= 1;
| -: 550:
| #####: 551: Item *substitute= item->substitution;
| #####: 552: bool do_fix_fields= !item->substitution->fixed;
| -: 553: /*
| -: 554: The Item_subselect has already been wrapped with Item_in_optimizer, so we
| -: 555: should search for item->optimizer, not 'item'.
| -: 556: */
| #####: 557: Item *replace_me= item->optimizer;
| #####: 558: DBUG_ASSERT(replace_me==substitute);
| -: 559:
| -: 560: Item **tree= (item->emb_on_expr_nest == (TABLE_LIST*)1)?
| #####: 561: &join->conds : &(item->emb_on_expr_nest->on_expr);
| #####: 562: if (replace_where_subcondition(join, tree, replace_me, substitute,
| -: 563: do_fix_fields))
| #####: 564: DBUG_RETURN(TRUE);
| #####: 565: item->substitution= NULL;
| -: 566:
| #####: 567: if (!thd->stmt_arena->is_conventional())
| -: 568: {
| -: 569: tree= (item->emb_on_expr_nest == (TABLE_LIST*)1)?
| -: 570: &join->select_lex->prep_where :
| #####: 571: &(item->emb_on_expr_nest->prep_on_expr);
| -: 572:
| #####: 573: if (replace_where_subcondition(join, tree, replace_me, substitute,
| -: 574: FALSE))
| #####: 575: DBUG_RETURN(TRUE);
| -: 576: }
| #####: 577: DBUG_RETURN(FALSE);
| -: 578:}
| -: 579:
| -: 580:
| 1451: 695: if ((*in_subq)->is_flattenable_semijoin)
| -: 696: {
| 1375: 697: if (convert_subq_to_sj(join, *in_subq))
| #####: 698: DBUG_RETURN(TRUE);
| -: 699: }
| -: 700: else
| -: 701: {
| 76: 702: if (convert_subq_to_jtbm(join, *in_subq, &remove_item))
| #####: 703: DBUG_RETURN(TRUE);
| -: 704: }
| 1451: 705: if (remove_item)
| -: 706: {
| 76: 1236: DBUG_ENTER("convert_subq_to_jtbm");
| -: 1237:
| 76: 1238: if (subq_pred->setup_engine(TRUE))
| #####: 1239: DBUG_RETURN(TRUE);
| -: 1240:
| 76: 1241: if (subq_pred->engine->engine_type() != subselect_engine::HASH_SJ_ENGINE)
| -: 1242: {
| #####: 1243: *remove_item= FALSE;
| #####: 1244: make_in_exists_conversion(parent_join->thd, parent_join, subq_pred);
| #####: 1245: DBUG_RETURN(FALSE);
| -: 1246: }
| 76: 1247: *remove_item= TRUE;
| -: 1248:
| 76: 1252: if (!(tbl_alias= (char*)parent_join->thd->calloc(sizeof(alias_mask)+5)) ||
| -: 1253: !(jtbm= alloc_join_nest(parent_join->thd))) //todo: this is not a join nest!
| -: 1254: {
| #####: 1255: DBUG_RETURN(TRUE);
| -: 1256: }
| -: 1257:
| 76: 1258: jtbm->join_list= emb_join_list;
| -: 1302: /* Inject sj_on_expr into the parent's WHERE or ON */
| 76: 1303: if (emb_tbl_nest)
| -: 1304: {
| #####: 1305: DBUG_ASSERT(0);
| -: 1306: /*emb_tbl_nest->on_expr= and_items(emb_tbl_nest->on_expr,
| -: 1307: sj_nest->sj_on_expr);
| -: 1308: emb_tbl_nest->on_expr->fix_fields(parent_join->thd, &emb_tbl_nest->on_expr);
| -: 2748: */
| 601: 2749: if (!(tab_ref->cond_guards= (bool**) thd->calloc(sizeof(uint*)*tmp_key_parts)))
| -: 2750: {
| #####: 2751: DBUG_RETURN(TRUE);
| -: 2752: }
| -: 2753:
. 601: 2754: tab_ref->key_err= 1;
| 52: 4010: hash_sj_engine->is_materialized= TRUE;
| -: 4011:
| 52: 4012: if (hash_sj_engine->materialize_join->error || tab->join->thd->is_fatal_error)
| #####: 4013: DBUG_RETURN(NESTED_LOOP_ERROR);
| -: 4014: }
| -: 4015: }
| 455621: 4016: else if (tab->bush_children)
| 137: 4032: if ((rc= sub_select(join, join_tab, FALSE/* no EOF */)) < 0 ||
| -: 4033: (rc= sub_select(join, join_tab, TRUE/* now EOF */)) < 0)
| -: 4034: {
| #####: 4035: join->return_tab= save_return_tab;
| #####: 4036: DBUG_RETURN(rc); /* it's NESTED_LOOP_(ERROR|KILLED)*/
| -: 4037: }
| 137: 4038: join->return_tab= save_return_tab;
| 137: 4039: sjm->materialized= TRUE;
File: sql/sql_base.cc
-------------------------------------------------------------------------------
| 10: 7784: Item *item= table_list->jtbm_subselect;
| 10: 7785: if (item->fix_fields(thd, &item))
| -: 7786: {
| #####: 7787: my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES);
| #####: 7788: DBUG_RETURN(1);
| -: 7789: }
| 10: 7790: DBUG_ASSERT(item == table_list->jtbm_subselect);
| 10: 7791: if (table_list->jtbm_subselect->setup_engine(FALSE))
| #####: 7792: DBUG_RETURN(1);
| -: 7793: }
. -: 7794: }
. -: 7795:
File: sql/sql_join_cache.cc
-------------------------------------------------------------------------------
. -: 2140: }
. -: 2141:
| 4620: 2142: if ((rc= join_tab_execution_startup(join_tab)) < 0)
| #####: 2143: goto finish2;
| -: 2144:
. -: 2145: /* Prepare to retrieve all records of the joined table */
| 4620: 2146: if ((error= join_tab_scan->open()))
File: sql/sql_select.cc
-------------------------------------------------------------------------------
| -: 7556: {
| -: 7557: /* Push condition to handler */
| 75098: 7558: if (!tab->table->file->cond_push(push_cond))
| #####: 7559: tab->table->file->pushed_cond= push_cond;
| -: 7560: }
. -: 7561: }
. -: 7562: }
| 136998: 8558: if (tab->bush_children)
| -: 8559: {
| 670: 8560: if (setup_sj_materialization(tab))
| #####: 8561: return TRUE;
| -: 8562: }
| -: 8563:
. 136998: 8564: TABLE *table=tab->table;
. -:14093:
| 2548539:14094: if (rc != NESTED_LOOP_NO_MORE_ROWS &&
| -:14095: (rc= join_tab_execution_startup(join_tab)) < 0)
| #####:14096: DBUG_RETURN(rc);
| -:14097:
. 2548539:14098: if (join_tab->loosescan_match_tab)
. 4:14099: join_tab->loosescan_match_tab->found_match= FALSE;
File: sql/sql_test.cc
-------------------------------------------------------------------------------
| 8: 210: if (tab->use_quick == 2)
| -: 211: fprintf(DBUG_FILE,
| -: 212: " quick select checked for each record (keys: %s)\n",
| #####: 213: tab->select->quick_keys.print(buf));
| 8: 214: else if (tab->select->quick)
| -: 215: {
| #####: 216: fprintf(DBUG_FILE, " quick select used:\n");
| #####: 217: tab->select->quick->dbug_dump(18, FALSE);
| -: 218: }
| -: 219: else
| 8: 220: VOID(fputs(" select used\n",DBUG_FILE));
-------------------------------------------------------------------------------
1667 line(s) in 16 source file(s) modified in revision(s).
50 line(s) not covered by tests.
For documentation, see http://forge.mysql.com/wiki/DGCov_doc
BR
Sergey
--
Sergey Petrunia, Software Developer
Monty Program AB, http://askmonty.org
Blog: http://s.petrunia.net/blog