# Copyright 2018 Google LLC # # Licensed under the Apache License, Version 2.0 (the 'License'); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an 'AS IS' BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # [START functions_sql_mysql] from os import getenv import pymysql from pymysql.err import OperationalError # TODO(developer): specify SQL connection details CONNECTION_NAME = getenv( 'INSTANCE_CONNECTION_NAME', '') DB_USER = getenv('MYSQL_USER', '') DB_PASSWORD = getenv('MYSQL_PASSWORD', '') DB_NAME = getenv('MYSQL_DATABASE', '') mysql_config = { 'user': DB_USER, 'password': DB_PASSWORD, 'db': DB_NAME, 'charset': 'utf8mb4', 'cursorclass': pymysql.cursors.DictCursor, 'autocommit': True } # Create SQL connection globally to enable reuse # PyMySQL does not include support for connection pooling mysql_conn = None def __get_cursor(): """ Helper function to get a cursor PyMySQL does NOT automatically reconnect, so we must reconnect explicitly using ping() """ try: return mysql_conn.cursor() except OperationalError: mysql_conn.ping(reconnect=True) return mysql_conn.cursor() def mysql_demo(request): global mysql_conn # Initialize connections lazily, in case SQL access isn't needed for this # GCF instance. Doing so minimizes the number of active SQL connections, # which helps keep your GCF instances under SQL connection limits. if not mysql_conn: try: mysql_conn = pymysql.connect(**mysql_config) except OperationalError: # If production settings fail, use local development ones mysql_config['unix_socket'] = f'/cloudsql/{CONNECTION_NAME}' mysql_conn = pymysql.connect(**mysql_config) # Remember to close SQL resources declared while running this function. # Keep any declared in global scope (e.g. mysql_conn) for later reuse. with __get_cursor() as cursor: cursor.execute('SELECT NOW() as now') results = cursor.fetchone() return str(results['now']) # [END functions_sql_mysql]