baza 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +55 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/include/db.rb +784 -0
- data/include/dbtime.rb +35 -0
- data/include/drivers/.DS_Store +0 -0
- data/include/drivers/mysql/mysql.rb +604 -0
- data/include/drivers/mysql/mysql_columns.rb +155 -0
- data/include/drivers/mysql/mysql_indexes.rb +69 -0
- data/include/drivers/mysql/mysql_sqlspecs.rb +5 -0
- data/include/drivers/mysql/mysql_tables.rb +443 -0
- data/include/drivers/sqlite3/libknjdb_java_sqlite3.rb +83 -0
- data/include/drivers/sqlite3/libknjdb_sqlite3_ironruby.rb +69 -0
- data/include/drivers/sqlite3/sqlite3.rb +184 -0
- data/include/drivers/sqlite3/sqlite3_columns.rb +177 -0
- data/include/drivers/sqlite3/sqlite3_indexes.rb +29 -0
- data/include/drivers/sqlite3/sqlite3_sqlspecs.rb +5 -0
- data/include/drivers/sqlite3/sqlite3_tables.rb +449 -0
- data/include/dump.rb +122 -0
- data/include/idquery.rb +109 -0
- data/include/model.rb +873 -0
- data/include/model_custom.rb +153 -0
- data/include/model_handler.rb +957 -0
- data/include/model_handler_sqlhelper.rb +499 -0
- data/include/query_buffer.rb +87 -0
- data/include/revision.rb +342 -0
- data/include/row.rb +153 -0
- data/include/sqlspecs.rb +5 -0
- data/lib/baza.rb +8 -0
- data/spec/baza_spec.rb +286 -0
- data/spec/db_spec_encoding_test_file.txt +1 -0
- data/spec/spec_helper.rb +12 -0
- metadata +215 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
class KnjDB_java_sqlite3
|
2
|
+
def escape_table
|
3
|
+
return "`"
|
4
|
+
end
|
5
|
+
|
6
|
+
def escape_col
|
7
|
+
return "`"
|
8
|
+
end
|
9
|
+
|
10
|
+
def escape_val
|
11
|
+
return "'"
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(knjdb_ob)
|
15
|
+
@knjdb = knjdb_ob
|
16
|
+
|
17
|
+
if @knjdb.opts[:sqlite_driver]
|
18
|
+
require @knjdb.opts[:sqlite_driver]
|
19
|
+
else
|
20
|
+
require File.dirname(__FILE__) + "/sqlitejdbc-v056.jar"
|
21
|
+
end
|
22
|
+
|
23
|
+
require "java"
|
24
|
+
import "org.sqlite.JDBC"
|
25
|
+
@conn = java.sql.DriverManager::getConnection("jdbc:sqlite:" + @knjdb.opts[:path])
|
26
|
+
@stat = @conn.createStatement
|
27
|
+
end
|
28
|
+
|
29
|
+
def query(string)
|
30
|
+
begin
|
31
|
+
return KnjDB_java_sqlite3_result.new(@stat.executeQuery(string))
|
32
|
+
rescue java.sql.SQLException => e
|
33
|
+
if e.message == "java.sql.SQLException: query does not return ResultSet"
|
34
|
+
#ignore it.
|
35
|
+
else
|
36
|
+
raise e
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def fetch(result)
|
42
|
+
return result.fetch
|
43
|
+
end
|
44
|
+
|
45
|
+
def escape(string)
|
46
|
+
if (!string)
|
47
|
+
return ""
|
48
|
+
end
|
49
|
+
|
50
|
+
string = string.gsub("'", "\\'")
|
51
|
+
return string
|
52
|
+
end
|
53
|
+
|
54
|
+
def lastID
|
55
|
+
return @conn.last_insert_row_id
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class KnjDB_java_sqlite3_result
|
60
|
+
def initialize(rs)
|
61
|
+
@rs = rs
|
62
|
+
@index = 0
|
63
|
+
|
64
|
+
if rs
|
65
|
+
@metadata = rs.getMetaData
|
66
|
+
@columns_count = @metadata.getColumnCount
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def fetch
|
71
|
+
if !@rs.next
|
72
|
+
return false
|
73
|
+
end
|
74
|
+
|
75
|
+
tha_return = {}
|
76
|
+
for i in (1..@columns_count)
|
77
|
+
col_name = @metadata.getColumnName(i)
|
78
|
+
tha_return.store(col_name, @rs.getString(i))
|
79
|
+
end
|
80
|
+
|
81
|
+
return tha_return
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "Mono.Data.Sqlite, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"
|
2
|
+
require "Mono.Data.SqliteClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"
|
3
|
+
|
4
|
+
class Baza::Driver::Sqlite3_ironruby
|
5
|
+
def escape_table
|
6
|
+
return "`"
|
7
|
+
end
|
8
|
+
|
9
|
+
def escape_col
|
10
|
+
return "`"
|
11
|
+
end
|
12
|
+
|
13
|
+
def escape_val
|
14
|
+
return "'"
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(knjdb_ob)
|
18
|
+
@knjdb = knjdb_ob
|
19
|
+
@conn = Mono::Data::SqliteClient::SqliteConnection.new("URI=file:" + @knjdb.opts[:path] + ",version=3")
|
20
|
+
@conn.Open
|
21
|
+
end
|
22
|
+
|
23
|
+
def query(string)
|
24
|
+
dbcmd = @conn.CreateCommand
|
25
|
+
dbcmd.CommandText = string
|
26
|
+
reader = dbcmd.ExecuteReader
|
27
|
+
return Baza::Driver::Sqlite3_ironruby_result.new(reader)
|
28
|
+
end
|
29
|
+
|
30
|
+
def escape(string)
|
31
|
+
if (!string)
|
32
|
+
return ""
|
33
|
+
end
|
34
|
+
|
35
|
+
string = string.gsub("'", "\\'")
|
36
|
+
return string
|
37
|
+
end
|
38
|
+
|
39
|
+
def lastID
|
40
|
+
return @conn.last_insert_row_id
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Baza::Driver::Sqlite3_ironruby_result
|
45
|
+
def initialize(reader)
|
46
|
+
@reader = reader
|
47
|
+
end
|
48
|
+
|
49
|
+
def fetch
|
50
|
+
if !@reader.Read
|
51
|
+
return false
|
52
|
+
end
|
53
|
+
|
54
|
+
ret = {}
|
55
|
+
|
56
|
+
count = 0
|
57
|
+
while true
|
58
|
+
begin
|
59
|
+
ret[@reader.get_name(count)] = @reader.get_string(count)
|
60
|
+
rescue IndexError => e
|
61
|
+
break
|
62
|
+
end
|
63
|
+
|
64
|
+
count += 1
|
65
|
+
end
|
66
|
+
|
67
|
+
return ret
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
#This class handels SQLite3-specific behaviour.
|
2
|
+
class Baza::Driver::Sqlite3
|
3
|
+
attr_reader :knjdb, :conn, :sep_table, :sep_col, :sep_val, :symbolize
|
4
|
+
attr_accessor :tables, :cols, :indexes
|
5
|
+
|
6
|
+
#Constructor. This should not be called manually.
|
7
|
+
def initialize(knjdb_ob)
|
8
|
+
@sep_table = "`"
|
9
|
+
@sep_col = "`"
|
10
|
+
@sep_val = "'"
|
11
|
+
|
12
|
+
@knjdb = knjdb_ob
|
13
|
+
@path = @knjdb.opts[:path] if @knjdb.opts[:path]
|
14
|
+
@path = @knjdb.opts["path"] if @knjdb.opts["path"]
|
15
|
+
@symbolize = true if !@knjdb.opts.key?(:return_keys) or @knjdb.opts[:return_keys] == "symbols"
|
16
|
+
|
17
|
+
@knjdb.opts[:subtype] = "java" if !@knjdb.opts.key?(:subtype) and RUBY_ENGINE == "jruby"
|
18
|
+
raise "No path was given." if !@path
|
19
|
+
|
20
|
+
if @knjdb.opts[:subtype] == "java"
|
21
|
+
if @knjdb.opts[:sqlite_driver]
|
22
|
+
require @knjdb.opts[:sqlite_driver]
|
23
|
+
else
|
24
|
+
require "#{File.dirname(__FILE__)}/../../../jruby/sqlitejdbc-v056.jar"
|
25
|
+
end
|
26
|
+
|
27
|
+
require "java"
|
28
|
+
import "org.sqlite.JDBC"
|
29
|
+
@conn = java.sql.DriverManager::getConnection("jdbc:sqlite:#{@knjdb.opts[:path]}")
|
30
|
+
@stat = @conn.createStatement
|
31
|
+
elsif @knjdb.opts[:subtype] == "rhodes"
|
32
|
+
@conn = SQLite3::Database.new(@path, @path)
|
33
|
+
else
|
34
|
+
@conn = SQLite3::Database.open(@path)
|
35
|
+
@conn.results_as_hash = true
|
36
|
+
@conn.type_translation = false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
#Executes a query against the driver.
|
41
|
+
def query(string)
|
42
|
+
begin
|
43
|
+
if @knjdb.opts[:subtype] == "rhodes"
|
44
|
+
return Baza::Driver::Sqlite3_result.new(self, @conn.execute(string, string))
|
45
|
+
elsif @knjdb.opts[:subtype] == "java"
|
46
|
+
begin
|
47
|
+
return Baza::Driver::Sqlite3_result_java.new(self, @stat.executeQuery(string))
|
48
|
+
rescue java.sql.SQLException => e
|
49
|
+
if e.message.to_s.index("query does not return ResultSet") != nil
|
50
|
+
return Baza::Driver::Sqlite3_result_java.new(self, nil)
|
51
|
+
else
|
52
|
+
raise e
|
53
|
+
end
|
54
|
+
end
|
55
|
+
else
|
56
|
+
return Baza::Driver::Sqlite3_result.new(self, @conn.execute(string))
|
57
|
+
end
|
58
|
+
rescue => e
|
59
|
+
#Add SQL to the error message.
|
60
|
+
raise e.class, "#{e.message} (SQL: #{string})"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
#SQLite3 driver doesnt support unbuffered queries??
|
65
|
+
alias query_ubuf query
|
66
|
+
|
67
|
+
#Escapes a string to be safe to used in a query.
|
68
|
+
def escape(string)
|
69
|
+
#This code is taken directly from the documentation so we dont have to rely on the SQLite3::Database class. This way it can also be used with JRuby and IronRuby...
|
70
|
+
#http://sqlite-ruby.rubyforge.org/classes/SQLite/Database.html
|
71
|
+
return string.to_s.gsub(/'/, "''")
|
72
|
+
end
|
73
|
+
|
74
|
+
#Escapes a string to be used as a column.
|
75
|
+
def esc_col(string)
|
76
|
+
string = string.to_s
|
77
|
+
raise "Invalid column-string: #{string}" if string.index(@sep_col) != nil
|
78
|
+
return string
|
79
|
+
end
|
80
|
+
|
81
|
+
alias :esc_table :esc_col
|
82
|
+
alias :esc :escape
|
83
|
+
|
84
|
+
#Returns the last inserted ID.
|
85
|
+
def lastID
|
86
|
+
return @conn.last_insert_row_id if @conn.respond_to?(:last_insert_row_id)
|
87
|
+
return self.query("SELECT last_insert_rowid() AS id").fetch[:id].to_i
|
88
|
+
end
|
89
|
+
|
90
|
+
#Closes the connection to the database.
|
91
|
+
def close
|
92
|
+
@conn.close
|
93
|
+
end
|
94
|
+
|
95
|
+
#Starts a transaction, yields the database and commits.
|
96
|
+
def transaction
|
97
|
+
@conn.transaction do
|
98
|
+
yield(@knjdb)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
#This class handels results when running in JRuby.
|
104
|
+
class Baza::Driver::Sqlite3_result_java
|
105
|
+
def initialize(driver, rs)
|
106
|
+
@index = 0
|
107
|
+
retkeys = driver.knjdb.opts[:return_keys]
|
108
|
+
|
109
|
+
if rs
|
110
|
+
metadata = rs.getMetaData
|
111
|
+
columns_count = metadata.getColumnCount
|
112
|
+
|
113
|
+
@rows = []
|
114
|
+
while rs.next
|
115
|
+
row_data = {}
|
116
|
+
for i in (1..columns_count)
|
117
|
+
col_name = metadata.getColumnName(i)
|
118
|
+
col_name = col_name.to_s.to_sym if retkeys == "symbols"
|
119
|
+
row_data[col_name] = rs.getString(i)
|
120
|
+
end
|
121
|
+
|
122
|
+
@rows << row_data
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
#Returns a single result.
|
128
|
+
def fetch
|
129
|
+
return false if !@rows
|
130
|
+
ret = @rows[@index]
|
131
|
+
return false if !ret
|
132
|
+
@index += 1
|
133
|
+
return ret
|
134
|
+
end
|
135
|
+
|
136
|
+
#Loops over every result and yields them.
|
137
|
+
def each
|
138
|
+
while data = self.fetch
|
139
|
+
yield(data)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
#This class handels the result when running MRI (or others).
|
145
|
+
class Baza::Driver::Sqlite3_result
|
146
|
+
#Constructor. This should not be called manually.
|
147
|
+
def initialize(driver, result_array)
|
148
|
+
@result_array = result_array
|
149
|
+
@index = 0
|
150
|
+
|
151
|
+
if driver.knjdb.opts[:return_keys] == "symbols"
|
152
|
+
@symbols = true
|
153
|
+
else
|
154
|
+
@symbols = false
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
#Returns a single result.
|
159
|
+
def fetch
|
160
|
+
result_hash = @result_array[@index]
|
161
|
+
return false if !result_hash
|
162
|
+
@index += 1
|
163
|
+
|
164
|
+
ret = {}
|
165
|
+
result_hash.each do |key, val|
|
166
|
+
if (Float(key) rescue false)
|
167
|
+
#do nothing.
|
168
|
+
elsif @symbols and !key.is_a?(Symbol)
|
169
|
+
ret[key.to_sym] = val
|
170
|
+
else
|
171
|
+
ret[key] = val
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
return ret
|
176
|
+
end
|
177
|
+
|
178
|
+
#Loops over every result yielding them.
|
179
|
+
def each
|
180
|
+
while data = self.fetch
|
181
|
+
yield(data)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
#This class handels the SQLite3-specific behaviour for columns.
|
2
|
+
class Baza::Driver::Sqlite3::Columns
|
3
|
+
attr_reader :db
|
4
|
+
|
5
|
+
#Constructor. This should not be called manually.
|
6
|
+
def initialize(args)
|
7
|
+
@args = args
|
8
|
+
end
|
9
|
+
|
10
|
+
#Returns SQL for a knjdb-compatible hash.
|
11
|
+
def data_sql(data)
|
12
|
+
raise "No type given." if !data["type"]
|
13
|
+
type = data["type"].to_s
|
14
|
+
|
15
|
+
if type == "enum"
|
16
|
+
type = "varchar"
|
17
|
+
data.delete("maxlength")
|
18
|
+
end
|
19
|
+
|
20
|
+
data["maxlength"] = 255 if type == "varchar" and !data.key?("maxlength")
|
21
|
+
data["maxlength"] = 11 if type == "int" and !data.key?("maxlength") and !data["autoincr"] and !data["primarykey"]
|
22
|
+
type = "integer" if @args[:db].int_types.index(type) and (data["autoincr"] or data["primarykey"])
|
23
|
+
|
24
|
+
sql = "`#{data["name"]}` #{type}"
|
25
|
+
sql << "(#{data["maxlength"]})" if data["maxlength"] and !data["autoincr"]
|
26
|
+
sql << " PRIMARY KEY" if data["primarykey"]
|
27
|
+
sql << " AUTOINCREMENT" if data["autoincr"]
|
28
|
+
|
29
|
+
if !data["null"] and data.key?("null")
|
30
|
+
sql << " NOT NULL"
|
31
|
+
|
32
|
+
if !data.key?("default") or !data["default"]
|
33
|
+
data["default"] = 0 if type == "int"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if data.key?("default_func")
|
38
|
+
sql << " DEFAULT #{data["default_func"]}"
|
39
|
+
elsif data.key?("default") and data["default"] != false
|
40
|
+
sql << " DEFAULT '#{@args[:db].escape(data["default"])}'"
|
41
|
+
end
|
42
|
+
|
43
|
+
return sql
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
#This class handels all the SQLite3-columns.
|
48
|
+
class Baza::Driver::Sqlite3::Columns::Column
|
49
|
+
attr_reader :args
|
50
|
+
|
51
|
+
#Constructor. This should not be called manually.
|
52
|
+
def initialize(args)
|
53
|
+
@args = args
|
54
|
+
@db = @args[:db]
|
55
|
+
end
|
56
|
+
|
57
|
+
#Returns the name of the column.
|
58
|
+
def name
|
59
|
+
return @args[:data][:name]
|
60
|
+
end
|
61
|
+
|
62
|
+
#Returns the columns table-object.
|
63
|
+
def table
|
64
|
+
return @db.tables[@args[:table_name]]
|
65
|
+
end
|
66
|
+
|
67
|
+
#Returns the data of the column as a hash in knjdb-format.
|
68
|
+
def data
|
69
|
+
return {
|
70
|
+
"type" => self.type,
|
71
|
+
"name" => self.name,
|
72
|
+
"null" => self.null?,
|
73
|
+
"maxlength" => self.maxlength,
|
74
|
+
"default" => self.default,
|
75
|
+
"primarykey" => self.primarykey?,
|
76
|
+
"autoincr" => self.autoincr?
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
#Returns the type of the column.
|
81
|
+
def type
|
82
|
+
if !@type
|
83
|
+
if match = @args[:data][:type].match(/^([A-z]+)$/)
|
84
|
+
@maxlength = false
|
85
|
+
type = match[0].to_sym
|
86
|
+
elsif match = @args[:data][:type].match(/^decimal\((\d+),(\d+)\)$/)
|
87
|
+
@maxlength = "#{match[1]},#{match[2]}"
|
88
|
+
type = :decimal
|
89
|
+
elsif match = @args[:data][:type].match(/^enum\((.+)\)$/)
|
90
|
+
@maxlength = match[1]
|
91
|
+
type = :enum
|
92
|
+
elsif match = @args[:data][:type].match(/^(.+)\((\d+)\)$/)
|
93
|
+
@maxlength = match[2]
|
94
|
+
type = match[1].to_sym
|
95
|
+
elsif @args[:data].key?(:type) and @args[:data][:type].to_s == ""
|
96
|
+
#A type can actually be empty in SQLite... Wtf?
|
97
|
+
return @args[:data][:type]
|
98
|
+
end
|
99
|
+
|
100
|
+
if type == :integer
|
101
|
+
@type = :int
|
102
|
+
else
|
103
|
+
@type = type
|
104
|
+
end
|
105
|
+
|
106
|
+
raise "Still not type? (#{@args[:data]})" if @type.to_s.strip.length <= 0
|
107
|
+
end
|
108
|
+
|
109
|
+
return @type
|
110
|
+
end
|
111
|
+
|
112
|
+
#Returns true if the column allows null. Otherwise false.
|
113
|
+
def null?
|
114
|
+
return false if @args[:data][:notnull].to_i == 1
|
115
|
+
return true
|
116
|
+
end
|
117
|
+
|
118
|
+
#Returns the maxlength of the column.
|
119
|
+
def maxlength
|
120
|
+
self.type if !@maxlength
|
121
|
+
return @maxlength if @maxlength
|
122
|
+
return false
|
123
|
+
end
|
124
|
+
|
125
|
+
#Returns the default value of the column.
|
126
|
+
def default
|
127
|
+
def_val = @args[:data][:dflt_value]
|
128
|
+
if def_val.to_s.slice(0..0) == "'"
|
129
|
+
def_val = def_val.to_s.slice(0)
|
130
|
+
end
|
131
|
+
|
132
|
+
if def_val.to_s.slice(-1..-1) == "'"
|
133
|
+
def_val = def_val.to_s.slice(0, def_val.length - 1)
|
134
|
+
end
|
135
|
+
|
136
|
+
return false if @args[:data][:dflt_value].to_s.length == 0
|
137
|
+
return def_val
|
138
|
+
end
|
139
|
+
|
140
|
+
#Returns true if the column is the primary key.
|
141
|
+
def primarykey?
|
142
|
+
return false if @args[:data][:pk].to_i == 0
|
143
|
+
return true
|
144
|
+
end
|
145
|
+
|
146
|
+
#Returns true if the column is auto-increasing.
|
147
|
+
def autoincr?
|
148
|
+
return true if @args[:data][:pk].to_i == 1 and @args[:data][:type].to_s == "integer"
|
149
|
+
return false
|
150
|
+
end
|
151
|
+
|
152
|
+
#Drops the column from the table.
|
153
|
+
def drop
|
154
|
+
self.table.copy("drops" => self.name)
|
155
|
+
end
|
156
|
+
|
157
|
+
#Changes data on the column. Like the name, type, maxlength or whatever.
|
158
|
+
def change(data)
|
159
|
+
newdata = data.clone
|
160
|
+
|
161
|
+
newdata["name"] = self.name if !newdata.key?("name")
|
162
|
+
newdata["type"] = self.type if !newdata.key?("type")
|
163
|
+
newdata["maxlength"] = self.maxlength if !newdata.key?("maxlength") and self.maxlength
|
164
|
+
newdata["null"] = self.null? if !newdata.key?("null")
|
165
|
+
newdata["default"] = self.default if !newdata.key?("default")
|
166
|
+
newdata["primarykey"] = self.primarykey? if !newdata.key?("primarykey")
|
167
|
+
|
168
|
+
@type = nil
|
169
|
+
@maxlength = nil
|
170
|
+
|
171
|
+
new_table = self.table.copy(
|
172
|
+
"alter_columns" => {
|
173
|
+
self.name.to_s => newdata
|
174
|
+
}
|
175
|
+
)
|
176
|
+
end
|
177
|
+
end
|