Commit Graph

265 Commits

Author SHA1 Message Date
Federico Caselli fcbdae075b Add support for the new oracle driver `oracledb`.
Fixes: #8054
Change-Id: Idd7c1bbb7ca39499f53bdf59a63a6a9d65f144a5
2022-06-07 12:59:57 -04:00
Mike Bayer ad14471bc9 Support handle_error for pre_ping
The :meth:`.DialectEvents.handle_error` event is now moved to the
:class:`.DialectEvents` suite from the :class:`.EngineEvents` suite, and
now participates in the connection pool "pre ping" event for those dialects
that make use of disconnect codes in order to detect if the database is
live. This allows end-user code to alter the state of "pre ping". Note that
this does not include dialects which contain a native "ping" method such as
that of psycopg2 or most MySQL dialects.

Fixes: #5648
Change-Id: I353d84a4f66f309d2467b7e67621db6b8c70411e
2022-05-31 15:06:28 -04:00
Mike Bayer 9f0db34563 update for flake8-future-imports 0.0.5
a whole bunch of errors were apparently blocked by 0.0.4
being installed.

Fixes: #8020
Change-Id: I22a0faeaabe03de501897893391946d677c2df7e
2022-05-14 12:28:01 -04:00
Mike Bayer c932123bac pep484: schema API
implement strict typing for schema.py

this module has lots of public API, lots of old decisions
and very hard to follow construction sequences in many
cases, and is also where we get a lot of new feature requests,
so strict typing should help keep things clean.

among improvements here, fixed the pool .info getters
and also figured out how to get ColumnCollection and
related to be covariant so that we may set them up
as returning Column or ColumnClause without any conflicts.

DDL was affected, noting that superclasses of DDLElement
(_DDLCompiles, added recently) can now be passed into
"ddl_if" callables; reorganized ddl into ExecutableDDLElement
as a new name for DDLElement and _DDLCompiles renamed to
BaseDDLElement.

setting up strict also located an API use case that
is completely broken, which is connection.execute(some_default)
returns a scalar value.   This case has been deprecated
and new paths have been set up so that connection.scalar()
may be used.  This likely wasn't possible in previous
versions because scalar() would assume a CursorResult.

The scalar() change also impacts Session as we have explicit
support (since someone had reported it as a regression)
for session.execute(Sequence()) to work.  They will get the
same deprecation message (which omits the word "Connection",
just uses ".execute()" and ".scalar()") and they can then
use Session.scalar() as well.  Getting this to type
correctly while still supporting ORM use cases required
some refactoring, and I also set up a keyword only delimeter
for Session.execute() and related as execution_options /
bind_arguments should always be keyword only, applied these
changes to AsyncSession as well.

Additionally simpify Table __init__ now that we are Python
3 only, we can have positional plus explicit kwargs finally.
Simplify Column.__init__ as well again taking advantage
of kw only arguments.

Fill in most/all __init__ methods in sqltypes.py as
the constructor for types is most of the API.   should
likely do this for dialect-specific types as well.

Apply _InfoType for all info attributes as should have been
done originally and update descriptor decorators.

Change-Id: I3f9f8ff3f1c8858471ff4545ac83d68c88107527
2022-04-15 10:29:23 -04:00
Mike Bayer 169ab546a9 add close=False parameter to engine.dispose()
Added new parameter :paramref:`.Engine.dispose.close`, defaulting to True.
When False, the engine disposal does not touch the connections in the old
pool at all, simply dropping the pool and replacing it. This use case is so
that when the original pool is transferred from a parent process, the
parent process may continue to use those connections.

Fixes: #7877
Change-Id: I88b0808442381ba5e50674787cdb64f0e77d8b54
2022-03-31 09:19:46 -04:00
mike bayer 678e7399e5 Merge "test #7820" into main 2022-03-21 19:57:52 +00:00
Mike Bayer 6c3d738757 pep 484 for types
strict types type_api.py, including TypeDecorator,
NativeForEmulated, etc.

Change-Id: Ib2eba26de0981324a83733954cb7044a29bbd7db
2022-03-19 23:15:15 -04:00
Mike Bayer fc5ec4fa97 test #7820
There was an apparent improvement in the distill params
methodology used in exec_driver_sql which allows raw tuples to
pass through.  In 1.4 there seems to be a _distill_cursor_params()
function that says it can handle this kind of parameter, but it isn't
used and when I tried to substitute it in for exec_driver_sql(),
things still fail.

In any case, add coverage here for the use case of passing
direct tuple params to exec_driver_sql including as the first
param, to note that it isn't mis-interpreted the way it is
in 1.x.

Change-Id: I27b875c0f874aee3f6f0d3e28c4c858dd39344e9
2022-03-14 17:03:59 -04:00
Mike Bayer 4c28867f94 additional mypy strictness
enable type checking within untyped defs.  This allowed
some more internals to be fixed up with assertions etc.

some internals that were unnecessary or not even used
at all were removed.  BaseCursorResult was no longer
necessary since we only have one kind of CursorResult
now.  The different ResultProxy subclasses that had
alternate "strategies" dont appear to be used at all
even in 1.4.x, as there's no code that accesses the
_cursor_strategy_cls attribute, which is also removed.
As these were mostly private constructs that weren't
even functioning correctly in any case,
it's fine to remove these over the 2.0 boundary.

