2010-02-15 35 views

Respuesta

4

Lamentablemente, no conozco una buena respuesta general para esto. Algunos dbapi (psycopg2 por ejemplo) admiten la ejecución de muchas declaraciones a la vez. Si los archivos no son enormes, solo puede cargarlos en una cadena y ejecutarlos en una conexión. Para otros, trataría de usar un cliente de línea de comandos para ese DB y canalizar los datos a ese utilizando el módulo de subproceso.

Si esos enfoques no son aceptables, entonces tendrá que seguir adelante e implementar un pequeño analizador de SQL que pueda dividir el archivo en declaraciones separadas. Esto es realmente complicado para obtener el 100% de corrección, ya que tendrá que tener en cuenta las reglas de escape literales específicas del dialecto de base de datos, el juego de caracteres utilizado, cualquier opción de configuración de base de datos que afecte el análisis literal (por ejemplo, PostgreSQL standard_conforming_strings).

Si solo necesitas obtener este 99.9% de corrección, entonces algo de magia de expresiones regulares debería llevarte la mayor parte del camino hasta allí.

4

Si está usando sqlite3 tiene una extensión útil para dbapi llamada conn.executescript (str), lo he conectado a través de algo como esto y parecía funcionar: (No todo el contexto se muestra pero debería ser lo suficiente para obtener la deriva)

def init_from_script(script): 
    Base.metadata.drop_all(db_engine) 
    Base.metadata.create_all(db_engine)  

    # HACK ALERT: we can do this using sqlite3 low level api, then reopen session. 
    f = open(script) 
    script_str = f.read().strip() 
    global db_session 
    db_session.close() 
    import sqlite3 
    conn = sqlite3.connect(db_file_name) 
    conn.executescript(script_str) 
    conn.commit() 

    db_session = Session() 

¿Es este mal puro que me pregunto? Busqué en vano un equivalente de sqlalchemy 'puro', tal vez podría agregarse a la biblioteca, algo así como db_session.execute_script (file_name)? Espero que db_session funcione bien después de todo eso (es decir, no hay necesidad de reiniciar el motor) pero aún no estoy seguro ... se necesita más investigación (es decir, ¿necesitamos obtener un nuevo motor o simplemente una sesión después de volver atrás de sqlalchemy? ?)

FYI sqlite3 incluye una rutina relacionada: sqlite3.complete_statement (SQL) si sacas tu propio analizador ...

1

que era capaz de ejecutar archivos de esquema utilizando .sql SQLAlchemy pura y algunas manipulaciones de cadenas. Seguramente no es un enfoque elegante, pero funciona.

# Open the .sql file 
    sql_file = open(<file.sql>,'r') 

    # Create an empty command string 
    sql_command = '' 

    # Iterate over all lines in the sql file 
    for line in sql_file: 
     # Ignore comented lines 
     if not line.startswith('--') and line.strip('\n'): 
      # Append line to the command string 
      sql_command += line.strip('\n') 

      # If the command string ends with ';', it is a full statement 
      if sql_command.endswith(';'): 
       # Try to execute statemente and commit it 
       try: 
        session.execute(text(sql_command)) 
        session.commit() 

       # Assert in case of error 
       except: 
        print('Ops') 

       # Finally, clear command string 
       finally: 
        sql_command = '' 

itera sobre todas las líneas en un archivo .sql ignorando las líneas comentadas. Luego concatena las líneas que forman una instrucción completa e intenta ejecutar la instrucción. Solo necesita un manejador de archivos y un objeto de sesión.

Cuestiones relacionadas