| 1 | n/a | # Mimic the sqlite3 console shell's .dump command |
|---|
| 2 | n/a | # Author: Paul Kippes <kippesp@gmail.com> |
|---|
| 3 | n/a | |
|---|
| 4 | n/a | # Every identifier in sql is quoted based on a comment in sqlite |
|---|
| 5 | n/a | # documentation "SQLite adds new keywords from time to time when it |
|---|
| 6 | n/a | # takes on new features. So to prevent your code from being broken by |
|---|
| 7 | n/a | # future enhancements, you should normally quote any identifier that |
|---|
| 8 | n/a | # is an English language word, even if you do not have to." |
|---|
| 9 | n/a | |
|---|
| 10 | n/a | def _iterdump(connection): |
|---|
| 11 | n/a | """ |
|---|
| 12 | n/a | Returns an iterator to the dump of the database in an SQL text format. |
|---|
| 13 | n/a | |
|---|
| 14 | n/a | Used to produce an SQL dump of the database. Useful to save an in-memory |
|---|
| 15 | n/a | database for later restoration. This function should not be called |
|---|
| 16 | n/a | directly but instead called from the Connection method, iterdump(). |
|---|
| 17 | n/a | """ |
|---|
| 18 | n/a | |
|---|
| 19 | n/a | cu = connection.cursor() |
|---|
| 20 | n/a | yield('BEGIN TRANSACTION;') |
|---|
| 21 | n/a | |
|---|
| 22 | n/a | # sqlite_master table contains the SQL CREATE statements for the database. |
|---|
| 23 | n/a | q = """ |
|---|
| 24 | n/a | SELECT "name", "type", "sql" |
|---|
| 25 | n/a | FROM "sqlite_master" |
|---|
| 26 | n/a | WHERE "sql" NOT NULL AND |
|---|
| 27 | n/a | "type" == 'table' |
|---|
| 28 | n/a | ORDER BY "name" |
|---|
| 29 | n/a | """ |
|---|
| 30 | n/a | schema_res = cu.execute(q) |
|---|
| 31 | n/a | for table_name, type, sql in schema_res.fetchall(): |
|---|
| 32 | n/a | if table_name == 'sqlite_sequence': |
|---|
| 33 | n/a | yield('DELETE FROM "sqlite_sequence";') |
|---|
| 34 | n/a | elif table_name == 'sqlite_stat1': |
|---|
| 35 | n/a | yield('ANALYZE "sqlite_master";') |
|---|
| 36 | n/a | elif table_name.startswith('sqlite_'): |
|---|
| 37 | n/a | continue |
|---|
| 38 | n/a | # NOTE: Virtual table support not implemented |
|---|
| 39 | n/a | #elif sql.startswith('CREATE VIRTUAL TABLE'): |
|---|
| 40 | n/a | # qtable = table_name.replace("'", "''") |
|---|
| 41 | n/a | # yield("INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"\ |
|---|
| 42 | n/a | # "VALUES('table','{0}','{0}',0,'{1}');".format( |
|---|
| 43 | n/a | # qtable, |
|---|
| 44 | n/a | # sql.replace("''"))) |
|---|
| 45 | n/a | else: |
|---|
| 46 | n/a | yield('{0};'.format(sql)) |
|---|
| 47 | n/a | |
|---|
| 48 | n/a | # Build the insert statement for each row of the current table |
|---|
| 49 | n/a | table_name_ident = table_name.replace('"', '""') |
|---|
| 50 | n/a | res = cu.execute('PRAGMA table_info("{0}")'.format(table_name_ident)) |
|---|
| 51 | n/a | column_names = [str(table_info[1]) for table_info in res.fetchall()] |
|---|
| 52 | n/a | q = """SELECT 'INSERT INTO "{0}" VALUES({1})' FROM "{0}";""".format( |
|---|
| 53 | n/a | table_name_ident, |
|---|
| 54 | n/a | ",".join("""'||quote("{0}")||'""".format(col.replace('"', '""')) for col in column_names)) |
|---|
| 55 | n/a | query_res = cu.execute(q) |
|---|
| 56 | n/a | for row in query_res: |
|---|
| 57 | n/a | yield("{0};".format(row[0])) |
|---|
| 58 | n/a | |
|---|
| 59 | n/a | # Now when the type is 'index', 'trigger', or 'view' |
|---|
| 60 | n/a | q = """ |
|---|
| 61 | n/a | SELECT "name", "type", "sql" |
|---|
| 62 | n/a | FROM "sqlite_master" |
|---|
| 63 | n/a | WHERE "sql" NOT NULL AND |
|---|
| 64 | n/a | "type" IN ('index', 'trigger', 'view') |
|---|
| 65 | n/a | """ |
|---|
| 66 | n/a | schema_res = cu.execute(q) |
|---|
| 67 | n/a | for name, type, sql in schema_res.fetchall(): |
|---|
| 68 | n/a | yield('{0};'.format(sql)) |
|---|
| 69 | n/a | |
|---|
| 70 | n/a | yield('COMMIT;') |
|---|