Change-Id: Ifd536987d104b1cd8b546cefdbd5c1e5d1801082
2022-03-12 11:42:50 -05:00
Mike Bayer a4bb502cf9 pep-484 for engine
All modules in sqlalchemy.engine are strictly
typed with the exception of cursor, default, and
reflection.  cursor and default pass with non-strict
typing, reflection is waiting on the multi-reflection
refactor.

Behavioral changes:

* create_connect_args() methods return a tuple of list,
  dict, rather than a list of list, dict
* removed allow_chars parameter from
  pyodbc connector ._get_server_version_info()
  method
* the parameter list passed to do_executemany is now
  a list in all cases. previously, this was being run
  through dialect.execute_sequence_format, which
  defaults to tuple and was only intended for individual
  tuple params.
* broke up dialect.dbapi into dialect.import_dbapi
  class method and dialect.dbapi module object.  added
  a deprecation path for legacy dialects.  it's not
  really feasible to type a single attr as a classmethod
  vs. module type.  The "type_compiler" attribute also
  has this problem with greater ability to work around,
  left that one for now.
* lots of constants changing to be Enum, so that we can
  type them.  for fixed tuple-position constants in
  cursor.py / compiler.py (which are used to avoid the
  speed overhead of namedtuple), using Literal[value]
  which seems to work well
* some tightening up in Row regarding __getitem__, which
  we can do since we are on full 2.0 style result use
* altered the set_connection_execution_options and
  set_engine_execution_options event flows so that the
  dictionary of options may be mutated within the event
  hook, where it will then take effect as the actual
  options used.  Previously, changing the dict would
  be silently ignored which seems counter-intuitive
  and not very useful.
* A lot of DefaultDialect/DefaultExecutionContext
  methods and attributes, including underscored ones, move
  to interfaces.  This is not fully ideal as it means
  the Dialect/ExecutionContext interfaces aren't publicly
  subclassable directly, but their current purpose
  is more of documentation for dialect authors who should
  (and certainly are) still be subclassing the DefaultXYZ
  versions in all cases

Overall, Result was the most extremely difficult class
hierarchy to type here as this hierarchy passes through
largely amorphous "row" datatypes throughout, which
can in fact by all kinds of different things, like
raw DBAPI rows, or Row objects, or "scalar"/Any, but
at the same time these types have meaning so I tried still
maintaining some level of semantic markings for these,
it highlights how complex Result is now, as it's trying
to be extremely efficient and inlined while also being
very open-ended and extensible.

Change-Id: I98b75c0c09eab5355fc7a33ba41dd9874274f12a
2022-03-01 09:09:02 -05:00
Mike Bayer ff1ab665cb mypy: sqlalchemy.util
Starting to set up practices and conventions to
get the library typed.

Key goals for typing are:

1. whole library can pass mypy without any strict
   turned on.
2. we can incrementally turn on some strict flags on a per-package/
   module basis, as here we turn on more strictness for sqlalchemy.util, exc,
   and log
3. mypy ORM plugin tests work fully without sqlalchemy2-stubs
   installed
4. public facing methods all have return types, major parameter
   signatures filled in also
5. Foundational elements like util etc. are typed enough so that
   we can use them in fully typed internals higher up the stack.

Conventions set up here:

1. we can use lots of config in setup.cfg to limit where mypy
   is throwing errors and how detailed it should be in different
   packages / modules.  We can use this to push up gerrits
   that will pass tests fully without everything being typed.
2. a new tox target pep484 is added.  this links to a new jenkins
   pep484 job that works across all projects (alembic, dogpile, etc.)

We've worked around some mypy bugs that will likely
be around for awhile, and also set up some core practices
for how to deal with certain things such as public_factory
modules (mypy won't accept a module from a callable at all,
so need to use simple type checking conditionals).

References: #6810
Change-Id: I80be58029896a29fd9f491aa3215422a8b705e12
2022-01-24 15:14:01 -05:00
Federico Caselli 76fa211620 Replace c extension with cython versions.
Re-implement c version immutabledict / processors / resultproxy / utils with cython.
Performance is in general in par or better than the c version
Added a collection module that has cython version of OrderedSet and IdentitySet

Added a new test/perf file to compare the implementations.
Run ``python test/perf/compiled_extensions.py all`` to execute the comparison test.

See results here: https://docs.google.com/document/d/1nOcDGojHRtXEkuy4vNXcW_XOJd9gqKhSeALGG3kYr6A/edit?usp=sharing

Fixes: #7256
Change-Id: I2930ef1894b5048210384728118e586e813f6a76
Signed-off-by: Federico Caselli <cfederico87@gmail.com>
2021-12-17 21:29:05 +01:00
Mike Bayer 22deafe152 Warn when caching is disabled / document
This patch adds new warnings for all elements that
don't indicate their caching behavior, including user-defined
ClauseElement subclasses and third party dialects.
it additionally adds new documentation to discuss an apparent
performance degradation in 1.4 when caching is disabled as a
result in the significant expense incurred by ORM
lazy loaders, which in 1.3 used BakedQuery so were actually
cached.

