99 *
1010 *
1111 * IDENTIFICATION
12- * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.154 2004/01/0505:07:35 tgl Exp $
12+ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.155 2004/01/0523:39:54 tgl Exp $
1313 *
1414 *-------------------------------------------------------------------------
1515 */
@@ -76,7 +76,7 @@ static bool match_index_to_operand(Node *operand, int indexcol,
7676RelOptInfo * rel ,IndexOptInfo * index );
7777static bool match_special_index_operator (Expr * clause ,Oid opclass ,
7878bool indexkey_on_left );
79- static List * expand_indexqual_condition (Expr * clause ,Oid opclass );
79+ static List * expand_indexqual_condition (RestrictInfo * rinfo ,Oid opclass );
8080static List * prefix_quals (Node * leftop ,Oid opclass ,
8181Const * prefix ,Pattern_Prefix_Status pstatus );
8282static List * network_prefix_quals (Node * leftop ,Oid expr_op ,Oid opclass ,
@@ -1418,8 +1418,7 @@ make_innerjoin_index_path(Query *root,
14181418{
14191419IndexPath * pathnode = makeNode (IndexPath );
14201420List * indexquals ,
1421- * allclauses ,
1422- * l ;
1421+ * allclauses ;
14231422
14241423/* XXX perhaps this code should be merged with create_index_path? */
14251424
@@ -1433,28 +1432,21 @@ make_innerjoin_index_path(Query *root,
14331432 */
14341433pathnode -> path .pathkeys = NIL ;
14351434
1436- /* ConvertRestrictInfo nodes to indexquals the executor can handle */
1435+ /* Convertclauses to indexquals the executor can handle */
14371436indexquals = expand_indexqual_conditions (index ,clausegroups );
14381437
1439- /*
1440- * Also make a flattened list of the RestrictInfo nodes; createplan.c
1441- * will need this later. We assume here that we can destructively
1442- * modify the passed-in clausegroups list structure.
1443- */
1444- allclauses = NIL ;
1445- foreach (l ,clausegroups )
1446- {
1447- /* nconc okay here since same clause couldn't be in two sublists */
1448- allclauses = nconc (allclauses , (List * )lfirst (l ));
1449- }
1438+ /* Flatten the clausegroups list to produce indexclauses list */
1439+ allclauses = flatten_clausegroups_list (clausegroups );
14501440
14511441/*
14521442 * Note that we are making a pathnode for a single-scan indexscan;
1453- * therefore, indexinfoand indexqual should be single-element lists.
1443+ * therefore, indexinfoetc should be single-element lists.
14541444 */
14551445pathnode -> indexinfo = makeList1 (index );
1456- pathnode -> indexqual = makeList1 (indexquals );
1457- pathnode -> indexjoinclauses = makeList1 (allclauses );
1446+ pathnode -> indexclauses = makeList1 (allclauses );
1447+ pathnode -> indexquals = makeList1 (indexquals );
1448+
1449+ pathnode -> isjoininner = true;
14581450
14591451/* We don't actually care what order the index scans in ... */
14601452pathnode -> indexscandir = NoMovementScanDirection ;
@@ -1489,6 +1481,61 @@ make_innerjoin_index_path(Query *root,
14891481return (Path * )pathnode ;
14901482}
14911483
1484+ /*
1485+ * flatten_clausegroups_list
1486+ * Given a list of lists of RestrictInfos, flatten it to a list
1487+ * of RestrictInfos.
1488+ *
1489+ * This is used to flatten out the result of group_clauses_by_indexkey()
1490+ * or one of its sibling routines, to produce an indexclauses list.
1491+ */
1492+ List *
1493+ flatten_clausegroups_list (List * clausegroups )
1494+ {
1495+ List * allclauses = NIL ;
1496+ List * l ;
1497+
1498+ foreach (l ,clausegroups )
1499+ {
1500+ allclauses = nconc (allclauses ,listCopy ((List * )lfirst (l )));
1501+ }
1502+ return allclauses ;
1503+ }
1504+
1505+ /*
1506+ * make_expr_from_indexclauses()
1507+ * Given an indexclauses structure, produce an ordinary boolean expression.
1508+ *
1509+ * This consists of stripping out the RestrictInfo nodes and inserting
1510+ * explicit AND and OR nodes as needed. There's not much to it, but
1511+ * the functionality is needed in a few places, so centralize the logic.
1512+ */
1513+ Expr *
1514+ make_expr_from_indexclauses (List * indexclauses )
1515+ {
1516+ List * orclauses = NIL ;
1517+ List * orlist ;
1518+
1519+ /* There's no such thing as an indexpath with zero scans */
1520+ Assert (indexclauses != NIL );
1521+
1522+ foreach (orlist ,indexclauses )
1523+ {
1524+ List * andlist = (List * )lfirst (orlist );
1525+
1526+ /* Strip RestrictInfos */
1527+ andlist = get_actual_clauses (andlist );
1528+ /* Insert AND node if needed, and add to orclauses list */
1529+ orclauses = lappend (orclauses ,make_ands_explicit (andlist ));
1530+ }
1531+
1532+ if (length (orclauses )> 1 )
1533+ return make_orclause (orclauses );
1534+ else
1535+ return (Expr * )lfirst (orclauses );
1536+ }
1537+
1538+
14921539/****************************************************************************
14931540 *---- ROUTINES TO CHECK OPERANDS ----
14941541 ****************************************************************************/
@@ -1799,8 +1846,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
17991846RestrictInfo * rinfo = (RestrictInfo * )lfirst (i );
18001847
18011848FastConc (& resultquals ,
1802- expand_indexqual_condition (rinfo -> clause ,
1803- curClass ));
1849+ expand_indexqual_condition (rinfo ,curClass ));
18041850}
18051851
18061852clausegroups = lnext (clausegroups );
@@ -1816,10 +1862,13 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
18161862
18171863/*
18181864 * expand_indexqual_condition --- expand a single indexqual condition
1865+ *
1866+ * The input is a single RestrictInfo, the output a list of RestrictInfos
18191867 */
18201868static List *
1821- expand_indexqual_condition (Expr * clause ,Oid opclass )
1869+ expand_indexqual_condition (RestrictInfo * rinfo ,Oid opclass )
18221870{
1871+ Expr * clause = rinfo -> clause ;
18231872/* we know these will succeed */
18241873Node * leftop = get_leftop (clause );
18251874Node * rightop = get_rightop (clause );
@@ -1883,7 +1932,7 @@ expand_indexqual_condition(Expr *clause, Oid opclass)
18831932break ;
18841933
18851934default :
1886- result = makeList1 (clause );
1935+ result = makeList1 (rinfo );
18871936break ;
18881937}
18891938
@@ -1978,7 +2027,7 @@ prefix_quals(Node *leftop, Oid opclass,
19782027elog (ERROR ,"no = operator for opclass %u" ,opclass );
19792028expr = make_opclause (oproid ,BOOLOID , false,
19802029 (Expr * )leftop , (Expr * )prefix_const );
1981- result = makeList1 (expr );
2030+ result = makeList1 (make_restrictinfo ( expr , true, true) );
19822031return result ;
19832032}
19842033
@@ -1993,7 +2042,7 @@ prefix_quals(Node *leftop, Oid opclass,
19932042elog (ERROR ,"no >= operator for opclass %u" ,opclass );
19942043expr = make_opclause (oproid ,BOOLOID , false,
19952044 (Expr * )leftop , (Expr * )prefix_const );
1996- result = makeList1 (expr );
2045+ result = makeList1 (make_restrictinfo ( expr , true, true) );
19972046
19982047/*-------
19992048 * If we can create a string larger than the prefix, we can say
@@ -2009,7 +2058,7 @@ prefix_quals(Node *leftop, Oid opclass,
20092058elog (ERROR ,"no < operator for opclass %u" ,opclass );
20102059expr = make_opclause (oproid ,BOOLOID , false,
20112060 (Expr * )leftop , (Expr * )greaterstr );
2012- result = lappend (result ,expr );
2061+ result = lappend (result ,make_restrictinfo ( expr , true, true) );
20132062}
20142063
20152064return result ;
@@ -2080,7 +2129,7 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
20802129 (Expr * )leftop ,
20812130 (Expr * )makeConst (datatype ,-1 ,opr1right ,
20822131false, false));
2083- result = makeList1 (expr );
2132+ result = makeList1 (make_restrictinfo ( expr , true, true) );
20842133
20852134/* create clause "key <= network_scan_last( rightop )" */
20862135
@@ -2095,7 +2144,7 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
20952144 (Expr * )leftop ,
20962145 (Expr * )makeConst (datatype ,-1 ,opr2right ,
20972146false, false));
2098- result = lappend (result ,expr );
2147+ result = lappend (result ,make_restrictinfo ( expr , true, true) );
20992148
21002149return result ;
21012150}