1
#!/usr/bin/env python
2
#-*- coding:utf-8 -*-
3
"""
4
    Database Drivers where to dump the data collected into
5
    a database.
6
"""
7
8
import os
9
10
class database:
11
    """
12
        Base class to implement drivers. Drivers should override those
13
        methods that might be incomatibles.
14
    """
15
    
16
    def __init__(self, database, username, password, hostname=None):
17
        pass
18
19
    def drop_tables(self):
20
        drop_changeset = 'DROP TABLE IF EXISTS changeset'
21
        drop_filetype = 'DROP TABLE IF EXISTS filetype'
22
23
        cursor = self.connection.cursor()
24
        cursor.execute(drop_changeset)
25
        cursor.execute(drop_filetype)
26
        self.connection.commit()
27
        cursor.close()
28
29
    def create_tables(self):
30
        create_changeset = '''CREATE TABLE changeset (
31
             "module" varchar(100),
32
             "version" varchar(30),
33
             "changeset" varchar(100),
34
             "date" date,
35
             "email" varchar(100),
36
             "domain" varchar(100),
37
             "name" varchar(100),
38
             "employer" varchar(100),
39
             "nversion" integer,
40
             "added" integer,
41
             "removed" integer)'''
42
43
        create_filetype = '''CREATE TABLE  filetype (
44
             "module" varchar(100),
45
             "version" varchar(30),
46
             "changeset" varchar(100),
47
             "type" varchar(100),
48
             "nversion" integer,
49
             "added" integer,
50
             "removed" integer)'''
51
52
        cursor = self.connection.cursor()
53
        cursor.execute(create_changeset)
54
        cursor.execute(create_filetype)
55
        self.connection.commit()
56
        cursor.close()
57
58
    def changeset2db(self, reader, module, version):
59
        """
60
            Store a CSV reader file of changeset into a table.
61
        """
62
63
        header = reader.next()
64
        cursor = self.connection.cursor()
65
        nversion = int(version.replace('.', ''))
66
67
        # Insert a row of data
68
        for (commit, date, email, domain, name, employer, added, removed) in reader:
69
            try:
70
                cursor.execute("""INSERT INTO changeset VALUES
71
                               ('%s', '%s', '%s', '%s', '%s', '%s',
72
                                '%s', '%s', %d, %d, %d)""" \
73
                               % (module, version, commit, date, email, 
74
                                  domain, name, employer,
75
                                  nversion, int(added), int(removed))
76
                              )
77
            except:
78
                self.connection.rollback()
79
                import chardet
80
                encoding = chardet.detect(name)['encoding']
81
                name = name.decode(encoding).encode('utf-8')
82
                cursor.execute("""INSERT INTO changeset VALUES
83
                               ('%s', '%s', '%s', '%s', '%s', '%s',
84
                                '%s', '%s', %d, %d, %d)""" \
85
                               % (module, version, commit, date, email, 
86
                                  domain, name, employer,
87
                                  nversion, int(added), int(removed))
88
                              )
89
90
            # It is required to commit every row.  If it fails once
91
            # because an enconding issue, the rollback will work for
92
            # only that row which was reinserted on the exception
93
            self.connection.commit()
94
95
        self.connection.commit()
96
        cursor.close()
97
98
    def filetype2db(self, reader, module, version):
99
        """
100
            Store a CSV reader file of file types into a table.
101
        """
102
        
103
        header = reader.next()
104
        cursor = self.connection.cursor()
105
        nversion = int(version.replace('.', ''))
106
107
        # Insert a row of data
108
        for (commit, filetype, added, removed) in reader:
109
            cursor.execute("""INSERT INTO filetype VALUES
110
                           ('%s', '%s', '%s', '%s', %d, %d, %d)""" \
111
                           % (module, version, commit, filetype,
112
                              nversion, int(added), int(removed))
113
                          )
114
115
        self.connection.commit()
116
        cursor.close()
117
118
class psqldb (database):
119
    """
120
        Postgresql Driver.
121
    """
122
    
123
    def __init__(self, database, username, password, hostname=None):
124
        import psycopg2 as dbapi
125
        from psycopg2.extensions import ISOLATION_LEVEL_READ_COMMITTED
126
        try:
127
            if hostname is not None:
128
                db = dbapi.connect(database=database,
129
                                user=username,
130
                                password=password,
131
                                host=hostname)
132
            else:
133
                db = dbapi.connect(database=database,
134
                                user=username)
135
            db.set_client_encoding('UTF8')
136
            db.set_isolation_level(ISOLATION_LEVEL_READ_COMMITTED)
137
            self.connection = db
138
        except:
139
            raise
140
141
142
class sqlitedb (database):
143
    """
144
        Sqlite3 Driver.
145
    """
146
    
147
    def __init__(self, database, username=None, 
148
                 password=None, hostname=None):
149
150
        import sqlite3 as dbapi
151
        db = dbapi.connect(database=database)
152
        self.connection = db