As a result of adding the warnings, a fair degree of
lesser used SQL expression objects identified that they did not
define caching behavior so would have been producing
``[no key]``, including PostgreSQL constructs ``hstore``
and ``array``.  These have been amended to use inherit
cache where appropriate.  "on conflict" constructs in
PostgreSQL, MySQL, SQLite still explicitly don't generate
a cache key at this time.

The change also adds a test for all constructs via
assert_compile() to assert they will not generate cache
warnings.

Fixes: #7394
Change-Id: I85958affbb99bfad0f5efa21bc8f2a95e7e46981
2021-12-06 18:27:19 -05:00
mike bayer 8ddb3ef165 Merge "propose emulated setinputsizes embedded in the compiler" into main 2021-11-25 18:22:59 +00:00
Federico Caselli 31acba8ff7 Clean up most py3k compat
Change-Id: I8172fdcc3103ff92aa049827728484c8779af6b7
2021-11-24 22:51:27 -05:00
Mike Bayer 939de240d3 propose emulated setinputsizes embedded in the compiler
Add a new system so that PostgreSQL and other dialects have a
reliable way to add casts to bound parameters in SQL statements,
replacing previous use of setinputsizes() for PG dialects.

rationale:

1. psycopg3 will be using the same SQLAlchemy-side "setinputsizes"
   as asyncpg, so we will be seeing a lot more of this

2. the full rendering that SQLAlchemy's compilation is performing
   is in the engine log as well as error messages.   Without this,
   we introduce three levels of SQL rendering, the compiler, the
   hidden "setinputsizes" in SQLAlchemy, and then whatever the DBAPI
   driver does.  With this new approach, users reporting bugs etc.
   will be less confused that there are as many as two separate
   layers of "hidden rendering"; SQLAlchemy's rendering is again
   fully transparent

3. calling upon a setinputsizes() method for every statement execution
   is expensive.  this way, the work is done behind the caching layer

4. for "fast insertmany()", I also want there to be a fast approach
   towards setinputsizes.  As it was, we were going to be taking
   a SQL INSERT with thousands of bound parameter placeholders and
   running a whole second pass on it to apply typecasts.    this way,
   we will at least be able to build the SQL string once without a huge
   second pass over the whole string

5. psycopg2 can use this same system for its ARRAY casts

6. the general need for PostgreSQL to have lots of type casts
   is now mostly in the base PostgreSQL dialect and works independently
   of a DBAPI being present.   dependence on DBAPI symbols that aren't
   complete / consistent / hashable is removed

I was originally going to try to build this into bind_expression(),
but it was revealed this worked poorly with custom bind_expression()
as well as empty sets.   the current impl also doesn't need to
run a second expression pass over the POSTCOMPILE sections, which
came out better than I originally thought it would.

Change-Id: I363e6d593d059add7bcc6d1f6c3f91dd2e683c0c
2021-11-23 16:52:55 -05:00
Federico Caselli 0b95f0055b Remove object in class definition
References: #4600
Change-Id: I2a62ddfe00bc562720f0eae700a497495d7a987a
2021-11-22 15:03:17 +00:00
mike bayer c0b0bf8ab8 Merge "Deprecate create_engine.implicit_returning" into main 2021-11-18 16:11:35 +00:00
mike bayer 863a048790 Merge "change the POSTCOMPILE/ SCHEMA symbols to not conflict w mssql quoting" into main 2021-11-09 23:52:28 +00:00
Mike Bayer b919a0a85a change the POSTCOMPILE/ SCHEMA symbols to not conflict w mssql quoting
Adjusted the compiler's generation of "post compile" symbols including
those used for "expanding IN" as well as for the "schema translate map" to
not be based directly on plain bracketed strings with underscores, as this
conflicts directly with SQL Server's quoting format of also using brackets,
which produces false matches when the compiler replaces "post compile" and
"schema translate" symbols. The issue created easy to reproduce examples
both with the :meth:`.Inspector.get_schema_names` method when used in
conjunction with the
:paramref:`_engine.Connection.execution_options.schema_translate_map`
feature, as well in the unlikely case that a symbol overlapping with the
internal name "POSTCOMPILE" would be used with a feature like "expanding
in".

Fixes: #7300
Change-Id: I6255c850b140522a4aba95085216d0bca18ce230
2021-11-09 15:30:58 -05:00
jonathan vanasco b2df5be7ee Deprecate create_engine.implicit_returning
The :paramref:`_sa.create_engine.implicit_returning` parameter is
deprecated on the :func:`_sa.create_engine` function only; the parameter
remains available on the :class:`_schema.Table` object. This parameter was
originally intended to enable the "implicit returning" feature of
SQLAlchemy when it was first developed and was not enabled by default.
Under modern use, there's no reason this parameter should be disabled, and
it has been observed to cause confusion as it degrades performance and
makes it more difficult for the ORM to retrieve recently inserted server
defaults. The parameter remains available on :class:`_schema.Table` to
specifically suit database-level edge cases which make RETURNING
infeasible, the sole example currently being SQL Server's limitation that
INSERT RETURNING may not be used on a table that has INSERT triggers on it.

Also removed from the Oracle dialect some logic that would upgrade
an Oracle 8/8i server version to use implicit returning if the
parameter were explictly passed; these versions of Oracle
still support RETURNING so the feature is now enabled for all
Oracle versions.

