1818import os
1919
2020# [START cloud_sql_connector_postgres_psycopg]
21+ from typing import Union
22+
23+ import sqlalchemy
2124
2225from google .cloud .sql .connector import Connector
2326from google .cloud .sql .connector import DefaultResolver
27+ from google .cloud .sql .connector import DnsResolver
28+
29+
30+ def create_sqlalchemy_engine (
31+ instance_connection_name : str ,
32+ user : str ,
33+ password : str ,
34+ db : str ,
35+ ip_type : str = "public" ,
36+ refresh_strategy : str = "background" ,
37+ resolver : Union [type [DefaultResolver ], type [DnsResolver ]] = DefaultResolver ,
38+ ) -> tuple [sqlalchemy .engine .Engine , Connector ]:
39+ """Creates a connection pool for a Cloud SQL instance and returns the pool
40+ and the connector. Callers are responsible for closing the pool and the
41+ connector.
42+
43+ A sample invocation looks like:
44+
45+ engine, connector = create_sqlalchemy_engine(
46+ inst_conn_name,
47+ user,
48+ password,
49+ db,
50+ )
51+ with engine.connect() as conn:
52+ time = conn.execute(sqlalchemy.text("SELECT NOW()")).fetchone()
53+ conn.commit()
54+ curr_time = time[0]
55+ # do something with query result
56+ connector.close()
57+
58+ Args:
59+ instance_connection_name (str):
60+ The instance connection name specifies the instance relative to the
61+ project and region. For example: "my-project:my-region:my-instance"
62+ user (str):
63+ The database user name, e.g., root
64+ password (str):
65+ The database user's password, e.g., secret-password
66+ db (str):
67+ The name of the database, e.g., mydb
68+ ip_type (str):
69+ The IP type of the Cloud SQL instance to connect to. Can be one
70+ of "public", "private", or "psc".
71+ refresh_strategy (Optional[str]):
72+ Refresh strategy for the Cloud SQL Connector. Can be one of "lazy"
73+ or "background". For serverless environments use "lazy" to avoid
74+ errors resulting from CPU being throttled.
75+ resolver (Optional[google.cloud.sql.connector.DefaultResolver]):
76+ Resolver class for resolving instance connection name. Use
77+ google.cloud.sql.connector.DnsResolver when resolving DNS domain
78+ names or google.cloud.sql.connector.DefaultResolver for regular
79+ instance connection names ("my-project:my-region:my-instance").
80+ """
81+ connector = Connector (refresh_strategy = refresh_strategy , resolver = resolver )
82+
83+ # create SQLAlchemy connection pool
84+ engine = sqlalchemy .create_engine (
85+ "postgresql+psycopg://" ,
86+ creator = lambda : connector .connect (
87+ instance_connection_name ,
88+ "psycopg" ,
89+ user = user ,
90+ password = password ,
91+ db = db ,
92+ local_socket_path = "/tmp/conn" ,
93+ ip_type = ip_type , # can be "public", "private" or "psc"
94+ autocommit = True ,
95+ ),
96+ )
97+ return engine , connector
2498
25- from sqlalchemy .dialects .postgresql .base import PGDialect
26- PGDialect ._get_server_version_info = lambda * args : (9 , 2 )
2799
28100# [END cloud_sql_connector_postgres_psycopg]
29101
@@ -36,25 +108,12 @@ def test_psycopg_connection() -> None:
36108 db = os .environ ["POSTGRES_DB" ]
37109 ip_type = os .environ .get ("IP_TYPE" , "public" )
38110
39- connector = Connector (refresh_strategy = "background" , resolver = DefaultResolver )
40-
41- pool = connector .connect (
42- inst_conn_name ,
43- "psycopg" ,
44- user = user ,
45- password = password ,
46- db = db ,
47- ip_type = ip_type , # can be "public", "private" or "psc"
111+ engine , connector = create_sqlalchemy_engine (
112+ inst_conn_name , user , password , db , ip_type
48113 )
49-
50- with pool as conn :
51-
52- # Open a cursor to perform database operations
53- with conn .cursor () as cur :
54-
55- # Query the database and obtain data as Python objects.
56- cur .execute ("SELECT NOW()" )
57- curr_time = cur .fetchone ()["now" ]
58- assert type (curr_time ) is datetime
59-
60-
114+ with engine .connect () as conn :
115+ time = conn .execute (sqlalchemy .text ("SELECT NOW()" )).fetchone ()
116+ conn .commit ()
117+ curr_time = time [0 ]
118+ assert type (curr_time ) is datetime
119+ connector .close ()
0 commit comments