Commit Graph

803 Commits

Author SHA1 Message Date
Mike Bayer 0718add371 Deprecate bind args, execute() methods that were missed
in particular text(bind), DDL.execute().

Change-Id: Ie85ae9f61219182f5649f68e5f52b4923843199c
2020-10-30 20:22:13 -04:00
Mike Bayer e9051d9b44 Add FAQ entry for retry subject; recipe w/ autocommit
In order to invalidate a connection within a Transaction
block and an execution context, we need to take advantage
of the simpler transaction design added in 1.4.  The recipe
can be done on 1.3 but it requires a lot more hacking
and isn't worth it.

Clearly since the recipe is part of the tests now we can
in the future consider adding a feature that's built
in for this case but it would have to absolutely guarantee
the DBAPI is in autocommit mode and also prevent
any "write" operations from taking place.   Recipe for now.

Fixes: #5657
Change-Id: Ia9ea8cced084d154e83e4d1c259e080b776ec38a
2020-10-19 18:48:58 -04: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 3ca8b45308 Revert "Use monotonic time for pool age measurement"
This reverts commit 0220b58917.

I completely misread https://www.python.org/dev/peps/pep-0418/#rationale
and the accuracy of monotonic() is *worse* on windows than time.time(),
which is bizarre.

Change-Id: I2d571e268a2051bea68736507773d3904403af9e
2020-10-07 10:09:41 -04:00
Mike Bayer bb32b59cd4 force a sleep for test_reconnect
as I dont have a windows machine to test I don't really know
how to get a millisecond-accurate timer for windows,
Python documentation claimed time.monotonic() did this however
the continued failure of test_reconnect indicates this is not the case
and that the timer is still bumping up by multi-millisecond
granularity.   force a delay instead.

Change-Id: I237b223eabc55c1d47ecece13873be1f7be20e47
2020-10-07 09:49:40 -04:00
Mike Bayer 0220b58917 Use monotonic time for pool age measurement
The internal clock used by the :class:`_pool.Pool` object is now
time.monotonic_time() under Python 3.  Under Python 2, time.time() is still
used, which is legacy. This clock is used to measure the age of a
connection against its starttime, and used in comparisons against the
pool_timeout setting as well as the last time the pool was marked as
invalid to determine if the connection should be recycled. Previously,
time.time() was used which was subject to inaccuracies as a result of
system clock changes as well as poor time resolution on windows.

Change-Id: I94f90044c1809508e26a5a00134981c2a00d0405
2020-10-07 09:14:13 -04:00
Mike Bayer 42b761aefb add --notimingintensive; block from github jobs
this provides a front-end option to disable tests marked
as timing_intensive, all of which are in test_pool, which are more
fragile and aren't consistent on the
github runners.   also remove /reduce unnecessary time.sleep()
from two other pool tests that are not timing intensive.

note that this removes test_hanging_connect_within_overflow
from the github runs via the timing_intensive requirement.

I've also removed MockReconnectTest from exclusions as those are
really important tests and they use mocks so should not have
platform dependent issues.   Need to see what the
windows failures are.

Closes: #5633
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5633
Pull-request-sha: 166833e16e

Change-Id: Icb3d284a2a952e2495d80fa91e22e0b32a54340f
2020-10-07 00:16:53 -04:00
Federico Caselli c68f9fb878 Enable pypy tests on github workflow
Fixes: #5223
Change-Id: I0952e54ed9af2952ea340be1945311376ffc1ad2
2020-10-02 21:21:11 +02:00
Federico Caselli 7362d454f4 Add reflection for Identity columns
Added support for reflecting "identity" columns, which are now returned
as part of the structure returned by :meth:`_reflection.Inspector.get_columns`.
When reflecting full :class:`_schema.Table` objects, identity columns will
be represented using the :class:`_schema.Identity` construct.

Fixed compilation error on oracle for sequence and identity column
``nominvalue`` and ``nomaxvalue`` options that require no space in them.

Improved test compatibility with oracle 18.

As part of the support for reflecting :class:`_schema.Identity` objects,
the method :meth:`_reflection.Inspector.get_columns` no longer returns
``mssql_identity_start`` and ``mssql_identity_increment`` as part of the
``dialect_options``. Use the information in the ``identity`` key instead.