Fixes: #6962
Change-Id: Ib338e300cd7c8026c3083043f645084a8211aed8
2021-11-09 11:34:48 -05:00
Gord Thompson bd1be0b7e0 De-emphasize notion of "default driver" (DBAPI)
Fixes: #6960

Even though a default driver still exists for
each dialect, remove most usages of `dialect://`
to encourage users to explicitly specify
`dialect+driver://`

Change-Id: I0ad42167582df509138fca64996bbb53e379b1af
2021-11-09 06:12:39 -07:00
Mike Bayer d050193daa fully implement future engine and remove legacy
The major action here is to lift and move future.Connection
and future.Engine fully into sqlalchemy.engine.base.   This
removes lots of engine concepts, including:

* autocommit
* Connection running without a transaction, autobegin
  is now present in all cases
* most "autorollback" is obsolete
* Core-level subtransactions (i.e. MarkerTransaction)
* "branched" connections, copies of connections
* execution_options() returns self, not a new connection
* old argument formats, distill_params(), simplifies calling
  scheme between engine methods
* before/after_execute() events (oriented towards compiled constructs)
  don't emit for exec_driver_sql().  before/after_cursor_execute()
  is still included for this
* old helper methods superseded by context managers, connection.transaction(),
  engine.transaction() engine.run_callable()
* ancient engine-level reflection methods has_table(), table_names()
* sqlalchemy.testing.engines.proxying_engine

References: #7257

Change-Id: Ib20ed816642d873b84221378a9ec34480e01e82c
2021-11-07 14:30:35 -05:00
Mike Bayer 248d232459 Check for Mapping explicitly in 2.0 params
Fixed issue in future :class:`_future.Connection` object where the
:meth:`_future.Connection.execute` method would not accept a non-dict
mapping object, such as SQLAlchemy's own :class:`.RowMapping` or other
``abc.collections.Mapping`` object as a parameter dictionary.

Fixes: #7291
Change-Id: I819f079d86d19d1d81c570e0680f987e51e34b84
2021-11-04 18:07:21 -04:00
mike bayer 72780bae33 Merge "First round of removal of python 2" into main 2021-11-02 20:51:28 +00:00
Mike Bayer c4abf5a442 use full context manager flow for future.Engine.begin()
Fixed issue in future :class:`_future.Engine` where calling upon
:meth:`_future.Engine.begin` and entering the context manager would not
close the connection if the actual BEGIN operation failed for some reason,
such as an event handler raising an exception; this use case failed to be
tested for the future version of the engine. Note that the "future" context
managers which handle ``begin()`` blocks in Core and ORM don't actually run
the "BEGIN" operation until the context managers are actually entered. This
is different from the legacy version which runs the "BEGIN" operation up
front.

Fixes: #7272
Change-Id: I9667ac0861a9e007c4b3dfcf0fcf0829038a8711
2021-11-01 16:37:31 -04:00
Federico Caselli 36e7aebd8d First round of removal of python 2
References: #4600
Change-Id: I61e35bc93fe95610ae75b31c18a3282558cd4ffe
2021-11-01 15:11:25 -04:00
Federico Caselli ed78e679ea Remove deprecated dialects and drivers
Fixes: #7258
Change-Id: I3577f665eca04f2632b69bcb090f0a4ec9271db9
2021-10-31 12:31:56 -04:00
Federico Caselli 26140c0811 Surface driver connection object when using a proxied dialect
Improve the interface used by adapted drivers, like the asyncio ones,
to access the actual connection object returned by the driver.

The :class:`_engine._ConnectionRecord` and
:class:`_engine._ConnectionFairy` now have two new attributes:

* ``dbapi_connection`` always represents a DBAPI compatible
object.  For pep-249 drivers, this is the DBAPI connection as it always
has been, previously accessed under the ``.connection`` attribute.
For asyncio drivers that SQLAlchemy adapts into a pep-249 interface,
the returned object will normally be a SQLAlchemy adaption object
called :class:`_engine.AdaptedConnection`.
* ``driver_connection`` always represents the actual connection object
maintained by the third party pep-249 DBAPI or async driver in use.
For standard pep-249 DBAPIs, this will always be the same object
as that of the ``dbapi_connection``.  For an asyncio driver, it will be
the underlying asyncio-only connection object.

The ``.connection`` attribute remains available and is now a legacy alias
of ``.dbapi_connection``.

Fixes: #6832
Change-Id: Ib72f97deefca96dce4e61e7c38ba430068d6a82e
2021-09-17 18:08:42 -04:00
Miguel Grinberg 4127482cc5 Add scalars method to connection and session classes
Added new methods :meth:`_orm.Session.scalars`,
:meth:`_engine.Connection.scalars`, :meth:`_asyncio.AsyncSession.scalars`
and :meth:`_asyncio.AsyncSession.stream_scalars`, which provide a short cut
to the use case of receiving a row-oriented :class:`_result.Result` object
and converting it to a :class:`_result.ScalarResult` object via the
:meth:`_engine.Result.scalars` method, to return a list of values rather
than a list of rows. The new methods are analogous to the long existing
:meth:`_orm.Session.scalar` and :meth:`_engine.Connection.scalar` methods
used to return a single value from the first row only. Pull request
courtesy Miguel Grinberg.

