(self, suggestion, word_before_cursor)
| 603 | return self.find_matches(word_before_cursor, joins, meta="join") |
| 604 | |
| 605 | def get_join_condition_matches(self, suggestion, word_before_cursor): |
| 606 | col = namedtuple("col", "schema tbl col") |
| 607 | tbls = self.populate_scoped_cols(suggestion.table_refs).items |
| 608 | cols = [(t, c) for t, cs in tbls() for c in cs] |
| 609 | try: |
| 610 | lref = (suggestion.parent or suggestion.table_refs[-1]).ref |
| 611 | ltbl, lcols = [(t, cs) for (t, cs) in tbls() if t.ref == lref][-1] |
| 612 | except IndexError: # The user typed an incorrect table qualifier |
| 613 | return [] |
| 614 | conds, found_conds = [], set() |
| 615 | |
| 616 | def add_cond(lcol, rcol, rref, prio, meta): |
| 617 | prefix = "" if suggestion.parent else ltbl.ref + "." |
| 618 | case = self.case |
| 619 | cond = prefix + case(lcol) + " = " + rref + "." + case(rcol) |
| 620 | if cond not in found_conds: |
| 621 | found_conds.add(cond) |
| 622 | conds.append(Candidate(cond, prio + ref_prio[rref], meta)) |
| 623 | |
| 624 | def list_dict(pairs): # Turns [(a, b), (a, c)] into {a: [b, c]} |
| 625 | d = defaultdict(list) |
| 626 | for pair in pairs: |
| 627 | d[pair[0]].append(pair[1]) |
| 628 | return d |
| 629 | |
| 630 | # Tables that are closer to the cursor get higher prio |
| 631 | ref_prio = {tbl.ref: num for num, tbl in enumerate(suggestion.table_refs)} |
| 632 | # Map (schema, table, col) to tables |
| 633 | coldict = list_dict(((t.schema, t.name, c.name), t) for t, c in cols if t.ref != lref) |
| 634 | # For each fk from the left table, generate a join condition if |
| 635 | # the other table is also in the scope |
| 636 | fks = ((fk, lcol.name) for lcol in lcols for fk in lcol.foreignkeys) |
| 637 | for fk, lcol in fks: |
| 638 | left = col(ltbl.schema, ltbl.name, lcol) |
| 639 | child = col(fk.childschema, fk.childtable, fk.childcolumn) |
| 640 | par = col(fk.parentschema, fk.parenttable, fk.parentcolumn) |
| 641 | left, right = (child, par) if left == child else (par, child) |
| 642 | for rtbl in coldict[right]: |
| 643 | add_cond(left.col, right.col, rtbl.ref, 2000, "fk join") |
| 644 | # For name matching, use a {(colname, coltype): TableReference} dict |
| 645 | coltyp = namedtuple("coltyp", "name datatype") |
| 646 | col_table = list_dict((coltyp(c.name, c.datatype), t) for t, c in cols) |
| 647 | # Find all name-match join conditions |
| 648 | for c in (coltyp(c.name, c.datatype) for c in lcols): |
| 649 | for rtbl in (t for t in col_table[c] if t.ref != ltbl.ref): |
| 650 | prio = 1000 if c.datatype in ("integer", "bigint", "smallint") else 0 |
| 651 | add_cond(c.name, c.name, rtbl.ref, prio, "name join") |
| 652 | |
| 653 | return self.find_matches(word_before_cursor, conds, meta="join") |
| 654 | |
| 655 | def get_function_matches(self, suggestion, word_before_cursor, alias=False): |
| 656 | if suggestion.usage == "from": |
nothing calls this directly
no test coverage detected