The mssql dialect will assume that at least MSSQL 2005 is used.
There is no hard exception raised if a previous version is detected,
but operations may fail for older versions.

Fixes: #5527
Fixes: #5324
Change-Id: If039fe637c46b424499e6bac54a2cbc0dc54cb57
2020-09-28 18:11:12 -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
Mike Bayer 7e864fc7b1 Create a framework to allow all SQLALCHEMY_WARN_20 to pass
As the test suite has widespread use of many patterns
that are deprecated, enable SQLALCHEMY_WARN_20 globally
for the test suite but then break the warnings filter
out into a whole list of all the individual warnings
we are looking for.  this way individual changesets
can target a specific class of warning, as many of these
warnings will indivdidually affect dozens of files
and potentially hundreds of lines of code.

Many warnings are also resolved here as this
patch started out that way.   From this point
forward there should be changesets that target a
subset of the warnings at a time.

For expediency, updates some migration 2.0 docs
for ORM as well.

Change-Id: I98b8defdf7c37b818b3824d02f7668e3f5f31c94
2020-09-16 12:31:05 -04:00
Mike Bayer 3d803a8ed3 Pass all pool parameters in recreate()
The following pool parameters were not being propagated to the new pool
created when :meth:`_engine.Engine.dispose` were called: ``pre_ping``,
``use_lifo``.  Additionally the ``recycle`` and ``reset_on_return``
parameters were not propagated for the :class:`_engine.AssertionPool`
class.  These issues have been fixed.

Fixes: #5582
Change-Id: Ifdb703aa7e849652242b9ff8071c854cd1d77e71
2020-09-14 11:36:31 -04:00
Mike Bayer 25b8e89d3d Deprecate engine-wise ss cursors; repair mariadbconnector
The server_side_cursors engine-wide feature relies upon
regexp parsing of statements a well as general guessing as
to when the feature should be used.   This is not within the
2.0 way of doing things and should be removed.

Additionally, mariadbconnector defaults to unbuffered cursors;
add new cursor hooks so that mariadbconnector can specify
buffered or unbuffered cursors without too much difficulty.
This will also correctly default mariadbconnector to buffered
cursors which should repair the segfaults we've been getting.

Try to restore the assert_raises that was removed in
5b6dfc0c38 to see if mariadbconnector segfaults
are resolved.

Change-Id: I77f1c972c742e40694972f578140bb0cac8c39eb
2020-09-13 13:06:02 -04:00
mike bayer dad484e7fa Merge "Do not specify type on mssql by default" 2020-09-12 16:26:39 +00:00
Federico Caselli 1d40a4ae15 Do not specify type on mssql by default
Make optional sequences render as identity in mssql
Remove unused dialect option sequence_default_column_type

Change-Id: I821eeffcb442f8d1b69186a9b798b15c3d8d6ff3
2020-09-12 10:00:23 -04:00
Federico Caselli e860060866 Update select usage to use the new 1.4 format
This change includes mainly that the bracketed use within
select() is moved to positional, and keyword arguments are
removed from calls to the select() function.  it does not
yet fully address other issues such as keyword arguments passed
to the table.select().

Additionally, allows False / None to both be considered
as "disable" for all of select.correlate(), select.correlate_except(),
query.correlate(), which establishes consistency with
passing of ``False`` for the legact select(correlate=False)
argument.

Change-Id: Ie6c6e6abfbd3d75d4c8de504c0cf0159e6999108
2020-09-08 17:13:48 -04:00
Mike Bayer e3716012c5 Create connection characteristics API; implement postgresql flags
Added support for PostgreSQL "readonly" and "deferrable" flags for all of
psycopg2, asyncpg and pg8000 dialects.   This takes advantage of a newly
generalized version of the "isolation level" API to support other kinds of
session attributes set via execution options that are reliably reset
when connections are returned to the connection pool.

Fixes: #5549
Change-Id: I0ad6d7a095e49d331618274c40ce75c76afdc7dd
2020-09-08 11:16:53 -04:00
Georg Richter 603f7d30f6 MariaDB dialect implementation
Fixes: #5459