Fixes: #6990
Closes: #6991
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/6991
Pull-request-sha: b3e0bb3042

Change-Id: Ia445775e24ca964b0162c2c8e5ca67dd1e39199f
2021-09-14 12:58:37 -04:00
Mike Bayer f9ba830ec0 restore statement substitution to before_execute()
Fixed issue where the ability of the
:meth:`_engine.ConnectionEvents.before_execute` method to alter the SQL
statement object passed, returning the new object to be invoked, was
inadvertently removed. This behavior has been restored.

The refactor in a1939719a6 removed this
feature for some reason and there were no tests in place to detect
it.  I don't see any indication this was planned.

Fixes: #6913
Change-Id: Ia77ca08aa91ab9403f19a8eb61e2a0e41aad138a
2021-08-20 22:17:55 -04:00
Mike Bayer 707e5d70fc labeling refactor
To service #6718 and #6710, the system by which columns are
given labels in a SELECT statement as well as the system that
gives them keys in a .c or .selected_columns collection have
been refactored to provide a single source of truth for
both, in constrast to the previous approach that included
similar logic repeated in slightly different ways.

Main ideas:

1. ColumnElement attributes ._label, ._anon_label, ._key_label
   are renamed to include the letters "tq", meaning
   "table-qualified" - these labels are only used when rendering
   a SELECT that has LABEL_STYLE_TABLENAME_PLUS_COL for its
   label style; as this label style is primarily legacy, the
   "tq" names should be isolated so that in a 2.0 style application
   these aren't being used at all

2. The means by which the "labels" and "proxy keys" for the elements
   of a SELECT has been centralized to a single source of truth;
   previously, the three of _generate_columns_plus_names,
   _generate_fromclause_column_proxies, and _column_naming_convention
   all had duplicated rules between them, as well as that there
   were a little bit of labeling rules in compiler._label_select_column
   as well; by this we mean that the various "anon_label" "anon_key"
   methods on ColumnElement were called by all four of these methods,
   where there were many cases where it was necessary that one method
   comes up with the same answer as another of the methods.  This
   has all been centralized into _generate_columns_plus_names
   for all the names except the "proxy key", which is generated
   by _column_naming_convention.

3. compiler._label_select_column has been rewritten to both not make
   any naming decisions nor any "proxy key" decisions, only whether
   to label or not to label; the _generate_columns_plus_names method
   gives it the information, where the proxy keys come from
   _column_naming_convention; previously, these proxy keys were matched
   based on restatement of similar (but not really the same) logic in
   two places.   The heuristics of "whether to label or not to label"
   are also reorganized to be much easier to read and understand.

4. a new method compiler._label_returning_column is added for dialects
   to use in their "generate returning columns" methods.   A
   github search reveals a small number of third party dialects also
   doing this using the prior _label_select_column method so we
   try to make sure _label_select_column continues to work the
   exact same way for that specific use case; for the "SELECT" use
   case it now needs

5. After some attempts to do it different ways, for the case where
   _proxy_key is giving us some kind of anon label, we are hard
   changing it to "_no_label" right now, as there's not currently
   a way to fully match anonymized labels from stmt.c or
   stmt.selected_columns to what will be in the result map.  The
   idea of "_no_label" is to encourage the user to use label('name')
   for columns they want to be able to target by string name that
   don't have a natural name.

Change-Id: I7a92a66f3a7e459ccf32587ac0a3c306650daf11
2021-07-12 18:50:29 -04:00
Mike Bayer 6967b45020 don't cache TypeDecorator by default
The :class:`.TypeDecorator` class will now emit a warning when used in SQL
compilation with caching unless the ``.cache_ok`` flag is set to ``True``
or ``False``. ``.cache_ok`` indicates that all the parameters passed to the
object are safe to be used as a cache key, ``False`` means they are not.

Fixes: #6436
Change-Id: Ib1bb7dc4b124e38521d615c2e2e691e4915594fb
2021-05-06 13:57:43 -04:00
Mike Bayer 37414a752b Add new "sync once" mode for pool.connect
Fixed critical regression caused by the change in :ticket`5497` where the
connection pool "init" phase no longer occurred within mutexed isolation,
allowing other threads to proceed with the dialect uninitialized, which
could then impact the compilation of SQL statements.

This issue is essentially the same regression which was fixed many years
ago in 🎫`2964` in dd32540dab,
which was missed this time as the test suite fo
that issue only tested the pool in isolation, and assumed the
"first_connect" event would be used by the Engine.  However
🎫`5497` stopped using "first_connect" and no test detected
the lack of mutexing, that has been resolved here through
the addition of more tests.

This fix also identifies what is probably a bug in earlier versions
of SQLAlchemy where the "first_connect" handler would be cancelled
if the initializer failed; this is evidenced by
test_explode_in_initializer which was doing a reconnect due to
c.rollback() yet wasn't hanging.  We now solve this issue by
preventing the manufactured Connection from ever reconnecting
inside the first_connect handler.

Also remove the "_sqla_unwrap" test attribute; this is almost
not used anymore however we can use a more targeted
wrapper supplied by the testing.engines.proxying_engine
function.

