Open luxint opened 2 years ago
I don't like the idea of table_names()
returning names of tables from connected databases as well, because it feels like it could lead to surprising behaviour - especially if those connected databases turn to have table names that are duplicated in the main connected database.
It would be neat if functions like .rows_where()
worked though.
One thought would be to support something like this:
rows = db["otherdb.tablename"].rows_where()
But... .
is a valid character in a SQLite table name. So "otherdb.tablename"
might ambiguously refer to a table called tablename
in a connected database with the alias otherdb
, OR a table in the current database with the name otherdb.tablename
.
Another potential fix: add a alias=
parameter to rows_where()
and other similar methods. Then you could do this:
rows = db["tablename"].rows_where(alias="otherdb")
This feels wrong to me: db["tablename"]
is the bit that is supposed to return a table object. Having part of what that table object is exist as a parameter to other methods is confusing.
Third option, and I think the one I like the best:
rows = db.table("tablename", alias="otherdb").rows_where(alias="otherdb")
The db.table(tablename)
method already exists as an alternative to db[tablename]
: https://sqlite-utils.datasette.io/en/stable/python-api.html#python-api-table-configuration
Implementing this would be a pretty big change - initial instinct is that I'd need to introduce a self.alias
property to Queryable
(the subclass of Table
and View
) and a new self.name_with_alias
getter which returns alias.tablename
if alias
is set to a not-None value. Then I'd need to rewrite every piece of code like this:
To look like this instead:
sql = "select {} from [{}]".format(select, self.name_with_alias)
But some parts would be harder - for example:
Would have to know to query alias.sqlite_master
instead.
The cached table counts logic like this would need a bunch of changes too:
Initial idea of how the .table()
method would change:
diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py
index 7a06304..3ecb40b 100644
--- a/sqlite_utils/db.py
+++ b/sqlite_utils/db.py
@@ -474,11 +474,12 @@ class Database:
self._tracer(sql, None)
return self.conn.executescript(sql)
- def table(self, table_name: str, **kwargs) -> Union["Table", "View"]:
+ def table(self, table_name: str, alias: Optional[str] = None, **kwargs) -> Union["Table", "View"]:
"""
Return a table object, optionally configured with default options.
:param table_name: Name of the table
+ :param alias: The database alias to use, if referring to a table in another connected database
"""
klass = View if table_name in self.view_names() else Table
return klass(self, table_name, **kwargs)
Hi,
I noticed
rows_where()
doesn't return any rows from tables which are from attached databases. Theexists()
function returns false. As far as I can see this is because thetable_names()
function only looks for table names in the current database and not in attached (or temp) databases.Besides,
rows_where()
, alsoinsert_all()
anddelete_where()
didn't do what I was expecting because of this. For the moment I've patchedtable_names()
for myself, see below but I'm not sure what the total impact is on the other functions like lookup truncate etc which all useexists()
. Alsoview_names()
doesn't look for views in attached or temp databases.