Skip to content

Commit 6237af3

Browse files
author
James William Pye
committed
Select the appropriate startup_data symbol.
8.0 and earliar didn't have a backend_start.
1 parent c56eda6 commit 6237af3

3 files changed

Lines changed: 46 additions & 34 deletions

File tree

postgresql/driver/pq3.py

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1903,9 +1903,7 @@ def connect(self):
19031903
self._raise_pq_error()
19041904
# gah, the fatality of the connection does not
19051905
# appear to exist...
1906-
raise RuntimeError(
1907-
"closed connection has no fatal error"
1908-
)
1906+
raise RuntimeError("closed connection has no fatal error")
19091907

19101908
self.pq = None
19111909
# if any exception occurs past this point, the connection
@@ -1925,13 +1923,13 @@ def connect(self):
19251923
# When ssl is True: SSL negotiation will occur *and* it must succeed.
19261924
# When ssl is False: SSL negotiation will occur but it may fail(NOSSL).
19271925
if sslmode == 'allow':
1928-
# first, without ssl, then with. :)
1926+
# without ssl, then with. :)
19291927
socket_factories = interlace(
19301928
zip(repeat(None, len(socket_factories)), socket_factories),
19311929
zip(repeat(True, len(socket_factories)), socket_factories)
19321930
)
19331931
elif sslmode == 'prefer':
1934-
# first, with ssl, then without. [maybe] :)
1932+
# with ssl, then without. [maybe] :)
19351933
socket_factories = interlace(
19361934
zip(repeat(False, len(socket_factories)), socket_factories),
19371935
zip(repeat(None, len(socket_factories)), socket_factories)
@@ -1952,25 +1950,27 @@ def connect(self):
19521950
# in these cases, can_skip is set to True so that the
19531951
# subsequent non-ssl attempt is skipped if it failed with the 'N' response.
19541952
can_skip = False
1953+
startup = self.connector._startup_parameters
1954+
password = self.connector._password
1955+
Connection3 = client.Connection
19551956
for (ssl, sf) in socket_factories:
19561957
if can_skip is True:
19571958
# the last attempt failed and knows this attempt will fail too.
19581959
can_skip = False
19591960
continue
1960-
pq = client.Connection(
1961-
sf, self.connector._startup_parameters,
1962-
password = self.connector._password,
1963-
)
1961+
pq = Connection3(sf, startup, password = password,)
19641962
if hasattr(self, 'tracer'):
19651963
pq.tracer = self.tracer
1964+
19661965
# Grab the negotiation transaction before
19671966
# connecting as it will be needed later if successful.
19681967
neg = pq.xact
19691968
pq.connect(ssl = ssl, timeout = timeout)
19701969

19711970
didssl = getattr(pq, 'ssl_negotiation', -1)
19721971

1973-
# It successfully connected if pq.xact is None.
1972+
# It successfully connected if pq.xact is None;
1973+
# The startup/negotiation xact completed.
19741974
if pq.xact is None:
19751975
self.pq = pq
19761976
self.security = 'ssl' if didssl is True else None
@@ -2019,30 +2019,25 @@ def connect(self):
20192019
# it's over.
20202020
raise could_not_connect_err
20212021
##
2022-
# connected, now initialize metadata
2023-
# Use the version_info and integer_datetimes setting to identify
2024-
# the necessary binary type i/o functions to use.
2022+
# connected, now initialize connection information.
20252023
self.backend_id = self.pq.backend_id
20262024

20272025
sv = self.settings.cache.get("server_version", "0.0")
20282026
self.version_info = pg_version.normalize(pg_version.split(sv))
20292027
# manual binding
20302028
self.sys = pg_lib.Binding(self, pg_lib.sys)
20312029

2032-
# Get the *full* version string.
2033-
self.version = self.prepare("SELECT pg_catalog.version()").first()
2030+
if self.version_info <= (8,0):
2031+
meth = self.sys.startup_data_no_start
2032+
else:
2033+
meth = self.sys.startup_data
2034+
# connection info
2035+
self.version, self.backend_start, \
2036+
self.client_address, self.client_port = meth()
2037+
20342038
# First word from the version string.
20352039
self.type = self.version.split()[0]
20362040

2037-
r = self.sys.activity_for(self.backend_id)
2038-
if r is not None:
2039-
# conditional initialization of client_address.
2040-
# pythons without ipaddr will likely give strings.
2041-
ca = r.get('client_addr')
2042-
if ca is not None:
2043-
self.client_address = ca.split('/')[0]
2044-
self.client_port = r.get('client_port')
2045-
self.backend_start = r.get('backend_start')
20462041
##
20472042
# Set standard_conforming_strings
20482043
scstr = self.settings.get('standard_conforming_strings')

postgresql/lib/__init__.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ class Symbol(Element):
6161
)
6262
_e_label = 'SYMBOL'
6363
_e_factors = ('library', 'source',)
64+
65+
# The statement execution methods; symbols allow this to be specified
66+
# in order for a default method to be selected.
6467
execution_methods = {
6568
'first',
6669
'rows',
@@ -96,6 +99,8 @@ def __str__(self):
9699
"""
97100
Provide the source of the query's symbol.
98101
"""
102+
# Explicitly run str() on source as it is expected that a
103+
# given symbol's source may be generated.
99104
return str(self.source)
100105

101106
class Library(Element):
@@ -145,6 +150,7 @@ class SymbolCollection(Library):
145150
'preload',
146151
'const',
147152
'proc',
153+
'transient',
148154
)
149155

