static void estimate_costs (struct predicate *tree) { if (tree) { estimate_costs (tree->pred_right); estimate_costs (tree->pred_left); tree->p_cost = get_pred_cost(tree); } }
/* * pglogGetForeignPaths * Create possible access paths for a scan on the foreign table * * Currently we don't support any push-down feature, so there is only one * possible access path, which simply returns all records in the order in * the data file. */ static void pglogGetForeignPaths(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid) { PgLogPlanState *fdw_private = (PgLogPlanState *) baserel->fdw_private; Cost startup_cost; Cost total_cost; List *columns; List *coptions = NIL; elog(DEBUG1,"Entering function %s",__func__); /* Decide whether to selectively perform binary conversion */ if (check_selective_binary_conversion(baserel, foreigntableid, &columns)) coptions = list_make1(makeDefElem("convert_selectively", (Node *) columns)); /* Estimate costs */ estimate_costs(root, baserel, fdw_private, &startup_cost, &total_cost); /* * Create a ForeignPath node and add it as only possible path. We use the * fdw_private list of the path to carry the convert_selectively option; * it will be propagated into the fdw_private list of the Plan node. */ add_path(baserel, (Path *) create_foreignscan_path(root, baserel, baserel->rows, startup_cost, total_cost, NIL, /* no pathkeys */ NULL, /* no outer rel either */ coptions)); /* * If data file was sorted, and we knew it somehow, we could insert * appropriate pathkeys into the ForeignPath node to tell the planner * that. */ }
struct predicate* build_expression_tree (int argc, char *argv[], int end_of_leading_options) { const struct parser_table *parse_entry; /* Pointer to the parsing table entry for this expression. */ char *predicate_name; /* Name of predicate being parsed. */ struct predicate *cur_pred; const struct parser_table *entry_close, *entry_print, *entry_open; int i, oldi; predicates = NULL; /* Find where in ARGV the predicates begin by skipping the list of * start points. As a side effect, also figure out which is the * first and last start point. */ start_points = argv + end_of_leading_options; for (i = end_of_leading_options; i < argc && !looks_like_expression(argv[i], true); i++) { ++num_start_points; } /* Enclose the expression in `( ... )' so a default -print will apply to the whole expression. */ entry_open = find_parser ("("); entry_close = find_parser (")"); entry_print = find_parser ("print"); assert (entry_open != NULL); assert (entry_close != NULL); assert (entry_print != NULL); parse_openparen (entry_open, argv, &argc); last_pred->p_name = "("; predicates->artificial = true; parse_begin_user_args (argv, argc, last_pred, predicates); pred_sanity_check (last_pred); /* Build the input order list. */ while (i < argc ) { state.already_issued_stat_error_msg = false; if (!looks_like_expression (argv[i], false)) { error (0, 0, _("paths must precede expression: %s"), argv[i]); usage (stderr, 1, NULL); } predicate_name = argv[i]; parse_entry = find_parser (predicate_name); if (parse_entry == NULL) { /* Command line option not recognized */ error (EXIT_FAILURE, 0, _("unknown predicate `%s'"), predicate_name); } /* We have recognised a test of the form -foo. Eat that, * unless it is a predicate like -newerXY. */ if (parse_entry->type != ARG_SPECIAL_PARSE) { i++; } oldi = i; if (!(*(parse_entry->parser_func)) (parse_entry, argv, &i)) { if (argv[i]) { if ( (ARG_SPECIAL_PARSE == parse_entry->type) && (i == oldi) ) { /* The special parse function spat out the * predicate. It must be invalid, or not tasty. */ error (EXIT_FAILURE, 0, _("invalid predicate `%s'"), predicate_name); } else { error (EXIT_FAILURE, 0, _("invalid argument `%s' to `%s'"), argv[i], predicate_name); } } else { /* Command line option requires an argument */ error (EXIT_FAILURE, 0, _("missing argument to `%s'"), predicate_name); } } else { last_pred->p_name = predicate_name; /* If the parser consumed an argument, save it. */ if (i != oldi) last_pred->arg_text = argv[oldi]; else last_pred->arg_text = NULL; } pred_sanity_check(last_pred); pred_sanity_check(predicates); /* XXX: expensive */ } parse_end_user_args (argv, argc, last_pred, predicates); if (predicates->pred_next == NULL) { /* No predicates that do something other than set a global variable were given; remove the unneeded initial `(' and add `-print'. */ cur_pred = predicates; predicates = last_pred = predicates->pred_next; free (cur_pred); parse_print (entry_print, argv, &argc); last_pred->p_name = "-print"; pred_sanity_check(last_pred); pred_sanity_check(predicates); /* XXX: expensive */ } else if (!default_prints (predicates->pred_next)) { /* One or more predicates that produce output were given; remove the unneeded initial `('. */ cur_pred = predicates; predicates = predicates->pred_next; pred_sanity_check (predicates); /* XXX: expensive */ free (cur_pred); } else { /* `( user-supplied-expression ) -print'. */ parse_closeparen (entry_close, argv, &argc); last_pred->p_name = ")"; last_pred->artificial = true; pred_sanity_check (last_pred); parse_print (entry_print, argv, &argc); last_pred->p_name = "-print"; last_pred->artificial = true; pred_sanity_check (last_pred); pred_sanity_check (predicates); /* XXX: expensive */ } if (options.debug_options & (DebugExpressionTree|DebugTreeOpt)) { fprintf (stderr, "Predicate List:\n"); print_list (stderr, predicates); } /* do a sanity check */ check_option_combinations (predicates); pred_sanity_check (predicates); /* Done parsing the predicates. Build the evaluation tree. */ cur_pred = predicates; eval_tree = get_expr (&cur_pred, NO_PREC, NULL); calculate_derived_rates (eval_tree); /* Check if we have any left-over predicates (this fixes * Debian bug #185202). */ if (cur_pred != NULL) { /* cur_pred->p_name is often NULL here */ if (pred_is (cur_pred, pred_closeparen)) { /* e.g. "find \( -true \) \)" */ error (EXIT_FAILURE, 0, _("you have too many ')'")); } else { if (cur_pred->p_name) error (EXIT_FAILURE, 0, _("unexpected extra predicate '%s'"), cur_pred->p_name); else error (EXIT_FAILURE, 0, _("unexpected extra predicate")); } } if (options.debug_options & (DebugExpressionTree|DebugTreeOpt)) { fprintf (stderr, "Eval Tree:\n"); print_tree (stderr, eval_tree, 0); } estimate_costs (eval_tree); /* Rearrange the eval tree in optimal-predicate order. */ opt_expr (&eval_tree); /* Check that the tree is in normalised order (opt_expr does this) */ check_normalization (eval_tree, true); do_arm_swaps (eval_tree); /* Check that the tree is still in normalised order */ check_normalization (eval_tree, true); if (options.debug_options & (DebugExpressionTree|DebugTreeOpt)) { fprintf (stderr, "Optimized Eval Tree:\n"); print_tree (stderr, eval_tree, 0); fprintf (stderr, "Optimized command line:\n"); print_optlist (stderr, eval_tree); fprintf (stderr, "\n"); } return eval_tree; }