Closes: #5515
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5515
Pull-request-sha: 760090b906

Change-Id: I30e8fbc02b7b5329ca228cd39f6fb7cfd0e43092
2020-08-31 18:19:35 -04:00
mike bayer 406034d41a Merge "internal test framework files for standardization of is_not/not_in;" 2020-08-30 14:33:08 +00:00
jonathan vanasco 672087176e internal test framework files for standardization of is_not/not_in;
this is safe for 1.3.x

Change-Id: Icba38fdc20f5d8ac407383a4278ccb346e09af38
2020-08-29 12:05:58 -04:00
Gord Thompson dc91c7db7f Emit v2.0 deprecation warning for "implicit autocommit"
"Implicit autocommit", which is the COMMIT that occurs when a DML or DDL
statement is emitted on a connection, is deprecated and won't be part of
SQLAlchemy 2.0.   A 2.0-style warning is emitted when autocommit takes
effect, so that the calling code may be adjusted to use an explicit
transaction.

As part of this change, DDL methods such as
:meth:`_schema.MetaData.create_all` when used against a
:class:`_engine.Engine` or :class:`_engine.Connection` will run the
operation in a BEGIN block if one is not started already.

The MySQL and MariaDB dialects now query from the information_schema.tables
system view in order to determine if a particular table exists or not.
Previously, the "DESCRIBE" command was used with an exception catch to
detect non-existent,  which would have the undesirable effect of emitting a
ROLLBACK on the connection. There appeared to be legacy encoding issues
which prevented the use of "SHOW TABLES", for this, but as MySQL support is
now at 5.0.2  or above due to 🎫`4189`, the information_schema tables
are now available in all cases.

Fixes: #4846
Change-Id: I733a7e0e17477a63607fb9931c87c393bbd7ac57
2020-08-28 16:32:05 -04:00
mike bayer 91100022ec Merge "make URL immutable" 2020-08-26 02:44:17 +00:00
Mike Bayer 3668b3a30c make URL immutable
it's not really correct that URL is mutable and doesn't do
any argument checking.   propose replacing it with an immutable
named tuple with rich copy-and-mutate methods.

At the moment this makes a hard change to the CreateEnginePlugin
docs that previously recommended url.query.pop().  I can't find
any plugins on github other than my own that are using this
feature, so see if we can just make a hard change on this one.

Fixes: #5526
Change-Id: I28a0a471d80792fa8c28f4fa573d6352966a4a79
2020-08-25 20:10:16 -04:00
Federico Caselli 9ab4da7018 Updates for MariaDB sequences
MariaDB should not run a Sequence if it has optional=True.
Additionally, rework the rules in crud.py to accommodate the
new combination MariaDB brings us, which is a dialect
that supports both cursor.lastrowid, explicit sequences,
*and* no support for returning.

Co-authored-by: Mike Bayer <mike_mp@zzzcomputing.com>
Fixes: #5528
Change-Id: I9a8ea69a34983affa95dfd22186e2908fdf0d58c
2020-08-22 12:46:12 -04:00
Mike Bayer a1939719a6 normalize execute style for events, 2.0
The _execute_20 and exec_driver_sql methods should wrap
up the parameters so that they represent the single list / single
dictionary style of invocation into the legacy methods.  then
the before_ after_ execute event handlers should be receiving
the parameter dictionary as a single dictionary.   this requires
that we break out distill_params to work differently if event
handlers are present.

additionally, add deprecation warnings for old argument passing
styles.

Change-Id: I97cb4d06adfcc6b889f10d01cc7775925cffb116
2020-08-20 10:14:21 -04:00
Tony Locke 06f1929b86 Update dialect for pg8000 version 1.16.0
The pg8000 dialect has been revised and modernized for the most recent
version of the pg8000 driver for PostgreSQL.  Changes to the dialect
include:

* All data types are now sent as text rather than binary.

* Using adapters, custom types can be plugged in to pg8000.

* Previously, named prepared statements were used for all statements.
  Now unnamed prepared statements are used by default, and named
  prepared statements can be used explicitly by calling the
  Connection.prepare() method, which returns a PreparedStatement
  object.

Pull request courtesy Tony Locke.

