mystic 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mystic.rb +92 -99
- data/lib/mystic/extensions.rb +11 -5
- data/lib/mystic/migration.rb +36 -46
- data/lib/mystic/model.rb +104 -98
- data/lib/mystic/postgres.rb +79 -0
- data/lib/mystic/sql.rb +5 -239
- data/lib/mystic/sql/column.rb +37 -0
- data/lib/mystic/sql/index.rb +78 -0
- data/lib/mystic/sql/table.rb +122 -0
- metadata +11 -12
- data/lib/mystic/adapter.rb +0 -145
- data/lib/mystic/adapters/abstract.rb +0 -90
- data/lib/mystic/adapters/mysql.rb +0 -51
- data/lib/mystic/adapters/postgres.rb +0 -95
- data/lib/mystic/constants.rb +0 -11
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "pg"
|
4
|
+
require "access_stack"
|
5
|
+
|
6
|
+
module Mystic
|
7
|
+
class Postgres
|
8
|
+
CONNECT_FIELDS = [
|
9
|
+
:host,
|
10
|
+
:hostaddr,
|
11
|
+
:port,
|
12
|
+
:dbname,
|
13
|
+
:user,
|
14
|
+
:password,
|
15
|
+
:connect_timeout,
|
16
|
+
:options,
|
17
|
+
:tty,
|
18
|
+
:sslmode,
|
19
|
+
:krbsrvname,
|
20
|
+
:gsslib
|
21
|
+
].freeze
|
22
|
+
|
23
|
+
INDEX_TYPES = [
|
24
|
+
:btree,
|
25
|
+
:hash,
|
26
|
+
:gist,
|
27
|
+
:spgist,
|
28
|
+
:gin
|
29
|
+
].freeze
|
30
|
+
|
31
|
+
def initialize opts={}
|
32
|
+
return if opts.empty?
|
33
|
+
@pool = AccessStack.new(
|
34
|
+
:size => opts[:pool] || 5,
|
35
|
+
:timeout => opts[:timeout] || 30,
|
36
|
+
:expires => opts[:expires],
|
37
|
+
:create => lambda { create_pg opts },
|
38
|
+
:destroy => lambda { |pg| pg.close },
|
39
|
+
:validate => lambda { |pg| pg != nil && pg.status == CONNECTION_OK }
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :connect, :initialize
|
44
|
+
|
45
|
+
def pool_size= v
|
46
|
+
@pool.size = v
|
47
|
+
end
|
48
|
+
|
49
|
+
def disconnect
|
50
|
+
@pool.empty!
|
51
|
+
end
|
52
|
+
|
53
|
+
def reap!
|
54
|
+
@pool.reap!
|
55
|
+
end
|
56
|
+
|
57
|
+
def connected?
|
58
|
+
!@pool.empty?
|
59
|
+
end
|
60
|
+
|
61
|
+
def escape str
|
62
|
+
@pool.with { |pg| pg.escape_string str }
|
63
|
+
end
|
64
|
+
|
65
|
+
def execute sql
|
66
|
+
res = @pool.with { |pg| pg.exec sql }
|
67
|
+
v = res[0][Mystic::JSON_COL] if res.ntuples == 1 && res.nfields == 1
|
68
|
+
v ||= res.ntuples.times.map { |i| res[i] } unless res.nil?
|
69
|
+
v ||= []
|
70
|
+
v
|
71
|
+
end
|
72
|
+
|
73
|
+
def create_pg opts
|
74
|
+
pg = PG.connect opts.subhash(*CONNECT_FIELDS)
|
75
|
+
pg.set_notice_receiver { |r| }
|
76
|
+
pg
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/mystic/sql.rb
CHANGED
@@ -2,243 +2,9 @@
|
|
2
2
|
|
3
3
|
module Mystic
|
4
4
|
module SQL
|
5
|
-
Error = Class.new
|
6
|
-
|
7
|
-
class SQLObject
|
8
|
-
def to_sql
|
9
|
-
Mystic.adapter.serialize_sql self
|
10
|
-
end
|
11
|
-
|
12
|
-
alias_method :to_s, :to_sql
|
13
|
-
end
|
14
|
-
|
15
|
-
class Index < SQLObject
|
16
|
-
attr_accessor :name, # Symbol or string
|
17
|
-
:table_name, # Symbol or string
|
18
|
-
:type, # Symbol
|
19
|
-
:unique, # TrueClass/FalseClass
|
20
|
-
:columns, # Array of Strings
|
21
|
-
:opts # Hash, see below
|
22
|
-
|
23
|
-
# opts
|
24
|
-
# It's a Hash that represents options
|
25
|
-
#
|
26
|
-
# MYSQL ONLY
|
27
|
-
# Key => Value (type)
|
28
|
-
# :comment => A string that's up to 1024 chars (String)
|
29
|
-
# :algorithm => The algorithm to use (Symbol)
|
30
|
-
# :lock => The lock to use (Symbol)
|
31
|
-
#
|
32
|
-
# POSTGRES ONLY
|
33
|
-
# Key => Value (type)
|
34
|
-
# :fillfactor => A value in the range 10..100 (Integer)
|
35
|
-
# :fastupdate => true/false (TrueClass/FalseClass)
|
36
|
-
# :concurrently => true/false (TrueClass/FalseClass)
|
37
|
-
# :tablespace => The name of the desired tablespace (String)
|
38
|
-
# :buffering => :on/:off/:auto (Symbol)
|
39
|
-
# :concurrently => true/false (TrueClass/FalseClass)
|
40
|
-
# :where => The conditions for including entries in your index, same as SELECT * FROM table WHERE ____ (String)
|
41
|
-
|
42
|
-
def initialize(opts={})
|
43
|
-
opts.symbolize!
|
44
|
-
raise ArgumentError, "Indeces need a table_name or else what's the point?." unless opts.member? :table_name
|
45
|
-
raise ArgumentError, "Indeces need columns or else what's the point?" unless opts.member? :columns
|
46
|
-
@name = opts.delete(:name).to_sym if opts.member? :name
|
47
|
-
@table_name = opts.delete(:table_name).to_sym
|
48
|
-
@type = (opts.delete :type || :btree).to_s.downcase.to_sym
|
49
|
-
@unique = opts.delete :unique || false
|
50
|
-
@columns = opts.delete(:columns).symbolize rescue []
|
51
|
-
@opts = opts
|
52
|
-
end
|
53
|
-
|
54
|
-
# can accept shit other than columns like
|
55
|
-
# box(location,location)
|
56
|
-
def <<(col)
|
57
|
-
case col
|
58
|
-
when Column
|
59
|
-
@columns << col.name.to_s
|
60
|
-
when String
|
61
|
-
@columns << col
|
62
|
-
else
|
63
|
-
raise ArgumentError, "Column must be a String or a Mystic::SQL::Column"
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
alias_method :push, :<<
|
68
|
-
|
69
|
-
def method_missing(meth, *args, &block)
|
70
|
-
return @opts[meth] if @opts.member? meth
|
71
|
-
nil
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
class Column < SQLObject
|
76
|
-
attr_accessor :name, :kind, :size, :constraints, :geom_kind, :geom_srid
|
77
|
-
|
78
|
-
def initialize(opts={})
|
79
|
-
@name = opts.delete(:name).to_s
|
80
|
-
@kind = opts.delete(:kind).to_sym
|
81
|
-
@size = opts.delete(:size).to_s if opts.member? :size
|
82
|
-
@geom_kind = opts.delete(:geom_kind)
|
83
|
-
@geom_srid = opts.delete(:geom_srid).to_i
|
84
|
-
@constraints = opts
|
85
|
-
end
|
86
|
-
|
87
|
-
def geospatial?
|
88
|
-
@geom_kind && @geom_srid
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
class Table < SQLObject
|
93
|
-
attr_reader :name
|
94
|
-
attr_accessor :columns,
|
95
|
-
:indeces,
|
96
|
-
:operations,
|
97
|
-
:opts
|
98
|
-
|
99
|
-
def self.create(opts={})
|
100
|
-
new true, opts
|
101
|
-
end
|
102
|
-
|
103
|
-
def self.alter(opts={})
|
104
|
-
new false, opts
|
105
|
-
end
|
106
|
-
|
107
|
-
def initialize(is_create=true, opts={})
|
108
|
-
@is_create = is_create
|
109
|
-
@opts = opts.symbolize
|
110
|
-
@columns = []
|
111
|
-
@indeces = []
|
112
|
-
@operations = []
|
113
|
-
|
114
|
-
@name = @opts.delete(:name).to_s
|
115
|
-
raise ArgumentError, "Argument 'name' is invalid." if @name.empty?
|
116
|
-
end
|
117
|
-
|
118
|
-
def create?
|
119
|
-
@is_create
|
120
|
-
end
|
121
|
-
|
122
|
-
def <<(obj)
|
123
|
-
case obj
|
124
|
-
when Column
|
125
|
-
@columns << obj
|
126
|
-
when Index
|
127
|
-
@indeces << obj
|
128
|
-
when Operation
|
129
|
-
@operations << obj
|
130
|
-
else
|
131
|
-
raise ArgumentError, "Argument is not a Mystic::SQL::Column, Mystic::SQL::Operation, or Mystic::SQL::Index."
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def to_sql
|
136
|
-
raise ArgumentError, "Table cannot have zero columns." if @columns.empty?
|
137
|
-
super
|
138
|
-
end
|
139
|
-
|
140
|
-
alias_method :push, :<<
|
141
|
-
|
142
|
-
#
|
143
|
-
## Operation DSL
|
144
|
-
#
|
145
|
-
|
146
|
-
def drop_index(idx_name)
|
147
|
-
raise Mystic::SQL::Error, "Cannot drop an index on a table that doesn't exist." if create?
|
148
|
-
self << Mystic::SQL::Operation.drop_index(
|
149
|
-
:index_name => idx_name.to_s,
|
150
|
-
:table_name => self.name.to_s
|
151
|
-
)
|
152
|
-
end
|
153
|
-
|
154
|
-
def rename_column(oldname, newname)
|
155
|
-
raise Mystic::SQL::Error, "Cannot rename a column on a table that doesn't exist." if create?
|
156
|
-
self << Mystic::SQL::Operation.rename_column(
|
157
|
-
:table_name => self.name.to_s,
|
158
|
-
:old_name => oldname.to_s,
|
159
|
-
:new_name => newname.to_s
|
160
|
-
)
|
161
|
-
end
|
162
|
-
|
163
|
-
def rename(newname)
|
164
|
-
raise Mystic::SQL::Error, "Cannot rename a table that doesn't exist." if create?
|
165
|
-
self << Mystic::SQL::Operation.rename_table(
|
166
|
-
:old_name => self.name.dup.to_s,
|
167
|
-
:new_name => newname.to_s,
|
168
|
-
:callback => lambda { self.name = newname }
|
169
|
-
)
|
170
|
-
end
|
171
|
-
|
172
|
-
def drop_columns(*col_names)
|
173
|
-
raise Mystic::SQL::Error, "Cannot drop a column(s) on a table that doesn't exist." if create?
|
174
|
-
self << Mystic::SQL::Operation.drop_columns(
|
175
|
-
:table_name => self.name.to_s,
|
176
|
-
:column_names => col_names.map(&:to_s)
|
177
|
-
)
|
178
|
-
end
|
179
|
-
|
180
|
-
#
|
181
|
-
## Column DSL
|
182
|
-
#
|
183
|
-
|
184
|
-
def column(col_name, kind, opts={})
|
185
|
-
self << Mystic::SQL::Column.new({
|
186
|
-
:name => col_name,
|
187
|
-
:kind => kind.to_sym
|
188
|
-
}.merge(opts || {}))
|
189
|
-
end
|
190
|
-
|
191
|
-
def geometry(col_name, kind, srid, opts={})
|
192
|
-
self << Mystic::SQL::Column.new({
|
193
|
-
:name => col_name,
|
194
|
-
:kind => :geometry,
|
195
|
-
:geom_kind => kind,
|
196
|
-
:geom_srid => srid
|
197
|
-
}.merge(opts || {}))
|
198
|
-
end
|
199
|
-
|
200
|
-
def index(*cols)
|
201
|
-
opts = cols.delete_at -1 if cols.last.is_a? Hash
|
202
|
-
opts ||= {}
|
203
|
-
opts[:columns] = cols
|
204
|
-
opts[:table_name] = @name
|
205
|
-
self << Mystic::SQL::Index.new(opts)
|
206
|
-
end
|
207
|
-
|
208
|
-
def method_missing(meth, *args, &block)
|
209
|
-
return column args[0], meth.to_s, args[1] if args.count > 0
|
210
|
-
return @opts[meth] if @opts.member?(meth)
|
211
|
-
nil
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
class Operation < SQLObject
|
216
|
-
attr_reader :kind,
|
217
|
-
:callback
|
218
|
-
|
219
|
-
def initialize(kind, opts={})
|
220
|
-
@kind = kind
|
221
|
-
@opts = opts.dup
|
222
|
-
@callback = @opts.delete :callback
|
223
|
-
end
|
224
|
-
|
225
|
-
def method_missing(meth, *args, &block)
|
226
|
-
@opts[meth.to_s.to_sym] rescue nil
|
227
|
-
end
|
228
|
-
|
229
|
-
def self.method_missing(meth, *args, &block)
|
230
|
-
new meth, (args[0] || {})
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
class Raw < SQLObject
|
235
|
-
def initialize(opts)
|
236
|
-
@sql = opts[:sql]
|
237
|
-
end
|
238
|
-
|
239
|
-
def to_sql
|
240
|
-
@sql
|
241
|
-
end
|
242
|
-
end
|
5
|
+
Error = Class.new StandardError
|
243
6
|
end
|
244
|
-
end
|
7
|
+
end
|
8
|
+
|
9
|
+
file_folder = File.dirname(File.absolute_path(__FILE__))
|
10
|
+
Dir.glob(file_folder + "/sql/**/*.rb", &method(:require))
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module Mystic
|
4
|
+
module SQL
|
5
|
+
class Column
|
6
|
+
attr_accessor :name, :kind, :size, :constraints, :geom_kind, :geom_srid
|
7
|
+
|
8
|
+
def initialize(opts={})
|
9
|
+
@name = opts.delete(:name).to_s
|
10
|
+
@kind = opts.delete(:kind).to_sym
|
11
|
+
@size = opts.delete(:size).to_s if opts.member? :size
|
12
|
+
@geom_kind = opts.delete(:geom_kind)
|
13
|
+
@geom_srid = opts.delete(:geom_srid).to_i
|
14
|
+
@constraints = opts
|
15
|
+
end
|
16
|
+
|
17
|
+
def geospatial?
|
18
|
+
@geom_kind && @geom_srid
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
sql = []
|
23
|
+
sql << name
|
24
|
+
sql << kind.downcase
|
25
|
+
sql << "(#{size})" if size && !size.empty? && !geospatial?
|
26
|
+
sql << "(#{geom_kind}, #{geom_srid})" if geospatial?
|
27
|
+
sql << (constraints[:null] ? "NULL" : "NOT NULL") if constraints.member?(:null)
|
28
|
+
sql << "UNIQUE" if constraints[:unique]
|
29
|
+
sql << "PRIMARY KEY" if constraints[:primary_key]
|
30
|
+
sql << "REFERENCES " + constraints[:references] if constraints.member?(:references)
|
31
|
+
sql << "DEFAULT " + constraints[:default] if constraints.member?(:default)
|
32
|
+
sql << "CHECK(#{constraints[:check]})" if constraints.member?(:check)
|
33
|
+
sql*" "
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module Mystic
|
4
|
+
module SQL
|
5
|
+
class Index
|
6
|
+
attr_accessor :name, # Symbol or string
|
7
|
+
:table_name, # Symbol or string
|
8
|
+
:type, # Symbol
|
9
|
+
:unique, # TrueClass/FalseClass
|
10
|
+
:columns, # Array of Strings
|
11
|
+
:opts # Hash, see below
|
12
|
+
|
13
|
+
INDEX_TYPES = [
|
14
|
+
:btree,
|
15
|
+
:hash,
|
16
|
+
:gist,
|
17
|
+
:spgist,
|
18
|
+
:gin
|
19
|
+
].freeze
|
20
|
+
|
21
|
+
# opts
|
22
|
+
# It's a Hash that represents options
|
23
|
+
#
|
24
|
+
# Key => Value (type)
|
25
|
+
# :fillfactor => A value in the range 10..100 (Integer)
|
26
|
+
# :fastupdate => true/false (TrueClass/FalseClass)
|
27
|
+
# :concurrently => true/false (TrueClass/FalseClass)
|
28
|
+
# :tablespace => The name of the desired tablespace (String)
|
29
|
+
# :buffering => :on/:off/:auto (Symbol)
|
30
|
+
# :concurrently => true/false (TrueClass/FalseClass)
|
31
|
+
# :where => The conditions for including entries in your index, same as SELECT * FROM table WHERE ____ (String)
|
32
|
+
|
33
|
+
def initialize opts={}
|
34
|
+
opts.symbolize!
|
35
|
+
raise ArgumentError, "Missing table_name." unless opts.member? :table_name
|
36
|
+
raise ArgumentError, "Indeces need columns or else what's the point?" unless opts.member? :columns
|
37
|
+
@name = opts.delete(:name).to_sym if opts.member? :name
|
38
|
+
@table_name = opts.delete(:table_name).to_sym
|
39
|
+
@type = (opts.delete(:type) || :btree).to_s.downcase.to_sym
|
40
|
+
@unique = opts.delete :unique || false
|
41
|
+
@columns = opts.delete(:columns).symbolize rescue []
|
42
|
+
@opts = opts
|
43
|
+
end
|
44
|
+
|
45
|
+
# can accept shit other than columns like
|
46
|
+
# box(location,location)
|
47
|
+
def << col
|
48
|
+
case col
|
49
|
+
when Column then @columns << col.name.to_s
|
50
|
+
when String then @columns << col
|
51
|
+
else raise ArgumentError, "Column must be a String or a Mystic::SQL::Column" end
|
52
|
+
end
|
53
|
+
|
54
|
+
def method_missing(meth, *args, &block)
|
55
|
+
return @opts[meth] if @opts.member? meth
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_s
|
60
|
+
storage_params = opts.subhash :fillfactor, :buffering, :fastupdate
|
61
|
+
|
62
|
+
sql = []
|
63
|
+
sql << "CREATE"
|
64
|
+
sql << "UNIQUE" if unique
|
65
|
+
sql << "INDEX"
|
66
|
+
sql << "CONCURENTLY" if concurrently
|
67
|
+
sql << name unless name.nil?
|
68
|
+
sql << "ON #{table_name}"
|
69
|
+
sql << "USING #{type}" if INDEX_TYPES.include? type
|
70
|
+
sql << "(#{columns.map(&:to_s).join ',' })"
|
71
|
+
sql << "WITH (#{storage_params.sqlize})" unless storage_params.empty?
|
72
|
+
sql << "TABLESPACE #{tablespace}" unless tablespace.nil?
|
73
|
+
sql << "WHERE #{where}" unless where.nil?
|
74
|
+
sql*' '
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module Mystic
|
4
|
+
module SQL
|
5
|
+
class Table
|
6
|
+
attr_reader :name
|
7
|
+
attr_accessor :columns,
|
8
|
+
:indeces,
|
9
|
+
:operations,
|
10
|
+
:opts
|
11
|
+
|
12
|
+
def self.create opts={}
|
13
|
+
new true, opts
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.alter opts={}
|
17
|
+
new false, opts
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize is_create=true, opts={}
|
21
|
+
@is_create = is_create
|
22
|
+
@opts = opts.symbolize
|
23
|
+
@columns = []
|
24
|
+
@indeces = []
|
25
|
+
@operations = []
|
26
|
+
|
27
|
+
@name = @opts.delete(:name).to_s
|
28
|
+
raise ArgumentError, "Argument 'name' is invalid." if @name.empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
def create?
|
32
|
+
@is_create
|
33
|
+
end
|
34
|
+
|
35
|
+
def << obj
|
36
|
+
case obj
|
37
|
+
when Column then @columns << obj
|
38
|
+
when Index then @indeces << obj
|
39
|
+
when Operation then @operations << obj
|
40
|
+
when String then @operations << obj
|
41
|
+
else raise ArgumentError, "Argument is not a Mystic::SQL::Column, Mystic::SQL::Operation, or Mystic::SQL::Index." end
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_s
|
45
|
+
raise ArgumentError, "Table cannot have zero columns." if @columns.empty?
|
46
|
+
sql = []
|
47
|
+
|
48
|
+
if create?
|
49
|
+
tbl = []
|
50
|
+
tbl << "CREATE TABLE #{name} (#{columns.map(&:to_s)*","})"
|
51
|
+
tbl << "INHERITS #{opts[:inherits]}" if opts[:inherits]
|
52
|
+
tbl << "TABLESPACE #{opts[:tablespace]}" if opts[:tablespace]
|
53
|
+
sql << tbl*' '
|
54
|
+
else
|
55
|
+
sql << "ALTER TABLE #{name} #{columns.map{ |c| "ADD COLUMN #{c.to_s}" }*', ' }"
|
56
|
+
end
|
57
|
+
|
58
|
+
sql.push(*indeces.map(&:to_s)) unless indeces.empty?
|
59
|
+
sql.push(*operations.map(&:to_s)) unless operations.empty?
|
60
|
+
sql*'; '
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
## Operation DSL
|
65
|
+
#
|
66
|
+
|
67
|
+
def drop_index idx_name
|
68
|
+
raise Mystic::SQL::Error, "Cannot drop an index on a table that doesn't exist." if create?
|
69
|
+
self << "DROP INDEX #{idx_name}"
|
70
|
+
end
|
71
|
+
|
72
|
+
def rename_column oldname, newname
|
73
|
+
raise Mystic::SQL::Error, "Cannot rename a column on a table that doesn't exist." if create?
|
74
|
+
self << "ALTER TABLE #{table_name} RENAME COLUMN #{old_name} TO #{new_name}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def rename newname
|
78
|
+
raise Mystic::SQL::Error, "Cannot rename a table that doesn't exist." if create?
|
79
|
+
self << "ALTER TABLE #{table_name} RENAME TO #{newname}"
|
80
|
+
self.name = newname
|
81
|
+
end
|
82
|
+
|
83
|
+
def drop_columns *col_names
|
84
|
+
raise Mystic::SQL::Error, "Cannot drop a column(s) on a table that doesn't exist." if create?
|
85
|
+
self << "ALTER TABLE #{table_name} #{col_names.map { |c| "DROP COLUMN #{c.to_s}" }*', ' }"
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
## Column DSL
|
90
|
+
#
|
91
|
+
|
92
|
+
def column col_name, kind, opts={}
|
93
|
+
self << Mystic::SQL::Column.new({
|
94
|
+
:name => col_name,
|
95
|
+
:kind => kind.to_sym
|
96
|
+
}.merge(opts || {}))
|
97
|
+
end
|
98
|
+
|
99
|
+
def geometry col_name, kind, srid, opts={}
|
100
|
+
self << Mystic::SQL::Column.new({
|
101
|
+
:name => col_name,
|
102
|
+
:kind => :geometry,
|
103
|
+
:geom_kind => kind,
|
104
|
+
:geom_srid => srid
|
105
|
+
}.merge(opts || {}))
|
106
|
+
end
|
107
|
+
|
108
|
+
def index *cols
|
109
|
+
opts = cols.delete_at -1 if cols.last.is_a? Hash
|
110
|
+
opts ||= {}
|
111
|
+
opts[:columns] = cols
|
112
|
+
opts[:table_name] = @name
|
113
|
+
self << Mystic::SQL::Index.new(opts)
|
114
|
+
end
|
115
|
+
|
116
|
+
def method_missing meth, *args, &block
|
117
|
+
return column args[0], meth.to_s, args[1] if args.count > 0
|
118
|
+
super
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|