It looks like Beaker supports two database backends, ext:database and ext:sqla, but what is the difference between them?
问题:
回答1:
Overview
Looking at the source code (Beaker-1.6.4-py2.7.egg), the backend initialization is different and the database schema are slightly different.
The key difference seems to be whether you want to use a preexisting SQLAlchemy connection (ext:sqla) or create a brand new connection (ext:database).
Additionally, ext:database can wholly be configured within ini configuration files while ext:sqla cannot.
Details: Config
In the configuration file, ext:database needs at least session.url
defined to point at the database. You can specify session.table_name
to point at the table (if you used something other than the default beaker_cache) as well as session.schema_name
if you like to toy with extra settings. Finally session.sa_opts
may be specified with a dictionary of options for the SQLAlchemy engine.
ext:sqla only needs a bind object (SQLAlchemy Engine or Connection object) and a bound SQLAlchemy Table object. It is easy enough to dynamically set these values when calling Pyramid's Configurator. Since the configuration file can only accept strings, neither ext:sqla field can be set in an ini configuration file.
Details: Table schema
The table schema are ever so slightly different as well. ext:database schema followed by ext:sqla schema:
cache = sa.Table(table_name, meta,
sa.Column('id', types.Integer, primary_key=True),
sa.Column('namespace', types.String(255), nullable=False),
sa.Column('accessed', types.DateTime, nullable=False),
sa.Column('created', types.DateTime, nullable=False),
sa.Column('data', types.PickleType, nullable=False),
sa.UniqueConstraint('namespace'),
schema=schema_name if schema_name else meta.schema
)
sa.Table(table_name, metadata,
sa.Column('namespace', sa.String(255), primary_key=True),
sa.Column('accessed', sa.DateTime, nullable=False),
sa.Column('created', sa.DateTime, nullable=False),
sa.Column('data', sa.PickleType, nullable=False),
schema=schema_name if schema_name else metadata.schema)
The ext:database schema will error if used as-is, because id needs to have a default value. In Postgres, simply create the type as Serial instead of Integer to automatically generate default values.
The ext:sqla is a complete subset of the ext:database schema, even though the Primary Keys are different. The PK for ext:sqla is namespace, but since the schema for ext:database makes namespace UNIQUE and NOT NULL, all requirements are met to treat it as a primary key. It would make sense to always implement the ext:database schema in case one wishes to change between ext:sqla and ext:database. ext:sqla makes use of auto-pickling by using SQLAlchemy PickleType for the data column. Creating the table in the backend by hand, rather than allowing ext:sqla to create it, seems to prevent this auto-pickling from taking place.
Apparent key difference
Put something like this into the config file:
sqlalchemy.url = postgresql://user@host.com/particulardb
...
session.type = ext:database
session.url = postgresql://user@host.com/particulardb
Even though the ext:database session.url and sqlalchemy.url are the same database, two connections will be made from the Pyramid instance.
ext:sqla will rectify the creation of two connections; once the sqlalchemy.url is bound to a SQLAlchemy Engine, that Engine may be used by ext:sqla instead of creating a new connection.
I'd think this is a common enough use case (ext:sqla SQLAlchemy Engine = pyramid SQLAlchemy Engine) to have special handling in the static config file. If such special handling exists, I haven't found it.