| 12 | |
| 13 | |
| 14 | def _complete(con, text, state): |
| 15 | global _completion_matches |
| 16 | |
| 17 | if state == 0: |
| 18 | if text.startswith("."): |
| 19 | _completion_matches = [ |
| 20 | c + " " for c in CLI_COMMANDS if c.startswith(text) |
| 21 | ] |
| 22 | else: |
| 23 | text_upper = text.upper() |
| 24 | _completion_matches = [ |
| 25 | c + " " for c in SQLITE_KEYWORDS if c.startswith(text_upper) |
| 26 | ] |
| 27 | |
| 28 | cursor = con.cursor() |
| 29 | schemata = tuple(row[1] for row |
| 30 | in cursor.execute("PRAGMA database_list")) |
| 31 | # tables, indexes, triggers, and views |
| 32 | # escape '_' which can appear in attached database names |
| 33 | select_clauses = ( |
| 34 | f"""\ |
| 35 | SELECT name || ' ' FROM \"{schema}\".sqlite_master |
| 36 | WHERE name LIKE REPLACE(:text, '_', '^_') || '%' ESCAPE '^'""" |
| 37 | for schema in schemata |
| 38 | ) |
| 39 | _completion_matches.extend( |
| 40 | row[0] |
| 41 | for row in cursor.execute( |
| 42 | " UNION ".join(select_clauses), {"text": text} |
| 43 | ) |
| 44 | ) |
| 45 | # columns |
| 46 | try: |
| 47 | select_clauses = ( |
| 48 | f"""\ |
| 49 | SELECT pti.name || ' ' FROM "{schema}".sqlite_master AS sm |
| 50 | JOIN pragma_table_xinfo(sm.name,'{schema}') AS pti |
| 51 | WHERE sm.type='table' AND |
| 52 | pti.name LIKE REPLACE(:text, '_', '^_') || '%' ESCAPE '^'""" |
| 53 | for schema in schemata |
| 54 | ) |
| 55 | _completion_matches.extend( |
| 56 | row[0] |
| 57 | for row in cursor.execute( |
| 58 | " UNION ".join(select_clauses), {"text": text} |
| 59 | ) |
| 60 | ) |
| 61 | except OperationalError: |
| 62 | # skip on SQLite<3.16.0 where pragma table-valued function is |
| 63 | # not supported yet |
| 64 | pass |
| 65 | # functions |
| 66 | try: |
| 67 | _completion_matches.extend( |
| 68 | row[0] for row in cursor.execute("""\ |
| 69 | SELECT DISTINCT UPPER(name) || '(' |
| 70 | FROM pragma_function_list() |
| 71 | WHERE name NOT IN ('->', '->>') AND |