-
Notifications
You must be signed in to change notification settings - Fork 408
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix type introspection being very slow on large databases
Stop using CTEs in the type introspection query, otherwise it runs for ages on databases with a large number of composite attributes (i. e. tons of tables with tons of columns). Fixes: #186
- Loading branch information
Showing
3 changed files
with
119 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# Copyright (C) 2016-present the asyncpg authors and contributors | ||
# <see AUTHORS file> | ||
# | ||
# This module is part of asyncpg and is released under | ||
# the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
|
||
from asyncpg import _testbase as tb | ||
|
||
|
||
MAX_RUNTIME = 0.1 | ||
|
||
|
||
class TestTimeout(tb.ConnectedTestCase): | ||
@classmethod | ||
def setUpClass(cls): | ||
super().setUpClass() | ||
cls.adminconn = cls.loop.run_until_complete( | ||
cls.cluster.connect(database='postgres', loop=cls.loop)) | ||
cls.loop.run_until_complete( | ||
cls.adminconn.execute('CREATE DATABASE asyncpg_intro_test')) | ||
|
||
@classmethod | ||
def tearDownClass(cls): | ||
cls.loop.run_until_complete( | ||
cls.adminconn.execute('DROP DATABASE asyncpg_intro_test')) | ||
|
||
cls.loop.run_until_complete(cls.adminconn.close()) | ||
cls.adminconn = None | ||
|
||
super().tearDownClass() | ||
|
||
@tb.with_connection_options(database='asyncpg_intro_test') | ||
async def test_introspection_on_large_db(self): | ||
await self.con.execute( | ||
'CREATE DOMAIN intro_test AS int' | ||
) | ||
|
||
await self.con.execute( | ||
'CREATE TABLE base ({})'.format( | ||
','.join('c{:02} varchar'.format(n) for n in range(50)) | ||
) | ||
) | ||
for n in range(1000): | ||
await self.con.execute( | ||
'CREATE TABLE child_{:04} () inherits (base)'.format(n) | ||
) | ||
|
||
with self.assertRunUnder(MAX_RUNTIME): | ||
await self.con.fetchval('SELECT $1::intro_test', 1) |