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%d>", 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