mystic 0.0.9 → 0.1.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.
- 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
|