150156
def __init__(self, symbols, preface = None):
@@ -356,7 +362,9 @@ def __getattr__(self, name):
356362
r = list(r)
357363
bs = s[name] = r
358364
else:
359-
bs = s[name] = BoundSymbol(sym, db)
365+
bs = BoundSymbol(sym, db)
366+
if sym.type != 'transient':
367+
s[name] = bs
360368
return bs
361369

362370
class Category(pg_api.Category):

postgresql/lib/libsys.sql

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,24 +114,33 @@ SELECT
114114
FROM
115115
pg_catalog.generate_series(1, array_upper(($1::text[][]), 1)) g(i)
116116

117-
[activity]
118-
SELECT client_addr, client_port, backend_start::text FROM pg_catalog.pg_stat_activity
117+
[startup_data:transient:first]
118+
SELECT
119+
pg_catalog.version()::text,
120+
backend_start::text,
121+
client_addr::text,
122+
client_port
123+
FROM pg_catalog.pg_stat_activity WHERE procpid = pg_catalog.pg_backend_pid();
119124

120-
[activity_for::first]
121-
*[activity]
122-
WHERE procpid = $1
125+
[startup_data_no_start:transient:first]
126+
SELECT
127+
pg_catalog.version()::text,
128+
NULL::text AS backend_start,
129+
client_addr::text,
130+
client_port
131+
FROM pg_catalog.pg_stat_activity WHERE procpid = pg_catalog.pg_backend_pid();
123132

124-
[sizeof_db::first]
133+
[sizeof_db:transient:first]
125134
SELECT pg_catalog.pg_database_size(current_database())::bigint
126135

127-
[sizeof_cluster::first]
136+
[sizeof_cluster:transient:first]
128137
SELECT SUM(pg_catalog.pg_database_size(datname))::bigint FROM pg_database
129138

130139
[sizeof_relation::first]
131140
SELECT pg_catalog.pg_relation_size($1::text)::bigint
132141

133-
[pg_reload_conf]
142+
[pg_reload_conf:transient:]
134143
SELECT pg_reload_conf()
135144

136-
[languages::column]
145+
[languages:transient:column]
137146
SELECT lanname FROM pg_catalog.pg_language

0 commit comments

Comments
 (0)