Notes by Mike: to get this all working it was needed to break
up JSONIndexType into "str" and "int" subtypes; this will be
needed for any dialect that is dependent on setinputsizes().

also includes @caselit's idea to include query params
in the dbdriver parameter.

Co-authored-by: Mike Bayer <mike_mp@zzzcomputing.com>

Closes: #5451
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5451
Pull-request-sha: 639751ca9c

Change-Id: I2869bc52c330916773a41d11d12c297aecc8fcd8
2020-08-18 11:12:16 -04:00
Mike Bayer 5fb0138a32 Implement rudimentary asyncio support w/ asyncpg
Using the approach introduced at
https://gist.github.com/zzzeek/6287e28054d3baddc07fa21a7227904e

We can now create asyncio endpoints that are then handled
in "implicit IO" form within the majority of the Core internals.
Then coroutines are re-exposed at the point at which we call
into asyncpg methods.

Patch includes:

* asyncpg dialect

* asyncio package

* engine, result, ORM session classes

* new test fixtures, tests

* some work with pep-484 and a short plugin for the
  pyannotate package, which seems to have so-so results

Change-Id: Idbcc0eff72c4cad572914acdd6f40ddb1aef1a7d
Fixes: #3414
2020-08-13 18:41:53 -04:00
Mike Bayer 302e8dee82 Don't link on_connect to first_connect event handler
Adjusted the dialect initialization process such that the
:meth:`_engine.Dialect.on_connect` is not called a second time on the first
connection.   The hook is called first, then the
:meth:`_engine.Dialect.initialize` is called if that connection is the
first for that dialect, then no more events are called.   This eliminates
the two calls to the "on_connect" function which can produce very difficult
debugging situations.

Fixes: #5497
Change-Id: Icefc2e884e30ee7b4ac84b99dc54bf992a6085e3
2020-08-07 18:01:49 -04:00
Mike Bayer 28fbb0cb94 more docs for autocommit isolation level
this concept is not clear that we offer real
DBAPI autocommit everywhere.  backport 1.3 with edits
as well

Change-Id: I2e8328b7fb6e1cdc5453ab29c94276f60c7ca149
2020-07-12 21:46:05 -04:00
Mike Bayer 91f376692d Add future=True to create_engine/Session; unify select()
Several weeks of using the future_select() construct
has led to the proposal there be just one select() construct
again which features the new join() method, and otherwise accepts
both the 1.x and 2.x argument styles.   This would make
migration simpler and reduce confusion.

However, confusion may be increased by the fact that select().join()
is different  Current thinking is we may be better off
with a few hard behavioral changes to old and relatively unknown APIs
rather than trying to play both sides within two extremely similar
but subtly different APIs.  At the moment, the .join() thing seems
to be the only behavioral change that occurs without the user
taking any explicit steps.   Session.execute() will still
behave the old way as we are adding a future flag.

This change also adds the "future" flag to Session() and
session.execute(), so that interpretation of the incoming statement,
as well as that the new style result is returned, does not
occur for existing applications unless they add the use
of this flag.

The change in general is moving the "removed in 2.0" system
further along where we want the test suite to fully pass
even if the SQLALCHEMY_WARN_20 flag is set.

Get many tests to pass when SQLALCHEMY_WARN_20 is set; this
should be ongoing after this patch merges.

Improve the RemovedIn20 warning; these are all deprecated
"since" 1.4, so ensure that's what the messages read.
Make sure the inforamtion link is on all warnings.
Add deprecation warnings for parameters present and
add warnings to all FromClause.select() types of methods.

Fixes: #5379
Fixes: #5284
Change-Id: I765a0b912b3dcd0e995426427d8bb7997cbffd51
References: #5159
2020-07-08 11:05:11 -04:00
Mike Bayer 5f5b56d646 Add an extra step to pool test_sync
Have observed CI failure with windows where not all
three connections got pulled out at the same time here
as the threads got serialized.  make sure all three
connections get used.

Change-Id: Ic2f7c7de1069358d95035f90c725c7dddd4f34d4
2020-06-27 22:57:52 -04:00
Mike Bayer 62be25cdfa Propose using RETURNING for bulk updates, deletes
This patch makes several improvements in the area of
bulk updates and deletes as well as the new session mechanics.

