On 8.5.2012, at 0:18, Michael Bayer wrote: > > On May 7, 2012, at 6:09 PM, Stefan Urbanek wrote: > >> >> p.s.: On the other hand, Table.is_view might be a good flag - to maintain >> consistency with the fact that Table() can reflect a view. However, I am not >> sure how does that fit into overall design of the library. > > the reason is that it's a partial, broken API: > > t = Table("myview", metadata, > Column(...), > Column(...), > # ... > is_view=True > ) > > metadata.create_all() > > ...to which we get, what exactly ? a view is not just a bunch of columns, > you need the whole view definition. > > similarly: > > mytable = Table("someview", metadata, autoload=True) > > assert mytable.is_view > > mytable_2 = mytable.tometadata(othermetadata) > > othermetadata.create_all() > > -> same thing ! how do we do a CREATE ? is the whole view definition > present ? do we have round trip tests for all that ? can I reflect a view > from Oracle and recreate on SQLite ? the answer is: absolutely not. It > would require that we can fully parse SQL, intelligently enough even to > translate it into another platform, which is not just out of scope, it would > be a vastly complicated process. >
You are right, I agree with that. That would create more confusion and even more inconsistencies. > Hence the whole thing stays as a recipe, and also why you're finding it > awkward that you'd like to emit DROP for views that you've reflected; the > "view reflection" use case was at most intended as a read only use case. > Creating views (and therefore dropping them as well) should not belong to Table and I see no problem with the way described in the recipe. The read-only flag might be really helpful though - once the table/view is reflected, it might be known what the source object type was (if it is possible to get it from DB engine/backend). Btw. this what I did finally and seems to work: # we already have: view_name, metadata, schema, statement (selectable) table = sqlalchemy.Table(view_name, metadata, autoload=False, schema=schema) full_name = "%s.%s" % (schema, view_name) if schema else view_name if table.exists(): inspector = sqlalchemy.engine.reflection.Inspector.from_engine(engine) view_names = inspector.get_view_names(schema=schema) if view_name in view_names: # Table reflects a view drop_statement = "DROP VIEW %s" % full_name engine.execute(drop_statement) else: # Table reflects a table table.drop(checkfirst=False) if materialize: create_stat = "CREATE TABLE" else: create_stat = "CREATE OR REPLACE VIEW" statement = "%s %s AS %s" % (create_stat, full_name, str(statement)) engine.execute(statement) > I'm not 100% sure how "view reflection" even got into the library, to be > honest, as it really doesn't belong in Table. a Table is not a view. Table is not a view, right. On the other hand, views are quite useful and in analytical domain they are being used quite a lot. The analytical data are mostly read-only during their use, therefore I see no problem with treating VIEWs as read-only TABLEs in this case. I would definitely not drop view reflection from the library, as it is makes building another kinds of abstractions/tools (besides ORM) much more easier. Stefan -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.