See if we can also open up Oracle for "ad hoc engines" tests
now that we have better connection management logic.

Fixes: #6337
Change-Id: I4a3476625c4606f1a304dbc940d500325e8adc1a
2021-04-21 22:31:42 -04:00
Mike Bayer b26cf96462 Explicitly test for Connection in dialect.has_table()
The :meth:`_engine.Dialect.has_table` method now raises an informative
exception if a non-Connection is passed to it, as this incorrect behavior
seems to be common.  This method is not intended for external use outside
of a dialect.  Please use the :meth:`.Inspector.has_table` method
or for cross-compatibility with older SQLAlchemy versions, the
:meth:`_engine.Engine.has_table` method.

Fixes: #5780
Fixes: #6062
Fixes: #6260
Change-Id: I9b2439675167019b68d682edee3dcdcfce836987
2021-04-14 12:14:12 -04:00
Mike Bayer ac2ed15740 Disallow AliasedReturnsRows from execution
Executing a :class:`_sql.Subquery` using :meth:`_engine.Connection.execute`
is deprecated and will emit a deprecation warning; this use case was an
oversight that should have been removed from 1.4. The operation will now
execute the underlying :class:`_sql.Select` object directly for backwards
compatibility. Similarly, the :class:`_sql.CTE` class is also not
appropriate for execution. In 1.3, attempting to execute a CTE would result
in an invalid "blank" SQL statement being executed; since this use case was
not working it now raises :class:`_exc.ObjectNotExecutableError`.
Previously, 1.4 was attempting to execute the CTE as a statement however it
was working only erratically.

The change also breaks out StatementRole from ReturnsRowsRole, as these
roles should not be in the same lineage (some statements don't return
rows, the whole class of ReturnsRows that are from clauses are
not statements).    Consolidate StatementRole and
CoerceTextStatementRole as there's no usage difference between
these.   Simplify some old tests that were trying to make
sure that "execution options" didn't transmit from a cte/subquery
out to a select; as cte/subuqery() aren't executable in any case
the options are removed.

Fixes: #6204
Change-Id: I62613b7ab418afdd22c409eae75659e3f52fb65f
2021-04-05 23:35:53 -04:00
Mike Bayer 20c0f774e5 Default caching to opt-out for 3rd party dialects
Added a new flag to the :class:`_engine.Dialect` class called
:attr:`_engine.Dialect.supports_statement_cache`. This flag now needs to be present
directly on a dialect class in order for SQLAlchemy's
:ref:`query cache <sql_caching>` to take effect for that dialect. The
rationale is based on discovered issues such as 🎫`6173` revealing
that dialects which hardcode literal values from the compiled statement,
often the numerical parameters used for LIMIT / OFFSET, will not be
compatible with caching until these dialects are revised to use the
parameters present in the statement only. For third party dialects where
this flag is not applied, the SQL logging will show the message "dialect
does not support caching", indicating the dialect should seek to apply this
flag once they have verified that no per-statement literal values are being
rendered within the compilation phase.

Fixes: #6184
Change-Id: I6fd5b5d94200458d4cb0e14f2f556dbc25e27e22
2021-04-01 18:59:41 -04:00
Federico Caselli 502be87a0b Add support for aiosqlite
Added support for the aiosqlite database driver for use with the
SQLAlchemy asyncio extension.

Fixes: #5920
Change-Id: Id11a320516a44e886a6f518d2866a0f992413e55
2021-03-24 11:45:39 -04:00
Mike Bayer c5b4af959e Guard against re-entrant autobegin in Core, ORM
Fixed bug in "future" version of :class:`.Engine` where emitting SQL during
the :meth:`.EngineEvents.do_begin` event hook would cause a re-entrant
condition due to autobegin, including the recipe documented for SQLite to
allow for savepoints and serializable isolation support.

Fixed issue in new :class:`_orm.Session` similar to that of the
:class:`_engine.Connection` where the new "autobegin" logic could be
tripped into a re-entrant state if SQL were executed within the
:meth:`.SessionEvents.after_transaction_create` event hook.

Also repair the new "testing_engine" pytest fixture to
set up for "future" engine appropriately, which wasn't working
leading to the test_execute.py tests not using the future
engine since recent f1e96cb087.

Fixes: #5845
Change-Id: Ib2432d8c8bd753e24be60720ec47affb2df15a4a
2021-01-15 20:14:34 -05:00
Mike Bayer ebbbac0a76 update execute() arg formats in modules and tests
continuing with producing a SQLAlchemy 1.4.0b2 that internally
does not emit any of its own 2.0 deprecation warnings,
migrate the *args and **kwargs passed to execute() methods
that now must be a single list or dictionary.

Alembic 1.5 is again waiting on this internal consistency to
be present so that it can pass all tests with no 2.0
deprecation warnings.