RETURNING is now used for an UPDATE or DELETE statement
emitted for a diaelct that supports "full returning"
in order to satisfy the "fetch" strategy; this currently
includes PostgreSQL and SQL Server.  The Oracle dialect
does not support RETURNING for more than one row,
so a new dialect capability "full_returning" is added
in addition to the existing "implicit_returning", indicating
this dialect supports RETURNING for zero or more rows,
not just a single identity row.

The "fetch" strategy will gracefully degrade to
the previous SELECT mechanics for dialects that do not
support RETURNING.

Additionally, the "fetch" strategy will attempt to use
evaluation for the VALUES that were UPDATEd, rather
than just expiring the updated attributes.   Values should
be evalutable in all cases where the value is not
a SQL expression.

The new approach also incurs some changes in the
session.execute mechanics, where do_orm_execute() event
handlers can now be chained to each return results;
this is in turn used by the handler to detect on a
per-bind basis if the fetch strategy needs to
do a SELECT or if it can do RETURNING.  A test suite is
added to test_horizontal_shard that breaks up a single
UPDATE or DELETE operation among multiple backends
where some are SQLite and don't support RETURNING and
others are PostgreSQL and do.

The session event mechanics are corrected
in terms of the "orm pre execute" hook, which now
receives a flag "is_reentrant" so that the two
ORM implementations for this can skip on their work
if they are being called inside of ORMExecuteState.invoke(),
where previously bulk update/delete were calling its
SELECT a second time.

In order for "fetch" to get the correct identity when
called as pre-execute, it also requests the identity_token
for each mapped instance which is now added as an optional
capability of a SELECT for ORM columns.   the identity_token
that's placed by horizontal_sharding is now made available
within each result row, so that even when fetching a
merged result of plain rows we can tell which row belongs
to which identity token.

The evaluator that takes place within the ORM bulk update and delete for
synchronize_session="evaluate" now supports the IN and NOT IN operators.
Tuple IN is also supported.

Fixes: #1653

Change-Id: I2292b56ae004b997cef0ba4d3fc350ae1dd5efc1
2020-06-23 10:41:39 -04:00
Mike Bayer 5624430eb1 Warn when transaction context manager ends on inactive transaction
if .rollback() or .commit() is called inside the transaction
context manager, the transaction object is deactivated.
the context manager continues but will not be able to correctly
fulfill it's closing state.  Ensure a warning is emitted when
this happens.

Change-Id: I8fc3a73f7c21575dda5bcbd6fb74ddb679771630
2020-06-12 20:28:37 -04:00
Mike Bayer b0cfa7379c Turn on caching everywhere, add logging
A variety of caching issues found by running
all tests with statement caching turned on.

The cache system now has a more conservative approach where
any subclass of a SQL element will by default invalidate
the cache key unless it adds the flag inherit_cache=True
at the class level, or if it implements its own caching.

Add working caching to a few elements that were
omitted previously; fix some caching implementations
to suit lesser used edge cases such as json casts
and array slices.

Refine the way BaseCursorResult and CursorMetaData
interact with caching; to suit cases like Alembic
modifying table structures, don't cache the
cursor metadata if it were created against a
cursor.description using non-positional matching,
e.g. "select *".   if a table re-ordered its columns
or added/removed, now that data is obsolete.

Additionally we have to adapt the cursor metadata
_keymap regardless of if we just processed
cursor.description, because if we ran against
a cached SQLCompiler we won't have the right
columns in _keymap.

Other refinements to how and when we do this
adaption as some weird cases
were exposed in the Postgresql dialect,
a text() construct that names just one column that
is not actually in the statement.   Fixed that
also as it looks like a cut-and-paste artifact
that doesn't actually affect anything.

Various issues with re-use of compiled result maps
and cursor metadata in conjunction with tables being
changed, such as change in order of columns.

mappers can be cleared but the class remains, meaning
a mapper has to use itself as the cache key not the class.

lots of bound parameter / literal issues, due to Alembic
creating a straight subclass of bindparam that renders
inline directly.   While we can update Alembic to not
do this, we have to assume other people might be doing
this, so bindparam() implements the inherit_cache=True
logic as well that was a bit involved.

