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,155 @@
|
|
1
|
+
#This class handels various MySQL-column-specific operations.
|
2
|
+
class Baza::Driver::Mysql::Columns
|
3
|
+
#Constructor. Should not be called manually.
|
4
|
+
def initialize(args)
|
5
|
+
@args = args
|
6
|
+
end
|
7
|
+
|
8
|
+
#Returns the SQL for this column.
|
9
|
+
def data_sql(data)
|
10
|
+
raise "No type given." if !data["type"]
|
11
|
+
|
12
|
+
data["maxlength"] = 255 if data["type"] == "varchar" and !data.key?("maxlength")
|
13
|
+
|
14
|
+
sql = "`#{data["name"]}` #{data["type"]}"
|
15
|
+
sql << "(#{data["maxlength"]})" if data["maxlength"]
|
16
|
+
sql << " PRIMARY KEY" if data["primarykey"]
|
17
|
+
sql << " AUTO_INCREMENT" if data["autoincr"]
|
18
|
+
sql << " NOT NULL" if !data["null"]
|
19
|
+
|
20
|
+
if data.key?("default_func")
|
21
|
+
sql << " DEFAULT #{data["default_func"]}"
|
22
|
+
elsif data.key?("default") and data["default"] != false
|
23
|
+
sql << " DEFAULT '#{@args[:db].escape(data["default"])}'"
|
24
|
+
end
|
25
|
+
|
26
|
+
sql << " COMMENT '#{@args[:db].escape(data["comment"])}'" if data.key?("comment")
|
27
|
+
sql << " AFTER `#{@args[:db].esc_col(data["after"])}`" if data["after"] and !data["first"]
|
28
|
+
sql << " FIRST" if data["first"]
|
29
|
+
sql << " STORAGE #{data["storage"].to_s.upcase}" if data["storage"]
|
30
|
+
|
31
|
+
return sql
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
#This class handels every MySQL-column, that can be returned from a table-object.
|
36
|
+
class Baza::Driver::Mysql::Columns::Column
|
37
|
+
attr_reader :args
|
38
|
+
|
39
|
+
#Constructor. Should not be called manually.
|
40
|
+
def initialize(args)
|
41
|
+
@args = args
|
42
|
+
end
|
43
|
+
|
44
|
+
#Used to validate in Knj::Wrap_map.
|
45
|
+
def __object_unique_id__
|
46
|
+
return @args[:data][:Field]
|
47
|
+
end
|
48
|
+
|
49
|
+
#Returns the name of the column.
|
50
|
+
def name
|
51
|
+
return @args[:data][:Field]
|
52
|
+
end
|
53
|
+
|
54
|
+
#Returns the table-object that this column belongs to.
|
55
|
+
def table
|
56
|
+
return @args[:db].tables[@args[:table_name]]
|
57
|
+
end
|
58
|
+
|
59
|
+
#Returns all data of the column in the knjdb-format.
|
60
|
+
def data
|
61
|
+
return {
|
62
|
+
"type" => self.type,
|
63
|
+
"name" => self.name,
|
64
|
+
"null" => self.null?,
|
65
|
+
"maxlength" => self.maxlength,
|
66
|
+
"default" => self.default,
|
67
|
+
"primarykey" => self.primarykey?,
|
68
|
+
"autoincr" => self.autoincr?
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
#Returns the type of the column (integer, varchar etc.).
|
73
|
+
def type
|
74
|
+
if !@type
|
75
|
+
if match = @args[:data][:Type].match(/^([A-z]+)$/)
|
76
|
+
@maxlength = false
|
77
|
+
@type = match[0].to_sym
|
78
|
+
elsif match = @args[:data][:Type].match(/^decimal\((\d+),(\d+)\)$/)
|
79
|
+
@maxlength = "#{match[1]},#{match[2]}"
|
80
|
+
@type = :decimal
|
81
|
+
elsif match = @args[:data][:Type].match(/^enum\((.+)\)$/)
|
82
|
+
@maxlength = match[1]
|
83
|
+
@type = :enum
|
84
|
+
elsif match = @args[:data][:Type].match(/^(.+)\((\d+)\)/)
|
85
|
+
@maxlength = match[2].to_i
|
86
|
+
@type = match[1].to_sym
|
87
|
+
end
|
88
|
+
|
89
|
+
raise "Still not type from: '#{@args[:data][:Type]}'." if @type.to_s.strip.length <= 0
|
90
|
+
end
|
91
|
+
|
92
|
+
return @type
|
93
|
+
end
|
94
|
+
|
95
|
+
#Return true if the columns allows null. Otherwise false.
|
96
|
+
def null?
|
97
|
+
return false if @args[:data][:Null] == "NO"
|
98
|
+
return true
|
99
|
+
end
|
100
|
+
|
101
|
+
#Returns the maxlength.
|
102
|
+
def maxlength
|
103
|
+
self.type if !@maxlength
|
104
|
+
return @maxlength if @maxlength
|
105
|
+
return false
|
106
|
+
end
|
107
|
+
|
108
|
+
#Returns the default value for the column.
|
109
|
+
def default
|
110
|
+
return false if (self.type == "datetime" or self.type == "date") and @args[:data][:Default].to_s.strip.length <= 0
|
111
|
+
return false if (self.type == "int" or self.type == "bigint") and @args[:data][:Default].to_s.strip.length <= 0
|
112
|
+
return false if !@args[:data][:Default]
|
113
|
+
return @args[:data][:Default]
|
114
|
+
end
|
115
|
+
|
116
|
+
#Returns true if the column is the primary key. Otherwise false.
|
117
|
+
def primarykey?
|
118
|
+
return true if @args[:data][:Key] == "PRI"
|
119
|
+
return false
|
120
|
+
end
|
121
|
+
|
122
|
+
#Returns true if the column is auto-increasing. Otherwise false.
|
123
|
+
def autoincr?
|
124
|
+
return true if @args[:data][:Extra].index("auto_increment") != nil
|
125
|
+
return false
|
126
|
+
end
|
127
|
+
|
128
|
+
#Returns the comment for the column.
|
129
|
+
def comment
|
130
|
+
return @args[:data][:Comment]
|
131
|
+
end
|
132
|
+
|
133
|
+
#Drops the column from the table.
|
134
|
+
def drop
|
135
|
+
@args[:db].query("ALTER TABLE `#{@args[:table_name]}` DROP COLUMN `#{self.name}`")
|
136
|
+
return nil
|
137
|
+
end
|
138
|
+
|
139
|
+
#Changes the column properties by the given hash.
|
140
|
+
def change(data)
|
141
|
+
col_escaped = "`#{@args[:db].esc_col(self.name)}`"
|
142
|
+
table_escape = "`#{@args[:db].esc_table(self.table.name)}`"
|
143
|
+
newdata = data.clone
|
144
|
+
|
145
|
+
newdata["name"] = self.name if !newdata.key?("name")
|
146
|
+
newdata["type"] = self.type if !newdata.key?("type")
|
147
|
+
newdata["maxlength"] = self.maxlength if !newdata.key?("maxlength") and self.maxlength
|
148
|
+
newdata["null"] = self.null? if !newdata.key?("null")
|
149
|
+
newdata["default"] = self.default if !newdata.key?("default") and self.default
|
150
|
+
newdata.delete("primarykey") if newdata.key?("primarykey")
|
151
|
+
|
152
|
+
type_s = newdata["type"].to_s
|
153
|
+
@args[:db].query("ALTER TABLE #{table_escape} CHANGE #{col_escaped} #{@args[:db].cols.data_sql(newdata)}")
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class Baza::Driver::Mysql::Indexes
|
2
|
+
def initialize(args)
|
3
|
+
@args = args
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class Baza::Driver::Mysql::Indexes::Index
|
8
|
+
attr_reader :columns
|
9
|
+
|
10
|
+
def initialize(args)
|
11
|
+
@args = args
|
12
|
+
@columns = []
|
13
|
+
end
|
14
|
+
|
15
|
+
#Used to validate in Knj::Wrap_map.
|
16
|
+
def __object_unique_id__
|
17
|
+
return @args[:data][:Key_name]
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
return @args[:data][:Key_name]
|
22
|
+
end
|
23
|
+
|
24
|
+
def table
|
25
|
+
return @args[:db].tables[@args[:table_name]]
|
26
|
+
end
|
27
|
+
|
28
|
+
def drop
|
29
|
+
sql = "DROP INDEX `#{self.name}` ON `#{self.table.name}`"
|
30
|
+
|
31
|
+
begin
|
32
|
+
@args[:db].query(sql)
|
33
|
+
rescue => e
|
34
|
+
#The index has already been dropped - ignore.
|
35
|
+
if e.message.index("check that column/key exists") != nil
|
36
|
+
#ignore.
|
37
|
+
else
|
38
|
+
raise e
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def data
|
44
|
+
return {
|
45
|
+
"name" => name,
|
46
|
+
"columns" => @columns
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
#Returns true if the index is a unique-index.
|
51
|
+
def unique?
|
52
|
+
if @args[:data][:Index_type] == "UNIQUE"
|
53
|
+
return true
|
54
|
+
else
|
55
|
+
return false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
#Returns true if the index is a primary-index.
|
60
|
+
def primary?
|
61
|
+
return true if @args[:data][:Index_type] == "BTREE"
|
62
|
+
return false
|
63
|
+
end
|
64
|
+
|
65
|
+
#Inspect crashes if this is not present? - knj.
|
66
|
+
def to_s
|
67
|
+
return "#<#{self.class.name}>"
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,443 @@
|
|
1
|
+
require "monitor"
|
2
|
+
|
3
|
+
#This class handels various MySQL-table-specific behaviour.
|
4
|
+
class Baza::Driver::Mysql::Tables
|
5
|
+
attr_reader :db, :list
|
6
|
+
|
7
|
+
#Constructor. This should not be called manually.
|
8
|
+
def initialize(args)
|
9
|
+
@args = args
|
10
|
+
@db = @args[:db]
|
11
|
+
@subtype = @db.opts[:subtype]
|
12
|
+
@list_mutex = Monitor.new
|
13
|
+
@list = Wref_map.new
|
14
|
+
@list_should_be_reloaded = true
|
15
|
+
end
|
16
|
+
|
17
|
+
#Cleans the wref-map.
|
18
|
+
def clean
|
19
|
+
@list.clean
|
20
|
+
end
|
21
|
+
|
22
|
+
#Returns a table by the given table-name.
|
23
|
+
def [](table_name)
|
24
|
+
table_name = table_name.to_s
|
25
|
+
|
26
|
+
begin
|
27
|
+
return @list[table_name]
|
28
|
+
rescue Wref::Recycled
|
29
|
+
#ignore.
|
30
|
+
end
|
31
|
+
|
32
|
+
self.list(:name => table_name) do |table_obj|
|
33
|
+
return table_obj if table_obj.name == table_name
|
34
|
+
end
|
35
|
+
|
36
|
+
raise Errno::ENOENT, "Table was not found: #{table_name}."
|
37
|
+
end
|
38
|
+
|
39
|
+
#Yields the tables of the current database.
|
40
|
+
def list(args = {})
|
41
|
+
ret = {} unless block_given?
|
42
|
+
|
43
|
+
sql = "SHOW TABLE STATUS"
|
44
|
+
sql << " WHERE `Name` = '#{@db.esc(args[:name])}'" if args[:name]
|
45
|
+
|
46
|
+
@list_mutex.synchronize do
|
47
|
+
@db.q(sql) do |d_tables|
|
48
|
+
obj = @list.get!(d_tables[:Name])
|
49
|
+
|
50
|
+
if !obj
|
51
|
+
obj = Baza::Driver::Mysql::Tables::Table.new(
|
52
|
+
:db => @db,
|
53
|
+
:data => d_tables
|
54
|
+
)
|
55
|
+
@list[d_tables[:Name]] = obj
|
56
|
+
end
|
57
|
+
|
58
|
+
if block_given?
|
59
|
+
yield(obj)
|
60
|
+
else
|
61
|
+
ret[d_tables[:Name]] = obj
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
if block_given?
|
67
|
+
return nil
|
68
|
+
else
|
69
|
+
return ret
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
#Creates a new table by the given name and data.
|
74
|
+
def create(name, data, args = nil)
|
75
|
+
raise "No columns was given for '#{name}'." if !data["columns"] or data["columns"].empty?
|
76
|
+
|
77
|
+
sql = "CREATE"
|
78
|
+
sql << " TEMPORARY" if data["temp"]
|
79
|
+
sql << " TABLE `#{name}` ("
|
80
|
+
|
81
|
+
first = true
|
82
|
+
data["columns"].each do |col_data|
|
83
|
+
sql << ", " if !first
|
84
|
+
first = false if first
|
85
|
+
col_data.delete("after") if col_data["after"]
|
86
|
+
sql << @db.cols.data_sql(col_data)
|
87
|
+
end
|
88
|
+
|
89
|
+
if data["indexes"] and !data["indexes"].empty?
|
90
|
+
sql << ", "
|
91
|
+
sql << Baza::Driver::Mysql::Tables::Table.create_indexes(data["indexes"], {
|
92
|
+
:db => @db,
|
93
|
+
:return_sql => true,
|
94
|
+
:create => false,
|
95
|
+
:on_table => false,
|
96
|
+
:table_name => name
|
97
|
+
})
|
98
|
+
end
|
99
|
+
|
100
|
+
sql << ")"
|
101
|
+
|
102
|
+
return [sql] if args and args[:return_sql]
|
103
|
+
@db.query(sql)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Baza::Driver::Mysql::Tables::Table
|
108
|
+
attr_reader :list
|
109
|
+
|
110
|
+
def initialize(args)
|
111
|
+
@args = args
|
112
|
+
@db = args[:db]
|
113
|
+
@data = args[:data]
|
114
|
+
@subtype = @db.opts[:subtype]
|
115
|
+
@list = Wref_map.new
|
116
|
+
@indexes_list = Wref_map.new
|
117
|
+
|
118
|
+
raise "Could not figure out name from: '#{@data}'." if @data[:Name].to_s.strip.length <= 0
|
119
|
+
end
|
120
|
+
|
121
|
+
def reload
|
122
|
+
@data = @db.q("SHOW TABLE STATUS WHERE `Name` = '#{@db.esc(self.name)}'").fetch
|
123
|
+
end
|
124
|
+
|
125
|
+
#Used to validate in Knj::Wrap_map.
|
126
|
+
def __object_unique_id__
|
127
|
+
return @data[:Name]
|
128
|
+
end
|
129
|
+
|
130
|
+
def name
|
131
|
+
return @data[:Name]
|
132
|
+
end
|
133
|
+
|
134
|
+
def drop
|
135
|
+
raise "Cant drop native table: '#{self.name}'." if self.native?
|
136
|
+
@db.query("DROP TABLE `#{self.name}`")
|
137
|
+
end
|
138
|
+
|
139
|
+
#Returns true if the table is safe to drop.
|
140
|
+
def native?
|
141
|
+
return true if @db.q("SELECT DATABASE() AS db").fetch[:db] == "mysql"
|
142
|
+
return false
|
143
|
+
end
|
144
|
+
|
145
|
+
def optimize
|
146
|
+
@db.query("OPTIMIZE TABLE `#{self.name}`")
|
147
|
+
return self
|
148
|
+
end
|
149
|
+
|
150
|
+
def rows_count
|
151
|
+
return @data[:Rows].to_i
|
152
|
+
end
|
153
|
+
|
154
|
+
def column(name)
|
155
|
+
name = name.to_s
|
156
|
+
|
157
|
+
if col = @list.get!(name)
|
158
|
+
return @list[name]
|
159
|
+
end
|
160
|
+
|
161
|
+
self.columns(:name => name) do |col|
|
162
|
+
return col if col.name == name
|
163
|
+
end
|
164
|
+
|
165
|
+
raise Errno::ENOENT, "Column not found: '#{name}'."
|
166
|
+
end
|
167
|
+
|
168
|
+
def columns(args = nil)
|
169
|
+
@db.cols
|
170
|
+
ret = {}
|
171
|
+
sql = "SHOW FULL COLUMNS FROM `#{self.name}`"
|
172
|
+
sql << " WHERE `Field` = '#{@db.esc(args[:name])}'" if args and args.key?(:name)
|
173
|
+
|
174
|
+
@db.q(sql) do |d_cols|
|
175
|
+
obj = @list.get!(d_cols[:Field].to_s)
|
176
|
+
|
177
|
+
if !obj
|
178
|
+
obj = Baza::Driver::Mysql::Columns::Column.new(
|
179
|
+
:table_name => self.name,
|
180
|
+
:db => @db,
|
181
|
+
:data => d_cols
|
182
|
+
)
|
183
|
+
@list[d_cols[:Field].to_s] = obj
|
184
|
+
end
|
185
|
+
|
186
|
+
if block_given?
|
187
|
+
yield(obj)
|
188
|
+
else
|
189
|
+
ret[d_cols[:Field].to_s] = obj
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
if block_given?
|
194
|
+
return nil
|
195
|
+
else
|
196
|
+
return ret
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def indexes(args = nil)
|
201
|
+
@db.indexes
|
202
|
+
ret = {}
|
203
|
+
|
204
|
+
sql = "SHOW INDEX FROM `#{self.name}`"
|
205
|
+
sql << " WHERE `Key_name` = '#{@db.esc(args[:name])}'" if args and args.key?(:name)
|
206
|
+
|
207
|
+
@db.q(sql) do |d_indexes|
|
208
|
+
next if d_indexes[:Key_name] == "PRIMARY"
|
209
|
+
|
210
|
+
obj = @indexes_list.get!(d_indexes[:Key_name].to_s)
|
211
|
+
|
212
|
+
if !obj
|
213
|
+
obj = Baza::Driver::Mysql::Indexes::Index.new(
|
214
|
+
:table_name => self.name,
|
215
|
+
:db => @db,
|
216
|
+
:data => d_indexes
|
217
|
+
)
|
218
|
+
obj.columns << d_indexes[:Column_name]
|
219
|
+
@indexes_list[d_indexes[:Key_name].to_s] = obj
|
220
|
+
end
|
221
|
+
|
222
|
+
if block_given?
|
223
|
+
yield(obj)
|
224
|
+
else
|
225
|
+
ret[d_indexes[:Key_name].to_s] = obj
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
if block_given?
|
230
|
+
return nil
|
231
|
+
else
|
232
|
+
return ret
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def index(name)
|
237
|
+
name = name.to_s
|
238
|
+
|
239
|
+
if index = @indexes_list.get!(name)
|
240
|
+
return index
|
241
|
+
end
|
242
|
+
|
243
|
+
self.indexes(:name => name) do |index|
|
244
|
+
return index if index.name.to_s == name
|
245
|
+
end
|
246
|
+
|
247
|
+
raise Errno::ENOENT, "Index not found: #{name}."
|
248
|
+
end
|
249
|
+
|
250
|
+
def create_columns(col_arr)
|
251
|
+
col_arr.each do |col_data|
|
252
|
+
sql = "ALTER TABLE `#{self.name}` ADD COLUMN #{@db.cols.data_sql(col_data)};"
|
253
|
+
@db.query(sql)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def create_indexes(index_arr, args = {})
|
258
|
+
return Baza::Driver::Mysql::Tables::Table.create_indexes(index_arr, args.merge(:table_name => self.name, :db => @db))
|
259
|
+
end
|
260
|
+
|
261
|
+
def self.create_indexes(index_arr, args = {})
|
262
|
+
db = args[:db]
|
263
|
+
|
264
|
+
if args[:return_sql]
|
265
|
+
sql = ""
|
266
|
+
first = true
|
267
|
+
end
|
268
|
+
|
269
|
+
index_arr.each do |index_data|
|
270
|
+
if !args[:return_sql]
|
271
|
+
sql = ""
|
272
|
+
end
|
273
|
+
|
274
|
+
if args[:create] or !args.key?(:create)
|
275
|
+
sql << "CREATE"
|
276
|
+
end
|
277
|
+
|
278
|
+
if index_data.is_a?(String)
|
279
|
+
index_data = {"name" => index_data, "columns" => [index_data]}
|
280
|
+
end
|
281
|
+
|
282
|
+
raise "No name was given." if !index_data.key?("name") or index_data["name"].strip.length <= 0
|
283
|
+
raise "No columns was given on index: '#{index_data["name"]}'." if !index_data["columns"] or index_data["columns"].empty?
|
284
|
+
|
285
|
+
if args[:return_sql]
|
286
|
+
if first
|
287
|
+
first = false
|
288
|
+
else
|
289
|
+
sql << ", "
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
sql << " UNIQUE" if index_data["unique"]
|
294
|
+
sql << " INDEX `#{db.esc_col(index_data["name"])}`"
|
295
|
+
|
296
|
+
if args[:on_table] or !args.key?(:on_table)
|
297
|
+
sql << " ON `#{db.esc_table(args[:table_name])}`"
|
298
|
+
end
|
299
|
+
|
300
|
+
sql << " ("
|
301
|
+
|
302
|
+
first = true
|
303
|
+
index_data["columns"].each do |col_name|
|
304
|
+
sql << ", " if !first
|
305
|
+
first = false if first
|
306
|
+
|
307
|
+
sql << "`#{db.esc_col(col_name)}`"
|
308
|
+
end
|
309
|
+
|
310
|
+
sql << ")"
|
311
|
+
|
312
|
+
if !args[:return_sql]
|
313
|
+
db.query(sql)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
if args[:return_sql]
|
318
|
+
return sql
|
319
|
+
else
|
320
|
+
return nil
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
def rename(newname)
|
325
|
+
oldname = self.name
|
326
|
+
@db.query("ALTER TABLE `#{oldname}` RENAME TO `#{newname}`")
|
327
|
+
@db.tables.list[newname] = self
|
328
|
+
@db.tables.list.delete(oldname)
|
329
|
+
@data[:Name] = newname
|
330
|
+
end
|
331
|
+
|
332
|
+
def truncate
|
333
|
+
@db.query("TRUNCATE `#{self.name}`")
|
334
|
+
return self
|
335
|
+
end
|
336
|
+
|
337
|
+
def data
|
338
|
+
ret = {
|
339
|
+
"name" => self.name,
|
340
|
+
"columns" => [],
|
341
|
+
"indexes" => []
|
342
|
+
}
|
343
|
+
|
344
|
+
columns.each do |name, column|
|
345
|
+
ret["columns"] << column.data
|
346
|
+
end
|
347
|
+
|
348
|
+
indexes.each do |name, index|
|
349
|
+
ret["indexes"] << index.data if name != "PRIMARY"
|
350
|
+
end
|
351
|
+
|
352
|
+
return ret
|
353
|
+
end
|
354
|
+
|
355
|
+
def insert(data)
|
356
|
+
@db.insert(self.name, data)
|
357
|
+
end
|
358
|
+
|
359
|
+
#Returns the current engine of the table.
|
360
|
+
def engine
|
361
|
+
return @data[:Engine]
|
362
|
+
end
|
363
|
+
|
364
|
+
def clone(newname, args = {})
|
365
|
+
raise "Invalid name." if newname.to_s.strip.empty?
|
366
|
+
|
367
|
+
sql = "CREATE TABLE `#{@db.esc_table(newname)}` ("
|
368
|
+
first = true
|
369
|
+
pkey_found = false
|
370
|
+
pkeys = []
|
371
|
+
|
372
|
+
self.columns do |col|
|
373
|
+
sql << ", " if !first
|
374
|
+
first = false if first
|
375
|
+
|
376
|
+
col_data = col.data
|
377
|
+
pkey_found = true if !pkey_found and col_data["primarykey"] and args[:force_single_pkey]
|
378
|
+
|
379
|
+
if args[:no_pkey] or (pkey_found and col_data["primarykey"] and args[:force_single_pkey])
|
380
|
+
col_data["primarykey"] = false
|
381
|
+
end
|
382
|
+
|
383
|
+
if col_data["primarykey"]
|
384
|
+
pkeys << col_data["name"]
|
385
|
+
col_data.delete("primarykey")
|
386
|
+
end
|
387
|
+
|
388
|
+
if args[:all_cols_storage]
|
389
|
+
col_data["storage"] = args[:all_cols_storage]
|
390
|
+
end
|
391
|
+
|
392
|
+
sql << @db.cols.data_sql(col_data)
|
393
|
+
end
|
394
|
+
|
395
|
+
if !pkeys.empty?
|
396
|
+
sql << ", PRIMARY KEY ("
|
397
|
+
|
398
|
+
first = true
|
399
|
+
pkeys.each do |pkey|
|
400
|
+
sql << ", " if !first
|
401
|
+
first = false if first
|
402
|
+
sql << "`#{@db.esc_col(pkey)}`"
|
403
|
+
end
|
404
|
+
|
405
|
+
sql << ")"
|
406
|
+
end
|
407
|
+
|
408
|
+
sql << ")"
|
409
|
+
sql << " TABLESPACE #{args[:tablespace]}" if args[:tablespace]
|
410
|
+
sql << " ENGINE=#{args[:engine]}" if args[:engine]
|
411
|
+
sql << ";"
|
412
|
+
|
413
|
+
puts sql
|
414
|
+
|
415
|
+
#Create table.
|
416
|
+
@db.query(sql)
|
417
|
+
|
418
|
+
|
419
|
+
#Insert data of previous data in a single query.
|
420
|
+
@db.query("INSERT INTO `#{newname}` SELECT * FROM `#{self.name}`")
|
421
|
+
|
422
|
+
|
423
|
+
#Create indexes.
|
424
|
+
new_table = @db.tables[newname]
|
425
|
+
indexes_list = []
|
426
|
+
self.indexes do |index|
|
427
|
+
indexes_list << index.data if !index.primary?
|
428
|
+
end
|
429
|
+
|
430
|
+
new_table.create_indexes(indexes_list)
|
431
|
+
|
432
|
+
|
433
|
+
#Return new table.
|
434
|
+
return new_table
|
435
|
+
end
|
436
|
+
|
437
|
+
#Changes the engine for a table.
|
438
|
+
def engine=(newengine)
|
439
|
+
raise "Invalid engine: '#{newengine}'." if !newengine.to_s.match(/^[A-z]+$/)
|
440
|
+
@db.query("ALTER TABLE `#{@db.esc_table(self.name)}` ENGINE = #{newengine}") if self.engine.to_s != newengine.to_s
|
441
|
+
@data[:Engine] = newengine
|
442
|
+
end
|
443
|
+
end
|