Change-Id: If6b792e57c8c5dff205419644ab68e631575a2fa
2021-01-15 13:04:58 -05:00
Mike Bayer f1e96cb087 reinvent xdist hooks in terms of pytest fixtures
To allow the "connection" pytest fixture and others work
correctly in conjunction with setup/teardown that expects
to be external to the transaction, remove and prevent any usage
of "xdist" style names that are hardcoded by pytest to run
inside of fixtures, even function level ones.   Instead use
pytest autouse fixtures to implement our own
r"setup|teardown_test(?:_class)?" methods so that we can ensure
function-scoped fixtures are run within them.   A new more
explicit flow is set up within plugin_base and pytestplugin
such that the order of setup/teardown steps, which there are now
many, is fully documented and controllable.   New granularity
has been added to the test teardown phase to distinguish
between "end of the test" when lock-holding structures on
connections should be released to allow for table drops,
vs. "end of the test plus its teardown steps" when we can
perform final cleanup on connections and run assertions
that everything is closed out.

From there we can remove most of the defensive "tear down everything"
logic inside of engines which for many years would frequently dispose
of pools over and over again, creating for a broken and expensive
connection flow.  A quick test shows that running test/sql/ against
a single Postgresql engine with the new approach uses 75% fewer new
connections, creating 42 new connections total, vs. 164 new
connections total with the previous system.

As part of this, the new fixtures metadata/connection/future_connection
have been integrated such that they can be combined together
effectively.  The fixture_session(), provide_metadata() fixtures
have been improved, including that fixture_session() now strongly
references sessions which are explicitly torn down before
table drops occur afer a test.

Major changes have been made to the
ConnectionKiller such that it now features different "scopes" for
testing engines and will limit its cleanup to those testing
engines corresponding to end of test, end of test class, or
end of test session.   The system by which it tracks DBAPI
connections has been reworked, is ultimately somewhat similar to
how it worked before but is organized more clearly along
with the proxy-tracking logic.  A "testing_engine" fixture
is also added that works as a pytest fixture rather than a
standalone function.  The connection cleanup logic should
now be very robust, as we now can use the same global
connection pools for the whole suite without ever disposing
them, while also running a query for PostgreSQL
locks remaining after every test and assert there are no open
transactions leaking between tests at all.  Additional steps
are added that also accommodate for asyncio connections not
explicitly closed, as is the case for legacy sync-style
tests as well as the async tests themselves.

As always, hundreds of tests are further refined to use the
new fixtures where problems with loose connections were identified,
largely as a result of the new PostgreSQL assertions,
many more tests have moved from legacy patterns into the newest.