turn on cache stats in logging.

Includes a fix to subqueryloader which moves all setup to
the create_row_processor() phase and elminates any storage
within the compiled context.   This includes some changes
to create_row_processor() signature and a revising of the
technique used to determine if the loader can participate
in polymorphic queries, which is also applied to
selectinloading.

DML update.values() and ordered_values() now coerces the
keys as we have tests that pass an arbitrary class here
which only includes __clause_element__(), so the
key can't be cached unless it is coerced.  this in turn
changed how composite attributes support bulk update
to use the standard approach of ClauseElement with
annotations that are parsed in the ORM context.

memory profiling successfully caught that the Session
from Query was getting passed into _statement_20()
so that was a big win for that test suite.

Apparently Compiler had .execute() and .scalar() methods
stuck on it, these date back to version 0.4 and there
was a single test in the PostgreSQL dialect tests
that exercised it for no apparent reason.   Removed
these methods as well as the concept of a Compiler
holding onto a "bind".

Fixes: #5386

Change-Id: I990b43aab96b42665af1b2187ad6020bee778784
2020-06-10 15:29:01 -04:00
Gord Thompson 668872fe01 Add support for "real" sequences in mssql
Added support for "CREATE SEQUENCE" and full :class:`.Sequence` support for
Microsoft SQL Server.  This removes the deprecated feature of using
:class:`.Sequence` objects to manipulate IDENTITY characteristics which
should now be performed using ``mssql_identity_start`` and
``mssql_identity_increment`` as documented at :ref:`mssql_identity`. The
change includes a new parameter :paramref:`.Sequence.data_type` to
accommodate SQL Server's choice of datatype, which for that backend
includes INTEGER and BIGINT.   The default starting value for SQL Server's
version of :class:`.Sequence` has been set at 1; this default is now
emitted within the CREATE SEQUENCE DDL for all backends.

Fixes: #4235
Fixes: #4633
Change-Id: I6aa55c441e8146c2f002e2e201a7f645e667b916
2020-05-29 08:10:38 -06:00
Mike Bayer 77f1b7d236 callcount reductions and refinement for cached queries
This commit includes that we've removed the "_orm_query"
attribute from compile state as well as query context.
The attribute created reference cycles and also added
method call overhead.    As part of this change,
the interface for ORMExecuteState changes a bit, as well
as the interface for the horizontal sharding extension
which now deprecates the "query_chooser" callable
in favor of "execute_chooser", which receives the contextual
object.  This will also work more nicely when we implement
the new execution path for bulk updates and deletes.

Pre-merge execution options for statement, connection,
arguments all up front in Connection.  that way they
can be passed to the before_execute / after_execute events,
and the ExecutionContext doesn't have to merge as second
time.   Core execute is pretty close to 1.3 now.

baked wasn't using the new one()/first()/one_or_none() methods,
fixed that.

Convert non-buffered cursor strategy to be a stateless
singleton.  inline all the paths by which the strategy
gets chosen, oracle and SQL Server dialects make use of the
already-invoked post_exec() hook to establish the alternate
strategies, and this is actually much nicer than it was before.

Add caching to mapper instance processor for getters.

Identified a reference cycle per query that was showing
up as a lot of gc cleanup, fixed that.

After all that, performance not budging much.  Even
test_baked_query now runs with significantly fewer function
calls than 1.3, still 40% slower.

Basically something about the new patterns just makes
this slower and while I've walked a whole bunch of them
back, it hardly makes a dent.  that said, the performance
issues are relatively small, in the 20-40% time increase
range, and the new caching feature
does provide for regular ORM and Core queries that
are cached, and they are faster than non-cached.

Change-Id: I7b0b0d8ca550c05f79e82f75cd8eff0bbfade053
2020-05-28 14:38:56 -04:00
mike bayer ebceb618ef Merge "Add immutabledict C code" 2020-05-23 12:51:07 +00:00
Mike Bayer fcbd03e48a Add immutabledict C code
Start trying to convert fundamental objects to
C as we now rely on a fairly small core of things,
and 1.4 is having problems with complexity added being
slower than the performance gains we are trying to build in.

