summaryrefslogtreecommitdiff
path: root/sqlplain/postgres_util.py
blob: b83bc1c75d4be64e447739fa0d863367c2b0a342 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import os
from sqlplain.util import openclose, getoutput

GET_PKEYS = '''\
SELECT attname FROM pg_attribute
WHERE attrelid = (
   SELECT indexrelid FROM pg_index AS i
   WHERE i.indrelid = (SELECT oid FROM pg_class WHERE relname=:table)
   AND i.indisprimary = 't')
ORDER BY attnum
'''

def get_kfields_postgres(conn, tname):
    return [x.attname for x in conn.execute(GET_PKEYS, (tname,))]

def create_db_postgres(uri):
    openclose(uri.copy(database='template1'),
              'CREATE DATABASE %(database)s' % uri)

def drop_db_postgres(uri):
    openclose(uri.copy(database='template1'),
              'DROP DATABASE %(database)s' % uri)

def get_sizeK_postgres(conn, table):
    return conn.execute('SELECT relpages*8 FROM pg_class WHERE relname=:table', 
                        (table,), scalar=True)

def get_tables_postgres(conn, schema):
    query = 'SELECT tablename FROM pg_tables'
    if schema:
        res = conn.execute(query + ' WHERE schemaname=:a', (schema,))
    else:
        res = conn.execute(query)
    return [r[0] for r in res]

def exists_table_postgres(conn, tname):
    return conn.execute('SELECT count(*) FROM pg_tables WHERE tablename=:table',
                        (tname,), scalar=True)
    
def exists_db_postgres(uri):
    dbname = uri['database']
    for row in openclose(
        uri.copy(database='template1'), 'SELECT datname FROM pg_database'):
        if row[0] == dbname:
            return True
    return False

def dump_file_postgres(uri, query, filename, mode, sep='\t', null='',
                       schema=None): # or null='\N'
    """
    Save the result of a query on a local file by using COPY TO and psql
    """
    if not ' ' in query: # assumes a table name was given
        query = '(select * from %s)' % query
    else:
        query = '(%s)' % query
    if mode == 'b':
        return psql(uri, "COPY %s TO STDOUT BINARY" % query, filename, schema)
    else:
        return psql(
            uri, "COPY %s TO STDOUT WITH DELIMITER '%s' NULL '%s'" %
            (query, sep, null), filename, schema)

# apparently copy_from from psycopg2 is buggy for large files
def load_file_postgres(uri, tname, filename, mode, sep='\t', null='',
                       schema=None): # or null='\N'
    """
    Load a file into a table by using COPY FROM and psql
    """
    stdin = file(filename)
    if mode == 'b':
        return psql(uri, "COPY %s FROM STDIN BINARY" % tname, stdin=stdin,
                    schema=schema)
    else: # csv mode
        copy_from = "COPY %s FROM STDIN WITH DELIMITER E'%s' NULL E'%s'" % (
            tname, sep, null)
        return psql(uri, copy_from, stdin=stdin, schema=schema)

###############################################################################

## pg_dump and pg_restore should be used for multiple tables or whole databases

def pg_dump(uri, filename, *args):
    """
    A small wrapper over pg_dump. Example:
    >> pg_dump(uri, thetable, thefile)
    """
    cmd = ['pg_dump', '-h', uri['host'], '-U', uri['user'],
           '-d', uri['database'], '-f', filename] + list(args)
    print ' '.join(cmd)
    return getoutput(cmd)

def pg_restore(uri, filename, *args):
    """
    A small wrapper over pg_restore. Example:
    >> pg_restore(uri, thetable, thefile)
    """
    cmd = ['pg_restore', '-h', uri['host'], '-U', uri['user'],
           '-d', uri['database'], filename] + list(args)
    print ' '.join(cmd)
    return getoutput(cmd)


def psql(uri, query, filename=os.devnull, stdin=None, schema=None):
    "Execute a query and save its result on filename"
    if not ' ' in query: # assumes a table name was given
        query = 'select * from %s' % query
    if schema:
        query = 'SET search_path TO %s; %s' % (schema, query) 
    cmd = ['psql', '-h', uri['host'], '-U', uri['user'], '-d', uri['database'],
           '-c', query, '-o', filename]
    # print cmd
    return getoutput(cmd, stdin)