An unfortunate discovery during the creation of this system is that
autouse fixtures (as well as if they are set up by
@pytest.mark.usefixtures) are not usable at our current scale with pytest
4.6.11 running under Python 2.  It's unclear if this is due
to the older version of pytest or how it implements itself for
Python 2, as well as if the issue is CPU slowness or just large
memory use, but collecting the full span of tests takes over
a minute for a single process when any autouse fixtures are in
place and on CI the jobs just time out after ten minutes.
So at the moment this patch also reinvents a small version of
"autouse" fixtures when py2k is running, which skips generating
the real fixture and instead uses two global pytest fixtures
(which don't seem to impact performance) to invoke the
"autouse" fixtures ourselves outside of pytest.
This will limit our ability to do more with fixtures
until we can remove py2k support.

py.test is still observed to be much slower in collection in the
4.6.11 version compared to modern 6.2 versions, so add support for new
TOX_POSTGRESQL_PY2K and TOX_MYSQL_PY2K environment variables that
will run the suite for fewer backends under Python 2.  For Python 3
pin pytest to modern 6.2 versions where performance for collection
has been improved greatly.

Includes the following improvements:

Fixed bug in asyncio connection pool where ``asyncio.TimeoutError`` would
be raised rather than :class:`.exc.TimeoutError`.  Also repaired the
:paramref:`_sa.create_engine.pool_timeout` parameter set to zero when using
the async engine, which previously would ignore the timeout and block
rather than timing out immediately as is the behavior with regular
:class:`.QueuePool`.

For asyncio the connection pool will now also not interact
at all with an asyncio connection whose ConnectionFairy is
being garbage collected; a warning that the connection was
not properly closed is emitted and the connection is discarded.
Within the test suite the ConnectionKiller is now maintaining
strong references to all DBAPI connections and ensuring they
are released when tests end, including those whose ConnectionFairy
proxies are GCed.

Identified cx_Oracle.stmtcachesize as a major factor in Oracle
test scalability issues, this can be reset on a per-test basis
rather than setting it to zero across the board.  the addition
of this flag has resolved the long-standing oracle "two task"
error problem.

For SQL Server, changed the temp table style used by the
"suite" tests to be the double-pound-sign, i.e. global,
variety, which is much easier to test generically.  There
are already reflection tests that are more finely tuned
to both styles of temp table within the mssql test
suite.  Additionally, added an extra step to the
"dropfirst" mechanism for SQL Server that will remove
all foreign key constraints first as some issues were
observed when using this flag when multiple schemas
had not been torn down.

Identified and fixed two subtle failure modes in the
engine, when commit/rollback fails in a begin()
context manager, the connection is explicitly closed,
and when "initialize()" fails on the first new connection
of a dialect, the transactional state on that connection
is still rolled back.

Fixes: #5826
Fixes: #5827
Change-Id: Ib1d05cb8c7cf84f9a4bfd23df397dc23c9329bfe
2021-01-13 22:10:13 -05:00
Mike Bayer fd3c063dd6 remove metadata.bind use from test suite
importantly this means we can remove bound metadata from
the fixtures that are used by Alembic's test suite.

hopefully this is the last one that has to happen to allow
Alembic to be fully 1.4/2.0.

Start moving from @testing.provide_metadata to a pytest
metadata fixture.  This does not seem to have any negative
effects even though TablesTest uses a "self.metadata" attribute.

Change-Id: Iae6ab95938a7e92b6d42086aec534af27b5577d3
2021-01-03 13:22:29 -05:00
Mike Bayer dd41a5e61a Cache asyngpg prepared statements
Enhanced the performance of the asyncpg dialect by caching the asyncpg
PreparedStatement objects on a per-connection basis. For a test case that
makes use of the same statement on a set of pooled connections this appears
to grant a 10-20% speed improvement.  The cache size is adjustable and may
also be disabled.

Unfortunately the caching gets more complicated when there are
schema changes present.  An invalidation scheme is now also added
to accommodate for prepared statements as well as asyncpg cached OIDs.
However, the exception raises cannot be prevented if DDL has changed
database structures that were cached for a particular asyncpg
connection.  Logic is added to clear the caches when these errors occur.

Change-Id: Icf02aa4871eb192f245690f28be4e9f9c35656c6
2021-01-02 22:09:39 -05:00
Mike Bayer ba5cbf9366 correct for "autocommit" deprecation warning
Ensure no autocommit warnings occur internally or
within tests.

Also includes fixes for SQL Server full text tests
which apparently have not been working at all for a long
time, as it used long removed APIs.  CI has not had
fulltext running for some years and is now installed.

Change-Id: Id806e1856c9da9f0a9eac88cebc7a94ecc95eb96
2020-12-11 13:26:05 -05:00
Mike Bayer 9b779611f9 Support pool.connect() event firing before all else
Fixed regression where a connection pool event specified with a keyword,
most notably ``insert=True``, would be lost when the event were set up.
This would prevent startup events that need to fire before dialect-level
events from working correctly.

The internal mechanics of the engine connection routine has been altered
such that it's now guaranteed that a user-defined event handler for the
:meth:`_pool.PoolEvents.connect` handler, when established using
``insert=True``, will allow an event handler to run that is definitely
invoked **before** any dialect-specific initialization starts up, most
notably when it does things like detect default schema name.
Previously, this would occur in most cases but not unconditionally.
A new example is added to the schema documentation illustrating how to
establish the "default schema name" within an on-connect event
(upcoming as part of I882edd5bbe06ee5b4d0a9c148854a57b2bcd4741)

Addiional changes to support setting default schema name:

The Oracle dialect now uses
``select sys_context( 'userenv', 'current_schema' ) from dual`` to get
the default schema name, rather than ``SELECT USER FROM DUAL``, to
accommodate for changes to the session-local schema name under Oracle.

Added a read/write ``.autocommit`` attribute to the DBAPI-adaptation layer
for the asyncpg dialect.   This so that when working with DBAPI-specific
schemes that need to use "autocommit" directly with the DBAPI connection,
the same ``.autocommit`` attribute which works with both psycopg2 as well
as pg8000 is available.

Fixes: #5716
Fixes: #5708
Change-Id: I7dce56b4345ffc720e25e2aaccb7e42bb29e5671
2020-11-19 13:40:54 -05:00
mike bayer 3179f70408 Merge "Add deprecation for base Executable.bind" 2020-10-17 14:11:48 +00:00
Mike Bayer 5162f2bc5f Add deprecation for base Executable.bind
These attributes will be removed in SQLAlchemy 2.0.

Also alters the deprecation message to qualify the
type of object correctly.  this in turn requires changes
in the warnings filter and deprecation tests.

Change-Id: I5779d9813e88f42e5db0c7b5e3ffff1d1535c203
2020-10-16 19:15:58 -04:00
Mike Bayer 87c24c498c Genericize setinputsizes and support pyodbc
Reworked the "setinputsizes()" set of dialect hooks to be correctly
extensible for any arbirary DBAPI, by allowing dialects individual hooks
that may invoke cursor.setinputsizes() in the appropriate style for that
DBAPI.   In particular this is intended to support pyodbc's style of usage
which is fundamentally different from that of cx_Oracle.  Added support
for pyodbc.

Fixes: #5649
Change-Id: I9f1794f8368bf3663a286932cfe3992dae244a10
2020-10-16 14:28:04 -04:00
Mike Bayer c3f102c9fe upgrade to black 20.8b1
It's better, the majority of these changes look more readable to me.
also found some docstrings that had formatting / quoting issues.

Change-Id: I582a45fde3a5648b2f36bab96bad56881321899b
2020-09-28 15:17:26 -04:00
Andrzej Bartosiński c4f28fb414 Stringify correctly for non-str exception argument
Fixed issue where a non-string object sent to
:class:`_exc.SQLAlchemyError` or a subclass, as occurs with some third
party dialects, would fail to stringify correctly. Pull request
courtesy Andrzej Bartosiński.

Fixes: #5599
Closes: #5600
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5600
Pull-request-sha: cdccccc42a

Change-Id: Icd710d9015abc80f61a84893d75fbb33ee0fe46e
2020-09-20 14:09:23 -04:00