immutabledict here does seem to bench as twice as fast as the
Python one, see below.  However, it does not appear to be
used prominently enough to make any dent in the performance
tests.

at the very least it may provide us some more lift-and-copy
code for more C extensions.

import timeit

from sqlalchemy.util._collections import not_immutabledict, immutabledict

def run(dict_cls):
    for i in range(1000000):
        d1 = dict_cls({"x": 5, "y": 4})

        d2 = d1.union({"x": 17, "new key": "some other value"}, None)

        assert list(d2) == ["x", "y", "new key"]

print(
    timeit.timeit(
        "run(d)", "from __main__ import run, not_immutabledict as d", number=1
    )
)
print(
    timeit.timeit(
        "run(d)", "from __main__ import run, immutabledict as d", number=1
    )
)

output:

python: 1.8799766399897635
C code: 0.8880784640205093

Change-Id: I29e7104dc21dcc7cdf895bf274003af2e219bf6d
2020-05-23 00:05:13 -04:00
mike bayer 3fb0eb5a15 Merge "Fix query string escaping in engine URLs" 2020-05-22 20:17:49 +00:00
Mike Bayer 5b2abf4d26 Structural / performance refinements
* state connection schema_translate_map entirely in terms of
  execution options, support for per-execution options as well

* use slots for role impls, remove superclass of the roles
  themselves as this is not needed

* tighten loop in resolve, might become a C function

Change-Id: Ib98ac9b65022fbf976e49c6060e4c37573528c5f
2020-05-22 10:30:38 -04:00
Miguel Grinberg 2644693c0b Fix query string escaping in engine URLs
Fixed issue in :class:`.URL` object where stringifying the object
would not URL encode special characters, preventing the URL from being
re-consumable as a real URL.  Pull request courtesy Miguel Grinberg.

Fixes: #5341
Closes: #5342
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5342
Pull-request-sha: 362ca33983

Change-Id: Ief6218122d1ec0c70479eb1a90e1c16433801924
2020-05-21 14:27:07 -04:00
Mike Bayer af0e59ff16 Disable "check unicode returns" under Python 3
Disabled the "unicode returns" check that runs on dialect startup when
running under Python 3, which for many years has occurred in order to test
the current DBAPI's behavior for whether or not it returns Python Unicode
or Py2K strings for the VARCHAR and NVARCHAR datatypes.  The check still
occurs by default under Python 2, however the mechanism to test the
behavior will be removed in SQLAlchemy 2.0 when Python 2 support is also
removed.

This logic was very effective when it was needed, however now that Python 3
is standard, all DBAPIs are expected to return Python 3 strings for
character datatypes.  In the unlikely case that a third party DBAPI does
not support this, the conversion logic within :class:`.String` is still
available and the third party dialect may specify this in its upfront
dialect flags by setting the dialect level flag ``returns_unicode_strings``
to one of :attr:`.String.RETURNS_CONDITIONAL` or
:attr:`.String.RETURNS_BYTES`, both of which will enable Unicode conversion
even under Python 3.

As part of this change, disabling testing of the doctest tutorials under
Python 2.

Fixes: #5315
Change-Id: I1260e894611409d3b7fe1a92bd90c52043bbcf19
2020-05-19 13:53:39 -04:00
Mike Bayer 0e53221eef Update transaction / connection handling
step one, do away with __connection attribute and using
awkward AttributeError logic

step two, move all management of "connection._transaction"
into the transaction objects themselves where it's easier
to follow.

build MarkerTransaction that takes the role of
"do-nothing block"

new connection datamodel is: connection._transaction, always
a root, connection._nested_transaction, always a nested.

nested transactions still chain to each other as this
is still sort of necessary but they consider the root
transaction separately, and the marker transactions
not at all.

introduce new InvalidRequestError subclass
PendingRollbackError.  Apply to connection and session
for all cases where a transaction needs to be rolled
back before continuing.   Within Connection,
both PendingRollbackError as well as ResourceClosedError
are now raised directly without being handled by
handle_dbapi_error();  this removes these two exception
cases from the handle_error event handler as well as
from StatementError wrapping, as these two exceptions are
not statement oriented and are instead programmatic
issues, that the application is failing to handle database
errors properly.

