← Back to Overview

src/backend/parser/parse_clause.c

Coverage: 49/50 lines (98.0%)
Total Lines
50
modified
Covered
49
98.0%
Uncovered
1
2.0%
키보드 네비게이션
transformRangeGraphTable() lines 908-996
Modified Lines Coverage: 41/42 lines (97.6%)
LineHitsSourceCommit
908 372 transformRangeGraphTable(ParseState *pstate, RangeGraphTable *rgt) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
909 - { 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
910 372 Relation rel; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
911 372 Oid graphid; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
912 372 GraphTableParseState *gpstate = palloc0_object(GraphTableParseState); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
913 372 Node *gp; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
914 372 List *columns = NIL; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
915 372 List *colnames = NIL; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
916 372 ListCell *lc; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
917 372 int resno = 0; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
918 372 bool saved_hasSublinks; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
919 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
920 372 rel = parserOpenTable(pstate, rgt->graph_name, AccessShareLock); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
921 369 if (rel->rd_rel->relkind != RELKIND_PROPGRAPH) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
922 3 ereport(ERROR, 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
923 - errcode(ERRCODE_WRONG_OBJECT_TYPE), 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
924 - errmsg("\"%s\" is not a property graph", 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
925 - RelationGetRelationName(rel)), 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
926 - parser_errposition(pstate, rgt->graph_name->location)); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
927 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
928 366 graphid = RelationGetRelid(rel); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
929 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
930 366 gpstate->graphid = graphid; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
931 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
932 - /* 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
933 - * The syntax does not allow nested GRAPH_TABLE and this function 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
934 - * prohibits subquery within GRAPH_TABLE. There should be only one 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
935 - * GRAPH_TABLE being transformed at a time. 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
936 - */ 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
937 366 Assert(!pstate->p_graph_table_pstate); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
938 366 pstate->p_graph_table_pstate = gpstate; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
939 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
940 366 Assert(!pstate->p_lateral_active); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
941 366 pstate->p_lateral_active = true; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
942 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
943 366 saved_hasSublinks = pstate->p_hasSubLinks; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
944 366 pstate->p_hasSubLinks = false; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
945 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
946 366 gp = transformGraphPattern(pstate, rgt->graph_pattern); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
947 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
948 1305 foreach(lc, rgt->columns) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
949 - { 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
950 948 ResTarget *rt = lfirst_node(ResTarget, lc); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
951 948 Node *colexpr; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
952 948 TargetEntry *te; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
953 948 char *colname; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
954 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
955 948 colexpr = transformExpr(pstate, rt->val, EXPR_KIND_SELECT_TARGET); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
956 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
957 942 if (rt->name) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
958 - colname = rt->name; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
959 - else 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
960 - { 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
961 511 if (IsA(colexpr, GraphPropertyRef)) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
962 511 colname = get_propgraph_property_name(castNode(GraphPropertyRef, colexpr)->propid); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
963 - else 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
964 - { 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
965 0 ereport(ERROR, 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
966 - errcode(ERRCODE_SYNTAX_ERROR), 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
967 - errmsg("complex graph table column must specify an explicit column name"), 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
968 - parser_errposition(pstate, rt->location)); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
969 - colname = NULL; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
970 - } 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
971 - } 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
972 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
973 942 colnames = lappend(colnames, makeString(colname)); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
974 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
975 942 te = makeTargetEntry((Expr *) colexpr, ++resno, colname, false); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
976 942 columns = lappend(columns, te); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
977 - } 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
978 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
979 357 table_close(rel, NoLock); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
980 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
981 357 pstate->p_graph_table_pstate = NULL; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
982 357 pstate->p_lateral_active = false; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
983 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
984 - /* 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
985 - * If we support subqueries within GRAPH_TABLE, those need to be 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
986 - * propagated to the queries resulting from rewriting graph table RTE. We 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
987 - * don't do that right now, hence prohibit it for now. 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
988 - */ 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
989 357 if (pstate->p_hasSubLinks) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
990 6 ereport(ERROR, 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
991 - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
992 - errmsg("subqueries within GRAPH_TABLE reference are not supported"))); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
993 351 pstate->p_hasSubLinks = saved_hasSublinks; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
994 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
995 351 return addRangeTableEntryForGraphTable(pstate, graphid, castNode(GraphPattern, gp), columns, colnames, rgt->alias, false, true); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
996 - } 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
transformFromClauseItem() lines 1151-1736
Modified Lines Coverage: 8/8 lines (100.0%)
LineHitsSourceCommit
1151 - transformFromClauseItem(ParseState *pstate, Node *n, -
1152 - ParseNamespaceItem **top_nsitem, -
1153 - List **namespace) -
1154 - { -
1155 - /* Guard against stack overflow due to overly deep subtree */ -
1156 - check_stack_depth(); -
1157 - -
1158 - if (IsA(n, RangeVar)) -
1159 - { -
1160 - /* Plain relation reference, or perhaps a CTE reference */ -
1161 - RangeVar *rv = (RangeVar *) n; -
1162 - RangeTblRef *rtr; -
1163 - ParseNamespaceItem *nsitem; -
1164 - -
1165 - /* Check if it's a CTE or tuplestore reference */ -
1166 - nsitem = getNSItemForSpecialRelationTypes(pstate, rv); -
1167 - -
1168 - /* if not found above, must be a table reference */ -
1169 - if (!nsitem) -
1170 - nsitem = transformTableEntry(pstate, rv); -
1171 - -
1172 - *top_nsitem = nsitem; -
1173 - *namespace = list_make1(nsitem); -
1174 - rtr = makeNode(RangeTblRef); -
1175 - rtr->rtindex = nsitem->p_rtindex; -
1176 - return (Node *) rtr; -
1177 - } -
1178 - else if (IsA(n, RangeSubselect)) -
1179 - { -
1180 - /* sub-SELECT is like a plain relation */ -
1181 - RangeTblRef *rtr; -
1182 - ParseNamespaceItem *nsitem; -
1183 - -
1184 - nsitem = transformRangeSubselect(pstate, (RangeSubselect *) n); -
1185 - *top_nsitem = nsitem; -
1186 - *namespace = list_make1(nsitem); -
1187 - rtr = makeNode(RangeTblRef); -
1188 - rtr->rtindex = nsitem->p_rtindex; -
1189 - return (Node *) rtr; -
1190 - } -
1191 - else if (IsA(n, RangeFunction)) -
1192 - { -
1193 - /* function is like a plain relation */ -
1194 - RangeTblRef *rtr; -
1195 - ParseNamespaceItem *nsitem; -
1196 - -
1197 - nsitem = transformRangeFunction(pstate, (RangeFunction *) n); -
1198 - *top_nsitem = nsitem; -
1199 - *namespace = list_make1(nsitem); -
1200 - rtr = makeNode(RangeTblRef); -
1201 - rtr->rtindex = nsitem->p_rtindex; -
1202 - return (Node *) rtr; -
1203 - } -
1204 - else if (IsA(n, RangeTableFunc) || IsA(n, JsonTable)) -
1205 - { -
1206 - /* table function is like a plain relation */ -
1207 - RangeTblRef *rtr; -
1208 - ParseNamespaceItem *nsitem; -
1209 - -
1210 - if (IsA(n, JsonTable)) -
1211 - nsitem = transformJsonTable(pstate, (JsonTable *) n); -
1212 - else -
1213 - nsitem = transformRangeTableFunc(pstate, (RangeTableFunc *) n); -
1214 - -
1215 - *top_nsitem = nsitem; -
1216 - *namespace = list_make1(nsitem); -
1217 - rtr = makeNode(RangeTblRef); -
1218 - rtr->rtindex = nsitem->p_rtindex; -
1219 - return (Node *) rtr; -
1220 - } -
1221 - else if (IsA(n, RangeGraphTable)) 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1222 - { 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1223 372 RangeTblRef *rtr; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1224 372 ParseNamespaceItem *nsitem; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1225 - 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1226 372 nsitem = transformRangeGraphTable(pstate, (RangeGraphTable *) n); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1227 351 *top_nsitem = nsitem; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1228 351 *namespace = list_make1(nsitem); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1229 351 rtr = makeNode(RangeTblRef); 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1230 351 rtr->rtindex = nsitem->p_rtindex; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1231 351 return (Node *) rtr; 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1232 - } 86c14eaWIP: SQL Property Graph Queries (SQL/PGQ)
1233 - else if (IsA(n, RangeTableSample)) -
1234 - { -
1235 - /* TABLESAMPLE clause (wrapping some other valid FROM node) */ -
1236 - RangeTableSample *rts = (RangeTableSample *) n; -
1237 - Node *rel; -
1238 - RangeTblEntry *rte; -
1239 - -
1240 - /* Recursively transform the contained relation */ -
1241 - rel = transformFromClauseItem(pstate, rts->relation, -
1242 - top_nsitem, namespace); -
1243 - rte = (*top_nsitem)->p_rte; -
1244 - /* We only support this on plain relations and matviews */ -
1245 - if (rte->rtekind != RTE_RELATION || -
1246 - (rte->relkind != RELKIND_RELATION && -
1247 - rte->relkind != RELKIND_MATVIEW && -
1248 - rte->relkind != RELKIND_PARTITIONED_TABLE)) -
1249 - ereport(ERROR, -
1250 - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -
1251 - errmsg("TABLESAMPLE clause can only be applied to tables and materialized views"), -
1252 - parser_errposition(pstate, exprLocation(rts->relation)))); -
1253 - -
1254 - /* Transform TABLESAMPLE details and attach to the RTE */ -
1255 - rte->tablesample = transformRangeTableSample(pstate, rts); -
1256 - return rel; -
1257 - } -
1258 - else if (IsA(n, JoinExpr)) -
1259 - { -
1260 - /* A newfangled join expression */ -
1261 - JoinExpr *j = (JoinExpr *) n; -
1262 - ParseNamespaceItem *nsitem; -
1263 - ParseNamespaceItem *l_nsitem; -
1264 - ParseNamespaceItem *r_nsitem; -
1265 - List *l_namespace, -
1266 - *r_namespace, -
1267 - *my_namespace, -
1268 - *l_colnames, -
1269 - *r_colnames, -
1270 - *res_colnames, -
1271 - *l_colnos, -
1272 - *r_colnos, -
1273 - *res_colvars; -
1274 - ParseNamespaceColumn *l_nscolumns, -
1275 - *r_nscolumns, -
1276 - *res_nscolumns; -
1277 - int res_colindex; -
1278 - bool lateral_ok; -
1279 - int sv_namespace_length; -
1280 - int k; -
1281 - -
1282 - /* -
1283 - * Recursively process the left subtree, then the right. We must do -
1284 - * it in this order for correct visibility of LATERAL references. -
1285 - */ -
1286 - j->larg = transformFromClauseItem(pstate, j->larg, -
1287 - &l_nsitem, -
1288 - &l_namespace); -
1289 - -
1290 - /* -
1291 - * Make the left-side RTEs available for LATERAL access within the -
1292 - * right side, by temporarily adding them to the pstate's namespace -
1293 - * list. Per SQL:2008, if the join type is not INNER or LEFT then the -
1294 - * left-side names must still be exposed, but it's an error to -
1295 - * reference them. (Stupid design, but that's what it says.) Hence, -
1296 - * we always push them into the namespace, but mark them as not -
1297 - * lateral_ok if the jointype is wrong. -
1298 - * -
1299 - * Notice that we don't require the merged namespace list to be -
1300 - * conflict-free. See the comments for scanNameSpaceForRefname(). -
1301 - */ -
1302 - lateral_ok = (j->jointype == JOIN_INNER || j->jointype == JOIN_LEFT); -
1303 - setNamespaceLateralState(l_namespace, true, lateral_ok); -
1304 - -
1305 - sv_namespace_length = list_length(pstate->p_namespace); -
1306 - pstate->p_namespace = list_concat(pstate->p_namespace, l_namespace); -
1307 - -
1308 - /* And now we can process the RHS */ -
1309 - j->rarg = transformFromClauseItem(pstate, j->rarg, -
1310 - &r_nsitem, -
1311 - &r_namespace); -
1312 - -
1313 - /* Remove the left-side RTEs from the namespace list again */ -
1314 - pstate->p_namespace = list_truncate(pstate->p_namespace, -
1315 - sv_namespace_length); -
1316 - -
1317 - /* -
1318 - * Check for conflicting refnames in left and right subtrees. Must do -
1319 - * this because higher levels will assume I hand back a self- -
1320 - * consistent namespace list. -
1321 - */ -
1322 - checkNameSpaceConflicts(pstate, l_namespace, r_namespace); -
1323 - -
1324 - /* -
1325 - * Generate combined namespace info for possible use below. -
1326 - */ -
1327 - my_namespace = list_concat(l_namespace, r_namespace); -
1328 - -
1329 - /* -
1330 - * We'll work from the nscolumns data and eref alias column names for -
1331 - * each of the input nsitems. Note that these include dropped -
1332 - * columns, which is helpful because we can keep track of physical -
1333 - * input column numbers more easily. -
1334 - */ -
1335 - l_nscolumns = l_nsitem->p_nscolumns; -
1336 - l_colnames = l_nsitem->p_names->colnames; -
1337 - r_nscolumns = r_nsitem->p_nscolumns; -
1338 - r_colnames = r_nsitem->p_names->colnames; -
1339 - -
1340 - /* -
1341 - * Natural join does not explicitly specify columns; must generate -
1342 - * columns to join. Need to run through the list of columns from each -
1343 - * table or join result and match up the column names. Use the first -
1344 - * table, and check every column in the second table for a match. -
1345 - * (We'll check that the matches were unique later on.) The result of -
1346 - * this step is a list of column names just like an explicitly-written -
1347 - * USING list. -
1348 - */ -
1349 - if (j->isNatural) -
1350 - { -
1351 - List *rlist = NIL; -
1352 - ListCell *lx, -
1353 - *rx; -
1354 - -
1355 - Assert(j->usingClause == NIL); /* shouldn't have USING() too */ -
1356 - -
1357 - foreach(lx, l_colnames) -
1358 - { -
1359 - char *l_colname = strVal(lfirst(lx)); -
1360 - String *m_name = NULL; -
1361 - -
1362 - if (l_colname[0] == '\0') -
1363 - continue; /* ignore dropped columns */ -
1364 - -
1365 - foreach(rx, r_colnames) -
1366 - { -
1367 - char *r_colname = strVal(lfirst(rx)); -
1368 - -
1369 - if (strcmp(l_colname, r_colname) == 0) -
1370 - { -
1371 - m_name = makeString(l_colname); -
1372 - break; -
1373 - } -
1374 - } -
1375 - -
1376 - /* matched a right column? then keep as join column... */ -
1377 - if (m_name != NULL) -
1378 - rlist = lappend(rlist, m_name); -
1379 - } -
1380 - -
1381 - j->usingClause = rlist; -
1382 - } -
1383 - -
1384 - /* -
1385 - * If a USING clause alias was specified, save the USING columns as -
1386 - * its column list. -
1387 - */ -
1388 - if (j->join_using_alias) -
1389 - j->join_using_alias->colnames = j->usingClause; -
1390 - -
1391 - /* -
1392 - * Now transform the join qualifications, if any. -
1393 - */ -
1394 - l_colnos = NIL; -
1395 - r_colnos = NIL; -
1396 - res_colnames = NIL; -
1397 - res_colvars = NIL; -
1398 - -
1399 - /* this may be larger than needed, but it's not worth being exact */ -
1400 - res_nscolumns = (ParseNamespaceColumn *) -
1401 - palloc0((list_length(l_colnames) + list_length(r_colnames)) * -
1402 - sizeof(ParseNamespaceColumn)); -
1403 - res_colindex = 0; -
1404 - -
1405 - if (j->usingClause) -
1406 - { -
1407 - /* -
1408 - * JOIN/USING (or NATURAL JOIN, as transformed above). Transform -
1409 - * the list into an explicit ON-condition. -
1410 - */ -
1411 - List *ucols = j->usingClause; -
1412 - List *l_usingvars = NIL; -
1413 - List *r_usingvars = NIL; -
1414 - ListCell *ucol; -
1415 - -
1416 - Assert(j->quals == NULL); /* shouldn't have ON() too */ -
1417 - -
1418 - foreach(ucol, ucols) -
1419 - { -
1420 - char *u_colname = strVal(lfirst(ucol)); -
1421 - ListCell *col; -
1422 - int ndx; -
1423 - int l_index = -1; -
1424 - int r_index = -1; -
1425 - Var *l_colvar, -
1426 - *r_colvar; -
1427 - -
1428 - Assert(u_colname[0] != '\0'); -
1429 - -
1430 - /* Check for USING(foo,foo) */ -
1431 - foreach(col, res_colnames) -
1432 - { -
1433 - char *res_colname = strVal(lfirst(col)); -
1434 - -
1435 - if (strcmp(res_colname, u_colname) == 0) -
1436 - ereport(ERROR, -
1437 - (errcode(ERRCODE_DUPLICATE_COLUMN), -
1438 - errmsg("column name \"%s\" appears more than once in USING clause", -
1439 - u_colname))); -
1440 - } -
1441 - -
1442 - /* Find it in left input */ -
1443 - ndx = 0; -
1444 - foreach(col, l_colnames) -
1445 - { -
1446 - char *l_colname = strVal(lfirst(col)); -
1447 - -
1448 - if (strcmp(l_colname, u_colname) == 0) -
1449 - { -
1450 - if (l_index >= 0) -
1451 - ereport(ERROR, -
1452 - (errcode(ERRCODE_AMBIGUOUS_COLUMN), -
1453 - errmsg("common column name \"%s\" appears more than once in left table", -
1454 - u_colname))); -
1455 - l_index = ndx; -
1456 - } -
1457 - ndx++; -
1458 - } -
1459 - if (l_index < 0) -
1460 - ereport(ERROR, -
1461 - (errcode(ERRCODE_UNDEFINED_COLUMN), -
1462 - errmsg("column \"%s\" specified in USING clause does not exist in left table", -
1463 - u_colname))); -
1464 - l_colnos = lappend_int(l_colnos, l_index + 1); -
1465 - -
1466 - /* Find it in right input */ -
1467 - ndx = 0; -
1468 - foreach(col, r_colnames) -
1469 - { -
1470 - char *r_colname = strVal(lfirst(col)); -
1471 - -
1472 - if (strcmp(r_colname, u_colname) == 0) -
1473 - { -
1474 - if (r_index >= 0) -
1475 - ereport(ERROR, -
1476 - (errcode(ERRCODE_AMBIGUOUS_COLUMN), -
1477 - errmsg("common column name \"%s\" appears more than once in right table", -
1478 - u_colname))); -
1479 - r_index = ndx; -
1480 - } -
1481 - ndx++; -
1482 - } -
1483 - if (r_index < 0) -
1484 - ereport(ERROR, -
1485 - (errcode(ERRCODE_UNDEFINED_COLUMN), -
1486 - errmsg("column \"%s\" specified in USING clause does not exist in right table", -
1487 - u_colname))); -
1488 - r_colnos = lappend_int(r_colnos, r_index + 1); -
1489 - -
1490 - /* Build Vars to use in the generated JOIN ON clause */ -
1491 - l_colvar = buildVarFromNSColumn(pstate, l_nscolumns + l_index); -
1492 - l_usingvars = lappend(l_usingvars, l_colvar); -
1493 - r_colvar = buildVarFromNSColumn(pstate, r_nscolumns + r_index); -
1494 - r_usingvars = lappend(r_usingvars, r_colvar); -
1495 - -
1496 - /* -
1497 - * While we're here, add column names to the res_colnames -
1498 - * list. It's a bit ugly to do this here while the -
1499 - * corresponding res_colvars entries are not made till later, -
1500 - * but doing this later would require an additional traversal -
1501 - * of the usingClause list. -
1502 - */ -
1503 - res_colnames = lappend(res_colnames, lfirst(ucol)); -
1504 - } -
1505 - -
1506 - /* Construct the generated JOIN ON clause */ -
1507 - j->quals = transformJoinUsingClause(pstate, -
1508 - l_usingvars, -
1509 - r_usingvars); -
1510 - } -
1511 - else if (j->quals) -
1512 - { -
1513 - /* User-written ON-condition; transform it */ -
1514 - j->quals = transformJoinOnClause(pstate, j, my_namespace); -
1515 - } -
1516 - else -
1517 - { -
1518 - /* CROSS JOIN: no quals */ -
1519 - } -
1520 - -
1521 - /* -
1522 - * If this is an outer join, now mark the appropriate child RTEs as -
1523 - * being nulled by this join. We have finished processing the child -
1524 - * join expressions as well as the current join's quals, which deal in -
1525 - * non-nulled input columns. All future references to those RTEs will -
1526 - * see possibly-nulled values, and we should mark generated Vars to -
1527 - * account for that. In particular, the join alias Vars that we're -
1528 - * about to build should reflect the nulling effects of this join. -
1529 - * -
1530 - * A difficulty with doing this is that we need the join's RT index, -
1531 - * which we don't officially have yet. However, no other RTE can get -
1532 - * made between here and the addRangeTableEntryForJoin call, so we can -
1533 - * predict what the assignment will be. (Alternatively, we could call -
1534 - * addRangeTableEntryForJoin before we have all the data computed, but -
1535 - * this seems less ugly.) -
1536 - */ -
1537 - j->rtindex = list_length(pstate->p_rtable) + 1; -
1538 - -
1539 - switch (j->jointype) -
1540 - { -
1541 - case JOIN_INNER: -
1542 - break; -
1543 - case JOIN_LEFT: -
1544 - markRelsAsNulledBy(pstate, j->rarg, j->rtindex); -
1545 - break; -
1546 - case JOIN_FULL: -
1547 - markRelsAsNulledBy(pstate, j->larg, j->rtindex); -
1548 - markRelsAsNulledBy(pstate, j->rarg, j->rtindex); -
1549 - break; -
1550 - case JOIN_RIGHT: -
1551 - markRelsAsNulledBy(pstate, j->larg, j->rtindex); -
1552 - break; -
1553 - default: -
1554 - /* shouldn't see any other types here */ -
1555 - elog(ERROR, "unrecognized join type: %d", -
1556 - (int) j->jointype); -
1557 - break; -
1558 - } -
1559 - -
1560 - /* -
1561 - * Now we can construct join alias expressions for the USING columns. -
1562 - */ -
1563 - if (j->usingClause) -
1564 - { -
1565 - ListCell *lc1, -
1566 - *lc2; -
1567 - -
1568 - /* Scan the colnos lists to recover info from the previous loop */ -
1569 - forboth(lc1, l_colnos, lc2, r_colnos) -
1570 - { -
1571 - int l_index = lfirst_int(lc1) - 1; -
1572 - int r_index = lfirst_int(lc2) - 1; -
1573 - Var *l_colvar, -
1574 - *r_colvar; -
1575 - Node *u_colvar; -
1576 - ParseNamespaceColumn *res_nscolumn; -
1577 - -
1578 - /* -
1579 - * Note we re-build these Vars: they might have different -
1580 - * varnullingrels than the ones made in the previous loop. -
1581 - */ -
1582 - l_colvar = buildVarFromNSColumn(pstate, l_nscolumns + l_index); -
1583 - r_colvar = buildVarFromNSColumn(pstate, r_nscolumns + r_index); -
1584 - -
1585 - /* Construct the join alias Var for this column */ -
1586 - u_colvar = buildMergedJoinVar(pstate, -
1587 - j->jointype, -
1588 - l_colvar, -
1589 - r_colvar); -
1590 - res_colvars = lappend(res_colvars, u_colvar); -
1591 - -
1592 - /* Construct column's res_nscolumns[] entry */ -
1593 - res_nscolumn = res_nscolumns + res_colindex; -
1594 - res_colindex++; -
1595 - if (u_colvar == (Node *) l_colvar) -
1596 - { -
1597 - /* Merged column is equivalent to left input */ -
1598 - *res_nscolumn = l_nscolumns[l_index]; -
1599 - } -
1600 - else if (u_colvar == (Node *) r_colvar) -
1601 - { -
1602 - /* Merged column is equivalent to right input */ -
1603 - *res_nscolumn = r_nscolumns[r_index]; -
1604 - } -
1605 - else -
1606 - { -
1607 - /* -
1608 - * Merged column is not semantically equivalent to either -
1609 - * input, so it needs to be referenced as the join output -
1610 - * column. -
1611 - */ -
1612 - res_nscolumn->p_varno = j->rtindex; -
1613 - res_nscolumn->p_varattno = res_colindex; -
1614 - res_nscolumn->p_vartype = exprType(u_colvar); -
1615 - res_nscolumn->p_vartypmod = exprTypmod(u_colvar); -
1616 - res_nscolumn->p_varcollid = exprCollation(u_colvar); -
1617 - res_nscolumn->p_varnosyn = j->rtindex; -
1618 - res_nscolumn->p_varattnosyn = res_colindex; -
1619 - } -
1620 - } -
1621 - } -
1622 - -
1623 - /* Add remaining columns from each side to the output columns */ -
1624 - res_colindex += -
1625 - extractRemainingColumns(pstate, -
1626 - l_nscolumns, l_colnames, &l_colnos, -
1627 - &res_colnames, &res_colvars, -
1628 - res_nscolumns + res_colindex); -
1629 - res_colindex += -
1630 - extractRemainingColumns(pstate, -
1631 - r_nscolumns, r_colnames, &r_colnos, -
1632 - &res_colnames, &res_colvars, -
1633 - res_nscolumns + res_colindex); -
1634 - -
1635 - /* If join has an alias, it syntactically hides all inputs */ -
1636 - if (j->alias) -
1637 - { -
1638 - for (k = 0; k < res_colindex; k++) -
1639 - { -
1640 - ParseNamespaceColumn *nscol = res_nscolumns + k; -
1641 - -
1642 - nscol->p_varnosyn = j->rtindex; -
1643 - nscol->p_varattnosyn = k + 1; -
1644 - } -
1645 - } -
1646 - -
1647 - /* -
1648 - * Now build an RTE and nsitem for the result of the join. -
1649 - */ -
1650 - nsitem = addRangeTableEntryForJoin(pstate, -
1651 - res_colnames, -
1652 - res_nscolumns, -
1653 - j->jointype, -
1654 - list_length(j->usingClause), -
1655 - res_colvars, -
1656 - l_colnos, -
1657 - r_colnos, -
1658 - j->join_using_alias, -
1659 - j->alias, -
1660 - true); -
1661 - -
1662 - /* Verify that we correctly predicted the join's RT index */ -
1663 - Assert(j->rtindex == nsitem->p_rtindex); -
1664 - /* Cross-check number of columns, too */ -
1665 - Assert(res_colindex == list_length(nsitem->p_names->colnames)); -
1666 - -
1667 - /* -
1668 - * Save a link to the JoinExpr in the proper element of p_joinexprs. -
1669 - * Since we maintain that list lazily, it may be necessary to fill in -
1670 - * empty entries before we can add the JoinExpr in the right place. -
1671 - */ -
1672 - for (k = list_length(pstate->p_joinexprs) + 1; k < j->rtindex; k++) -
1673 - pstate->p_joinexprs = lappend(pstate->p_joinexprs, NULL); -
1674 - pstate->p_joinexprs = lappend(pstate->p_joinexprs, j); -
1675 - Assert(list_length(pstate->p_joinexprs) == j->rtindex); -
1676 - -
1677 - /* -
1678 - * If the join has a USING alias, build a ParseNamespaceItem for that -
1679 - * and add it to the list of nsitems in the join's input. -
1680 - */ -
1681 - if (j->join_using_alias) -
1682 - { -
1683 - ParseNamespaceItem *jnsitem; -
1684 - -
1685 - jnsitem = palloc_object(ParseNamespaceItem); -
1686 - jnsitem->p_names = j->join_using_alias; -
1687 - jnsitem->p_rte = nsitem->p_rte; -
1688 - jnsitem->p_rtindex = nsitem->p_rtindex; -
1689 - jnsitem->p_perminfo = NULL; -
1690 - /* no need to copy the first N columns, just use res_nscolumns */ -
1691 - jnsitem->p_nscolumns = res_nscolumns; -
1692 - /* set default visibility flags; might get changed later */ -
1693 - jnsitem->p_rel_visible = true; -
1694 - jnsitem->p_cols_visible = true; -
1695 - jnsitem->p_lateral_only = false; -
1696 - jnsitem->p_lateral_ok = true; -
1697 - jnsitem->p_returning_type = VAR_RETURNING_DEFAULT; -
1698 - /* Per SQL, we must check for alias conflicts */ -
1699 - checkNameSpaceConflicts(pstate, list_make1(jnsitem), my_namespace); -
1700 - my_namespace = lappend(my_namespace, jnsitem); -
1701 - } -
1702 - -
1703 - /* -
1704 - * Prepare returned namespace list. If the JOIN has an alias then it -
1705 - * hides the contained RTEs completely; otherwise, the contained RTEs -
1706 - * are still visible as table names, but are not visible for -
1707 - * unqualified column-name access. -
1708 - * -
1709 - * Note: if there are nested alias-less JOINs, the lower-level ones -
1710 - * will remain in the list although they have neither p_rel_visible -
1711 - * nor p_cols_visible set. We could delete such list items, but it's -
1712 - * unclear that it's worth expending cycles to do so. -
1713 - */ -
1714 - if (j->alias != NULL) -
1715 - my_namespace = NIL; -
1716 - else -
1717 - setNamespaceColumnVisibility(my_namespace, false); -
1718 - -
1719 - /* -
1720 - * The join RTE itself is always made visible for unqualified column -
1721 - * names. It's visible as a relation name only if it has an alias. -
1722 - */ -
1723 - nsitem->p_rel_visible = (j->alias != NULL); -
1724 - nsitem->p_cols_visible = true; -
1725 - nsitem->p_lateral_only = false; -
1726 - nsitem->p_lateral_ok = true; -
1727 - -
1728 - *top_nsitem = nsitem; -
1729 - *namespace = lappend(my_namespace, nsitem); -
1730 - -
1731 - return (Node *) j; -
1732 - } -
1733 - else -
1734 - elog(ERROR, "unrecognized node type: %d", (int) nodeTag(n)); -
1735 - return NULL; /* can't get here, keep compiler quiet */ -
1736 - } -