Project

General

Profile

1
#!/usr/bin/env python
2
# Loads a command's CSV output stream into a PostgreSQL table.
3
# When no command is specified, just cleans up the specified table.
4
# The command may be run more than once.
5

    
6
import os.path
7
import subprocess
8
import sys
9

    
10
sys.path.append(os.path.dirname(__file__)+"/../lib")
11

    
12
import exc
13
import opts
14
import sql
15
import sql_io
16
import sql_gen
17
import streams
18
import strings
19
import util
20

    
21
def main():
22
    # Usage
23
    env_names = []
24
    def usage_err():
25
        raise SystemExit('Usage: '+opts.env_usage(env_names)+' '+sys.argv[0]
26
            +' [input_cmd args...]')
27
    
28
    # Parse args
29
    input_cmd = sys.argv[1:]
30
    
31
    # Get config from env vars
32
    table = opts.get_env_var('table', None, env_names)
33
    schema = opts.get_env_var('schema', 'public', env_names)
34
    has_row_num = opts.env_flag('has_row_num', True, env_names)
35
    db_config = opts.get_env_vars(sql.db_config_names, None, env_names)
36
    verbosity = util.cast(float, opts.get_env_var('verbosity', 3, env_names))
37
    
38
    if not (table != None and 'engine' in db_config): usage_err()
39
    
40
    # Connect to DB
41
    def log(msg, level=1):
42
        '''Higher level -> more verbose'''
43
        if level <= verbosity:
44
            sys.stderr.write(strings.to_raw_str(msg.rstrip('\n')+'\n'))
45
    db = sql.connect(db_config, log_debug=log)
46
    
47
    table = sql_gen.Table(table, schema)
48
    
49
    use_copy_from = True
50
    
51
    # Loads data into the table using the currently-selected approach.
52
    def load():
53
        # Open input stream
54
        proc = subprocess.Popen(input_cmd, stdout=subprocess.PIPE, bufsize=-1)
55
        in_ = proc.stdout
56
        line_in = streams.ProgressInputStream(in_, sys.stderr, n=1000)
57
        
58
        # Import data
59
        try: sql_io.import_csv(db, table, line_in, use_copy_from, has_row_num)
60
        finally:
61
            line_in.close() # also closes proc.stdout
62
            proc.wait()
63
    
64
    if input_cmd != []:
65
        try: load()
66
        except sql.DatabaseErrors, e:
67
            if use_copy_from: # first try
68
                exc.print_ex(e, plain=True)
69
                use_copy_from = False
70
                load() # try again with different approach
71
            else: raise
72
    else: sql_io.cleanup_table(db, table)
73

    
74
main()
(10-10/60)