Unable to connect to Google Cloud SQL from development server using SQLAlchemy

前端 未结 2 1125
南方客
南方客 2020-12-19 18:25

I\'ve been unsuccessful at connecting to Google Cloud SQL using SQLAlchemy 0.7.9 from my development workstation (in hopes to generate the schema using create_all()). I can

相关标签:
2条回答
  • It turns out the mysql+gaerdbms:/// driver in SQLAlchemy was only setup to use the rdbms_apiproxy DBAPI, which can only be used when accessing Google Cloud SQL from a Google App Engine instance. I submitted a ticket to SQLAlchemy to update the driver to use the OAuth-based rdbms_googleapi when not on Google App Engine, just like the Django driver provided in the App Engine SDK. rdbms_googleapi is also the DBAPI that google_sql.py uses (remote sql console).

    The updated dialect is expected to be part of 0.7.10 and 0.8.0 releases, but until they are available, you can do the following:


    1 - Copy the updated dialect in the ticket to a file (ex. gaerdbms_dialect.py)

    from sqlalchemy.dialects.mysql.mysqldb import MySQLDialect_mysqldb
    from sqlalchemy.pool import NullPool
    import re
    
    """Support for Google Cloud SQL on Google App Engine
    
    Connecting
    -----------
    
    Connect string format::
    
        mysql+gaerdbms:///<dbname>?instance=<project:instance>
    
    
      # Example:
      create_engine('mysql+gaerdbms:///mydb?instance=myproject:instance1')
    """
    
    
    class MySQLDialect_gaerdbms(MySQLDialect_mysqldb):
    
        @classmethod
        def dbapi(cls):
            from google.appengine.api import apiproxy_stub_map
    
            if apiproxy_stub_map.apiproxy.GetStub('rdbms'):
                from google.storage.speckle.python.api import rdbms_apiproxy
                return rdbms_apiproxy
            else:
                from google.storage.speckle.python.api import rdbms_googleapi
                return rdbms_googleapi
    
        @classmethod
        def get_pool_class(cls, url):
            # Cloud SQL connections die at any moment
            return NullPool
    
        def create_connect_args(self, url):
            opts = url.translate_connect_args()
            opts['dsn'] = ''  # unused but required to pass to rdbms.connect()
            opts['instance'] = url.query['instance']
            return [], opts
    
        def _extract_error_code(self, exception):
            match = re.compile(r"^(\d+):").match(str(exception))
            code = match.group(1)
            if code:
                return int(code)
    
    dialect = MySQLDialect_gaerdbms
    

    2 - Register the custom dialect (you can override the existing schema)

    from sqlalchemy.dialects import registry
    registry.register("mysql.gaerdbms", "application.database.gaerdbms_dialect", "MySQLDialect_gaerdbms")
    

    Note: 0.8 allows a dialect to be registered within the current process (as shown above). If you are running an older version of SQLAlchemy, I recommend upgrading to 0.8+ or you'll need to create a separate install for the dialect as outlined here.


    3 - Update your create_engine('...') url as the project and instance are now provided as part of the query string of the URL

    mysql+gaerdbms:///<dbname>?instance=<project:instance>
    

    for example:

    create_engine('mysql+gaerdbms:///mydb?instance=myproject:instance1')
    
    0 讨论(0)
  • 2020-12-19 19:10

    I think I have a working sample script as follows. Can you try a similar thing and let me know how it goes?

    However(and you might be already aware of it), if your goal is to create the schema on Google Cloud SQL instance, maybe you can create the schema against a local mysql server, dump it with mysqldump, and then import the schema to Google Cloud SQL. Using local mysql server is very convenient for development anyway.

    from sqlalchemy import create_engine
    from google.storage.speckle.python.api import rdbms as dbi_driver
    from google.storage.speckle.python.api import rdbms_googleapi
    
    INSTANCE = 'YOURPROJECT:YOURINSTANCE'
    DATABASE = 'YOURDATABASE'
    
    def get_connection():       
        return rdbms_googleapi.connect('', instance=INSTANCE, database=DATABASE)
    
    def main():
        engine = create_engine(
            'mysql:///YOURPROJECT:YOURINSTANCE/YOURDATABASE',
            module=dbi_driver,
            creator=get_connection,
        )
        print engine.execute('SELECT 1').scalar()
    
    if __name__ == '__main__':
        main()
    
    0 讨论(0)
提交回复
热议问题