Class: DBI::DBD::SQLite::Database

Inherits:
BaseDatabase show all
Defined in:
lib/dbd/sqlite/database.rb

Overview

See DBI::BaseDatabase.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from BaseDatabase

#do, #execute

Constructor Details

#initialize(dbname, user, auth, attr_hash) ⇒ Database

Constructor. Valid attributes:

  • AutoCommit: Commit after every statement execution.



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
# File 'lib/dbd/sqlite/database.rb', line 14

def initialize(dbname, user, auth, attr_hash)
    # FIXME why isn't this crap being done in DBI?
    unless dbname.kind_of? String
        raise DBI::InterfaceError, "Database Name must be a string"
    end

    unless dbname.length > 0
        raise DBI::InterfaceError, "Database Name needs to be length > 0"
    end

    unless attr_hash.kind_of? Hash
        raise DBI::InterfaceError, "Attributes should be a hash"
    end

    # FIXME handle busy_timeout in SQLite driver
    # FIXME handle SQLite pragmas in SQLite driver
    @attr_hash = attr_hash
    @open_handles = 0

    self["AutoCommit"] = true if self["AutoCommit"].nil?

    # open the database
    begin
        @db = ::SQLite::Database.new(dbname)
    rescue Exception => e
        raise DBI::OperationalError, "Couldn't open database #{dbname}: #{e.message}"
    end
end

Instance Attribute Details

#attr_hashObject (readonly)

Returns the value of attribute attr_hash.



6
7
8
# File 'lib/dbd/sqlite/database.rb', line 6

def attr_hash
  @attr_hash
end

#dbObject (readonly)

Returns the value of attribute db.



5
6
7
# File 'lib/dbd/sqlite/database.rb', line 5

def db
  @db
end

#open_handlesObject

Returns the value of attribute open_handles.



7
8
9
# File 'lib/dbd/sqlite/database.rb', line 7

def open_handles
  @open_handles
end

Instance Method Details

#[](key) ⇒ Object



92
93
94
# File 'lib/dbd/sqlite/database.rb', line 92

def [](key)
    return @attr_hash[key]
end

#[]=(key, value) ⇒ Object

See DBI::BaseDatabase#[]=.

If AutoCommit is set to true using this method, was previously false, and we are currently in a transaction, The act of setting this will cause an immediate commit.



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/dbd/sqlite/database.rb', line 103

def []=(key, value)

    old_value = @attr_hash[key]

    @attr_hash[key] = value

    # special handling of settings
    case key
    when "AutoCommit"
        # if the value being set is true and the previous value is false,
        # commit the current transaction (if any)
        # FIXME I still think this is a horrible way of handling this.
        if value and !old_value
            begin 
                @dbh.commit
            rescue Exception => e
            end
        end
    end

    return @attr_hash[key]
end

#columns(tablename) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/dbd/sqlite/database.rb', line 126

def columns(tablename)
    return nil unless tablename and tablename.kind_of? String

    sth = prepare("PRAGMA table_info(?)")
    sth.bind_param(1, tablename)
    sth.execute
    columns = [ ]
    while row = sth.fetch
        column = { }
        column["name"] = row[1]

        m = DBI::DBD::SQLite.parse_type(row[2])
        column["type_name"] = m[1]
        column["precision"] = m[3].to_i if m[3]
        column["scale"]     = m[5].to_i if m[5]

        column["nullable"]  = row[3].to_i == 0
        column["default"]   = row[4]
        columns.push column
    end

    sth.finish
    return columns
    # XXX it'd be nice if the spec was changed to do this k/v with the name as the key.
end

#commitObject



75
76
77
# File 'lib/dbd/sqlite/database.rb', line 75

def commit
    @db.commit if @db.transaction_active?
end

#database_nameObject



49
50
51
52
53
54
55
56
# File 'lib/dbd/sqlite/database.rb', line 49

def database_name
    st = DBI::DBD::SQLite::Statement.new('PRAGMA database_list', self)
    st.execute
    row = st.fetch
    st.finish

    return row[2]
end

#disconnectObject



43
44
45
46
47
# File 'lib/dbd/sqlite/database.rb', line 43

def disconnect
    rollback rescue nil
    @db.close if @db and !@db.closed?
    @db = nil
end

#pingObject



62
63
64
# File 'lib/dbd/sqlite/database.rb', line 62

def ping
    return !@db.closed?
end

#prepare(stmt) ⇒ Object



58
59
60
# File 'lib/dbd/sqlite/database.rb', line 58

def prepare(stmt)
    return DBI::DBD::SQLite::Statement.new(stmt, self)
end

#rollbackObject

Rollback the transaction. SQLite has some issues with open statement handles when this happens. If there are still open handles, a DBI::Warning exception will be raised.



84
85
86
87
88
89
90
# File 'lib/dbd/sqlite/database.rb', line 84

def rollback
    if @open_handles > 0
        raise DBI::Warning, "Leaving unfinished select statement handles while rolling back a transaction can corrupt your database or crash your program"
    end

    @db.rollback if @db.transaction_active?
end

#tablesObject



66
67
68
69
70
71
72
73
# File 'lib/dbd/sqlite/database.rb', line 66

def tables
    sth = prepare("select name from sqlite_master where type in ('table', 'view')")
    sth.execute
    tables = sth.fetch_all.flatten
    sth.finish
    return tables
    # FIXME does sqlite use views too? not sure, but they need to be included according to spec
end