Revise savepoints so that when a release fails, they set
themselves as inactive so that their rollback() method
does not throw another exception.

Give savepoints another go on MySQL, can't get release working
however get support for basic round trip going

Fixes: #5327
Change-Id: Ia3cbbf56d4882fcc7980f90519412f1711fae74d
2020-05-17 16:32:22 -04:00
Mike Bayer 79de84b25e Actively unset reset agent in discard transaction
The assumptions in _discard_transaction from
916e1fea25 were too narrow,
assuming that if the given transaction were not our
"current" one, that this would not be the reset agent.  however
as the legacy behvaior is that even a "nested" transaction gets
set as "self._transaction", this did not accommodate for the nested
transaction being thrown away.   We will attempt to refine all of this
logic in #5327 for 1.4 /master assuming this is feasible for the
full suite of current use cases.

Fixes: #5326
Change-Id: I6787e82c9e50c23317f87d0d094122c6a6f066da
2020-05-14 10:51:29 -04:00
Mike Bayer 916e1fea25 Assert reset agent always set correctly and is active
Fixed fairly critical issue where the DBAPI connection could be returned to
the connection pool while still in an un-rolled-back state. The reset agent
responsible for rolling back the connection could be corrupted in the case
that the transaction was "closed" without being rolled back or committed,
which can occur in some scenarios when using ORM sessions and emitting
.close() in a certain pattern involving savepoints.   The fix ensures that
the reset agent is always active.

note that the reset agent will go away in 2.0 and the only real
purpose of it is for logging of ROLLBACK.   Apparently with the
SQLite singleton engine in the test suite, there are some strucutral
mismatches in the test fixtures where the reset agent is getting
set differently than the transaction likely due to the same connection
being shared in multiple context, though it's unclear.

Fixes: #5326
Change-Id: If056870ea70a2d9a1749768988d5e023f3061b31
2020-05-13 16:12:42 -04:00
Mike Bayer aded39f68c Propose Result as immediate replacement for ResultProxy
As progress is made on the _future.Result, including breaking
it out such that DBAPI behaviors are local to specific
implementations, it becomes apparent that the Result object
is a functional superset of ResultProxy and that basic
operations like fetchone(), fetchall(), and fetchmany()
behave pretty much exactly the same way on the new object.
Reorganize things so that ResultProxy is now referred to
as LegacyCursorResult, which subclasses CursorResult
that represents the DBAPI-cursor version of Result,
making use of a multiple inheritance pattern so that
the functionality of Result is also available in non-DBAPI
contexts, as will be necessary for some ORM
patterns.

Additionally propose the composition system for Result
that will form the basis for ORM-alternative result
systems such as horizontal sharding and dogpile cache.
As ORM results will soon be coming directly from
instances of Result, these extensions will instead
build their own ResultFetchStrategies that perform
the special steps to create composed or cached
result sets.

Also considering at the moment not emitting deprecation
warnings for fetchXYZ() methods; the immediate issue
is Keystone tests are calling upon it, but as the
implementations here are proving to be not in any
kind of conflict with how Result works, there's
not too much issue leaving them around and deprecating
at some later point.

References: #5087
References: #4395
Fixes: #4959
Change-Id: I8091919d45421e3f53029b8660427f844fee0228
2020-05-01 16:09:24 -04:00
Mike Bayer 2f617f56f2 Create initial 2.0 engine implementation
Implemented the SQLAlchemy 2 :func:`.future.create_engine` function which
is used for forwards compatibility with SQLAlchemy 2.   This engine
features always-transactional behavior with autobegin.

Allow execution options per statement execution.  This includes
that the before_execute() and after_execute() events now accept
an additional dictionary with these options, empty if not
passed; a legacy event decorator is added for backwards compatibility
which now also emits a deprecation warning.

Add some basic tests for execution, transactions, and
the new result object.   Build out on a new testing fixture
that swaps in the future engine completely to start with.

Change-Id: I70e7338bb3f0ce22d2f702537d94bb249bd9fb0a
Fixes: #4644
2020-04-16 13:35:55 -04:00