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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
# sqlite_adapter.rb
# author: Luke Holden <lholden@cablelan.net>
require 'active_record/connection_adapters/abstract_adapter'
module ActiveRecord
class Base
# Establishes a connection to the database that's used by all Active Record objects
def self.sqlite_connection(config) # :nodoc:
require_library_or_gem('sqlite') unless self.class.const_defined?(:SQLite)
symbolize_strings_in_hash(config)
unless config.has_key?(:dbfile)
raise ArgumentError, "No database file specified. Missing argument: dbfile"
end
config[:dbfile] = File.expand_path(config[:dbfile], RAILS_ROOT) if Object.const_defined?(:RAILS_ROOT)
db = SQLite::Database.new(config[:dbfile], 0)
db.show_datatypes = "ON" if !defined? SQLite::Version
db.results_as_hash = true if defined? SQLite::Version
db.type_translation = false
ConnectionAdapters::SQLiteAdapter.new(db, logger)
end
end
module ConnectionAdapters
class SQLiteColumn < Column
def string_to_binary(value)
value.gsub(/(\0|\%)/) do
case $1
when "\0" then "%00"
when "%" then "%25"
end
end
end
def binary_to_string(value)
value.gsub(/(%00|%25)/) do
case $1
when "%00" then "\0"
when "%25" then "%"
end
end
end
end
class SQLiteAdapter < AbstractAdapter # :nodoc:
def select_all(sql, name = nil)
select(sql, name)
end
def select_one(sql, name = nil)
result = select(sql, name)
result.nil? ? nil : result.first
end
def columns(table_name, name = nil)
table_structure(table_name).inject([]) do |columns, field|
columns << SQLiteColumn.new(field['name'], field['dflt_value'], field['type'])
columns
end
end
def insert(sql, name = nil, pk = nil, id_value = nil)
execute(sql, name = nil)
id_value || @connection.send( defined?( SQLite::Version ) ? :last_insert_row_id : :last_insert_rowid )
end
def execute(sql, name = nil)
log(sql, name, @connection) do |connection|
if defined?( SQLite::Version )
case sql
when "BEGIN" then connection.transaction
when "COMMIT" then connection.commit
when "ROLLBACK" then connection.rollback
else connection.execute(sql)
end
else
connection.execute( sql )
end
end
end
def update(sql, name = nil)
execute(sql, name)
@connection.changes
end
def delete(sql, name = nil)
sql += " WHERE 1=1" unless sql =~ /WHERE/i
execute(sql, name)
@connection.changes
end
def begin_db_transaction() execute "BEGIN" end
def commit_db_transaction() execute "COMMIT" end
def rollback_db_transaction() execute "ROLLBACK" end
def quote_string(s)
SQLite::Database.quote(s)
end
def quote_column_name(name)
return "'#{name}'"
end
private
def select(sql, name = nil)
results = nil
log(sql, name, @connection) { |connection| results = connection.execute(sql) }
rows = []
results.each do |row|
hash_only_row = {}
row.each_key do |key|
hash_only_row[key.sub(/\w+\./, "")] = row[key] unless key.class == Fixnum
end
rows << hash_only_row
end
return rows
end
def table_structure(table_name)
sql = "PRAGMA table_info(#{table_name});"
results = nil
log(sql, nil, @connection) { |connection| results = connection.execute(sql) }
return results
end
end
end
end
|