tags:

views:

78

answers:

2

I have a large SQL script that creates my database (multiple tables, triggers, and such. Using MySQL), and I need to execute that script from within a python program. My old code did this:

sql_file = open(os.path.join(self.path_to_sql, filename), 'r')
sql_text = sql_file.read()
sql_stmts = sql_text.split(';')
for s in sql_stmts:
    cursor.execute(s)

This worked fine until I started including triggers in my sql script. Since I now need to change the delimiter from ; to something else, in order to support triggers with multiple SQL statements in each, my code to split each statement into it's own string no longer works because the "delimiter |" line in my script fails to split properly, and I get a syntax error from cursor.execute(s).

So, I need some way to tell mysqldb to execute an entire sql script at once, instead of individual sql statements. I tried this:

sql_file = open(os.path.join(self.path_to_sql, filename), 'r')
sql_text = sql_file.read()
cursor.execute(sql_text)

However, I get the following error when I try to run that code: ProgrammingError: (2014, "Commands out of sync; you can't run this command now") My Google-fu tells me that this is because the Python mysqldb package doesn't support complex SQL statements being sent to cursor.execute().

So how can I do this? I'd really like to find a way to do this entirely within Python, so that the code will remain entirely portable. We have several programmers working on this project in Eclipse, some on Windows and some on Mac, and the code needs to work on the Linux production server as well.

If I can't use Python code to actually run the SQL, how can I tell Python to launch a separate program to execute it?

+1  A: 

(not a python solution) you can use

  os.system('mysql < etc')

ooh, edit (python solution):

if you have the query broken up by line, you can close and reopen the cursor and execute by line.

redit: sorry, only skimmed your first paragraph. seems like you were doing this sort of thing at first.

Orbit
After a bit of work I seem to have gotten your solution to work. I'm seeing some strange behavior with it, however, so I'm going to keep working on it. I'd *really* like to find a solution that works entirely within Python, though, since this really needs to be totally portable.
CoreDumpError
After a bit more work, I've decided to go with your solution. The problems I was having were latent bugs in my code that hadn't expressed themselves until I started loading my DDL from an external program (per your solution). So you've not only helped me find a solution to the delimiter issue, but also fixed a really bad bug! You're awesome.
CoreDumpError
wooo <3 unintended good consequences.
Orbit
A: 

This doesn't seem like a very good way to structure a multi-language program.

Brandon's answer is really the right way to go if all you're doing is just executing a big chunk of sql.

On the other hand, if you're doing stuff with the results of queries throughout the process of the job, then you shouldn't try to parse a large, wellformed sql script. Instead you should mix the sql statements into your python code.

TokenMacGuy
We're not doing anything with the results of the queries in these scripts. We just run the script to recreate the database (and another to fill it with test data) every time we run a unit test, so that our data is always consistent. And what do you mean by "not a good way to structure a multi-language program"? I'm just confused by your terminology.
CoreDumpError
multilanguage just means that you have two programming languages in your program, python and sql. unless parsing is a core part of the functionality of the program, one language should treat the other as a black-box, and not make any attempt to parse it in any way.
TokenMacGuy
Yeah, that's exactly what I'd like to do! All I care about is executing the sql script and moving on. It's just that the old code (which I didn't write) breaks now because of the delimiter issue. I have no attachment to this code, so any solution will be fine. Also, what did you mean by "Brandom's answer"? There's no answers to my question by anyone named Brandon, as far as I can tell.
CoreDumpError
@Core: there was an answer from Brandon earlier; looks like he deleted it.
Adam Bernier
Awwww :(. Does anyone remember what he said? I really need a solution to this.
CoreDumpError
he was advising about `cursor.executemany()` (http://mysql-python.sourceforge.net/MySQLdb-1.2.2/public/MySQLdb.cursors.BaseCursor-class.html#executemany)
TokenMacGuy