mystic 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mystic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathaniel Symer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-11 00:00:00.000000000 Z
11
+ date: 2014-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: densify
@@ -38,9 +38,9 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- description: Database management/access gem. Supports adapters, migrations, and a
42
- singleton to make SQL queries.
43
- email: nate@ivytap.com
41
+ description: Pooled PG singleton instance. Focus more on writing SQL than dealing
42
+ with a finnicky ORM. It powers the Pawky backend.
43
+ email: nate@natesymer.com
44
44
  executables:
45
45
  - mystic
46
46
  extensions: []
@@ -49,15 +49,14 @@ files:
49
49
  - LICENSE
50
50
  - bin/mystic
51
51
  - lib/mystic.rb
52
- - lib/mystic/adapter.rb
53
- - lib/mystic/adapters/abstract.rb
54
- - lib/mystic/adapters/mysql.rb
55
- - lib/mystic/adapters/postgres.rb
56
- - lib/mystic/constants.rb
57
52
  - lib/mystic/extensions.rb
58
53
  - lib/mystic/migration.rb
59
54
  - lib/mystic/model.rb
55
+ - lib/mystic/postgres.rb
60
56
  - lib/mystic/sql.rb
57
+ - lib/mystic/sql/column.rb
58
+ - lib/mystic/sql/index.rb
59
+ - lib/mystic/sql/table.rb
61
60
  homepage: https://github.com/ivytap/mystic
62
61
  licenses:
63
62
  - MIT
@@ -81,6 +80,6 @@ rubyforge_project:
81
80
  rubygems_version: 2.2.2
82
81
  signing_key:
83
82
  specification_version: 4
84
- summary: Expressive migrations and adapters coupled with a singleton for SQL execution.
85
- Heroku, rails, whatever compatible.
83
+ summary: Pooled PG singleton instance. Focus more on writing SQL than dealing with
84
+ a finnicky ORM.
86
85
  test_files: []
@@ -1,145 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "densify"
4
- require "access_stack"
5
-
6
- module Mystic
7
- class Adapter
8
- attr_accessor :pool_size,
9
- :pool_timeout,
10
- :pool_expires
11
-
12
- @@blocks = {}
13
-
14
- def self.create(name="",opts={})
15
- name = name.to_s.downcase.strip
16
- name = "postgres" if name =~ /^postg.*$/i # Includes PostGIS
17
- name = "mysql" if name =~ /^mysql.*$/i
18
-
19
- require "mystic/adapters/" + name
20
-
21
- Object.const_get("Mystic::#{name.capitalize}Adapter").new opts
22
- end
23
-
24
- def initialize(opts={})
25
- opts.symbolize.each do |k,v|
26
- k = ('@' + k.to_s).to_sym
27
- instance_variable_set k,v if instance_variables.include? k
28
- end
29
- end
30
-
31
- # Gets the adapter name (examples: postgres, mysql)
32
- def self.adapter
33
- a = name.split("::").last.sub("Adapter","").downcase
34
- a = "abstract" if a.empty?
35
- a
36
- end
37
-
38
- def adapter
39
- self.class.adapter
40
- end
41
-
42
- # Map a block to an adapter's block hash
43
- # This avoids cases where a subclass' class var
44
- # changes that class var on its superclass
45
- def self.map_block(key, block)
46
- @@blocks[adapter] ||= {}
47
- @@blocks[adapter][key] = block
48
- end
49
-
50
- # Fetch a block for the current adapter
51
- def block_for(key)
52
- b = @@blocks[adapter][key] rescue nil
53
- b ||= @@blocks["abstract"][key] rescue nil
54
- b ||= lambda { "" }
55
- b
56
- end
57
-
58
- #
59
- # Adapter DSL
60
- # Implemented using method_missing
61
- #
62
-
63
- # example
64
- # execute do |inst,sql|
65
- # inst.exec sql
66
- # end
67
-
68
- # execute(inst,sql)
69
- # Executes SQL and returns Ruby types
70
-
71
- # TODO: different kinds of escaping: ident & quote
72
-
73
- # sanitize(inst,sql)
74
- # Escapes a literal
75
-
76
- # connect(opts)
77
- # Creates an instance of the DB connection
78
-
79
- # disconnect(inst)
80
- # Disconnects and destroys inst (a database connection)
81
-
82
- # validate(inst)
83
- # Checks if inst is a valid connection
84
-
85
- # Map missing methods to blocks
86
- # DB ops or SQL generation
87
- def self.method_missing(meth, *args, &block)
88
- map_block meth, block
89
- end
90
-
91
- #
92
- # Adapter methods
93
- # These are called internally
94
- # They are called by class methods
95
- # in ../mystic.rb
96
- #
97
- def connect(opts)
98
- disconnect unless @pool.nil?
99
- @pool = AccessStack.new(
100
- :size => @pool_size,
101
- :timeout => @pool_timeout,
102
- :expires => @pool_expires,
103
- :create => lambda { block_for(:connect).call opts }
104
- )
105
- end
106
-
107
- def disconnect
108
- @pool.destroy ||= block_for :disconnect
109
- @pool.empty!
110
- end
111
-
112
- def reap
113
- @pool.validate ||= block_for :validate
114
- @pool.reap
115
- end
116
-
117
- def execute(sql)
118
- raise AdapterError, "Adapter's connection pool doesn't exist and so Mystic has not connected to the database." if @pool.nil?
119
- @pool.with { |inst| block_for(:execute).call inst, sql }
120
- end
121
-
122
- def sanitize(str)
123
- @pool.with { |inst| block_for(:sanitize).call inst, str }
124
- end
125
-
126
- def json_supported?
127
- block_for(:json_supported).call
128
- end
129
-
130
- def serialize_sql(obj)
131
- return case obj
132
- when SQL::Table
133
- block_for(:table).call obj
134
- when SQL::Index
135
- block_for(:index).call obj
136
- when SQL::Column
137
- block_for(:column).call obj
138
- when SQL::Operation
139
- res = block_for(obj.kind).call obj
140
- obj.callback.call unless obj.callback.nil?
141
- res
142
- end
143
- end
144
- end
145
- end
@@ -1,90 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "mystic"
4
- require "mystic/adapter"
5
- require "mystic/sql"
6
-
7
- #
8
- # This adapter is designed to hold
9
- # basic, spec-adherent SQL generation
10
- # so adapters can be more DRY
11
- #
12
-
13
- module Mystic
14
- class Adapter
15
-
16
- json_supported { false }
17
-
18
- table do |obj|
19
- sql = []
20
- sql.push "CREATE TABLE #{obj.name} (#{obj.columns.map(&:to_sql)*","})" if obj.create?
21
- sql.push "ALTER TABLE #{obj.name} #{obj.columns.map{|c| "ADD COLUMN #{c.to_sql}" }*', '}" unless obj.create?
22
- sql.push *(obj.indeces.map(&:to_sql)) unless obj.indeces.empty?
23
- sql.push *(obj.operations.map(&:to_sql)) unless obj.operations.empty?
24
- sql*"; "
25
- end
26
-
27
- column do |obj|
28
- sql = []
29
- sql << obj.name
30
- sql << obj.kind.downcase
31
- sql << "(#{obj.size})" if obj.size && !obj.size.empty? && !obj.geospatial?
32
- sql << "(#{obj.geom_kind}, #{obj.geom_srid})" if obj.geospatial?
33
- sql << (obj.constraints[:null] ? "NULL" : "NOT NULL") if obj.constraints.member?(:null)
34
- sql << "UNIQUE" if obj.constraints[:unique]
35
- sql << "PRIMARY KEY" if obj.constraints[:primary_key]
36
- sql << "REFERENCES " + obj.constraints[:references] if obj.constraints.member?(:references)
37
- sql << "DEFAULT " + obj.constraints[:default] if obj.constraints.member?(:default)
38
- sql << "CHECK(#{obj.constraints[:check]})" if obj.constraints.member?(:check)
39
- sql*" "
40
- end
41
-
42
- index do |index|
43
- sql = []
44
- sql << "CREATE"
45
- sql << "UNIQUE" if index.unique
46
- sql << "INDEX"
47
- sql << index.name if index.name
48
- sql << "ON"
49
- sql << index.table_name
50
- sql << "(#{index.columns.map(&:to_s).join(',')})"
51
- sql*" "
52
- end
53
-
54
- #
55
- ## Operations
56
- #
57
-
58
- drop_columns do |obj|
59
- "ALTER TABLE #{obj.table_name} #{obj.column_names.map{|c| "DROP COLUMN #{c.to_s}" }*', '}"
60
- end
61
-
62
- rename_column do |obj|
63
- "ALTER TABLE #{obj.table_name} RENAME COLUMN #{obj.old_name} TO #{obj.new_name}"
64
- end
65
-
66
- create_view do |obj|
67
- "CREATE VIEW #{obj.name} AS #{obj.sql}"
68
- end
69
-
70
- drop_view do |obj|
71
- "DROP VIEW #{obj.name}"
72
- end
73
-
74
- drop_table do |obj|
75
- "DROP TABLE #{obj.table_name} #{obj.cascade? ? "CASCADE" : "RESTRICT" }"
76
- end
77
-
78
- rename_table do |obj|
79
- "ALTER TABLE #{obj.old_name} RENAME TO #{obj.new_name}"
80
- end
81
-
82
- #
83
- ## Transaction Operations
84
- #
85
-
86
- start_transaction { "BEGIN" }
87
- commit_transaction { "COMMIT" }
88
- rollback_transaction { "ROLLBACK" }
89
- end
90
- end
@@ -1,51 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "mysql2"
4
-
5
- # TODO:
6
- # 1. Implement geometry
7
-
8
- module Mystic
9
- class MysqlAdapter < Mystic::Adapter
10
- ALGORITHMS = [:default, :inplace, :copy]
11
- LOCKS = [:default, :none, :shared, :exclusive]
12
-
13
- connect { |opts| Mysql2::client.new opts }
14
- disconnect { |mysql| mysql.close }
15
- validate { |mysql| mysql.ping }
16
- execute { |mysql, sql| mysql.query(sql).to_a }
17
- sanitize { |mysql, str| mysql.escape str }
18
-
19
- drop_index do |index|
20
- "DROP INDEX #{index.name} ON #{index.table_name}"
21
- end
22
-
23
- index do |index|
24
- sql = []
25
- sql << "CREATE"
26
- sql << "UNIQUE" if index.unique
27
- sql << "INDEX"
28
- sql << index.name if index.name
29
- sql << "ON"
30
- sql << index.table_name
31
- sql << "USING #{obj.type.to_s.capitalize}" if index.type
32
- sql << "(#{index.columns.map(&:to_s).join ',' })"
33
- sql << "COMMENT #{index.comment.truncate 1024}" if index.comment
34
- sql << "ALGORITHM #{index.algorithm.to_s.upcase}" if !index.lock && ALGORITHMS.include? index.algorithm
35
- sql << "LOCK #{index.lock.to_s.upcase}" if !index.algorithm && LOCKS.include? index.lock
36
- sql*" "
37
- end
38
-
39
- # Leverage MySQL savepoints to make up for transactions' flaws
40
- start_transaction { <<-sql
41
- BEGIN;
42
- SAVEPOINT mystic_migration8889;
43
- DECLARE EXIT HANDLER FOR SQLWARNING ROLLBACK TO mystic_migration8889;
44
- DECLARE EXIT HANDLER FOR NOT FOUND ROLLBACK TO mystic_migration8889;
45
- DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK TO mystic_migration8889;
46
- sql
47
- }
48
- commit_transaction { "RELEASE SAVEPOINT mystic_migration8889;COMMIT" }
49
- rollback_transaction { "ROLLBACK TO mystic_migration8889; RELEASE SAVEPOINT mystic_migration8889; ROLLBACK" }
50
- end
51
- end
@@ -1,95 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "mystic/adapters/abstract"
4
- require "pg"
5
-
6
- # Mystic adapter for Postgres, includes PostGIS
7
-
8
- module Mystic
9
- class PostgresAdapter < Mystic::Adapter
10
- INDEX_TYPES = [
11
- :btree,
12
- :hash,
13
- :gist,
14
- :spgist,
15
- :gin
16
- ].freeze
17
-
18
- CONNECT_FIELDS = [
19
- :host,
20
- :hostaddr,
21
- :port,
22
- :dbname,
23
- :user,
24
- :password,
25
- :connect_timeout,
26
- :options,
27
- :tty,
28
- :sslmode,
29
- :krbsrvname,
30
- :gsslib
31
- ].freeze
32
-
33
- connect { |opts| PG.connect opts.subhash(*CONNECT_FIELDS) }
34
- disconnect { |pg| pg.close }
35
- validate { |pg| pg.status == CONNECTION_OK }
36
- sanitize { |pg, str| pg.escape_string str }
37
- json_supported { true }
38
-
39
- execute do |pg, sql|
40
- res = pg.exec sql
41
- v = res[0][Mystic::JSON_COL] if res.ntuples == 1 && res.nfields == 1
42
- v ||= res.ntuples.times.map { |i| res[i] } unless res.nil?
43
- v ||= []
44
- v
45
- end
46
-
47
- drop_index do |index|
48
- "DROP INDEX #{index.index_name}"
49
- end
50
-
51
- create_ext do |ext|
52
- "CREATE EXTENSION \"#{ext.name}\""
53
- end
54
-
55
- drop_ext do |ext|
56
- "DROP EXTENSION \"#{ext.name}\""
57
- end
58
-
59
- index do |index|
60
- storage_params = index.opts.subhash :fillfactor, :buffering, :fastupdate
61
-
62
- sql = []
63
- sql << "CREATE"
64
- sql << "UNIQUE" if index.unique
65
- sql << "INDEX"
66
- sql << "CONCURENTLY" if index.concurrently
67
- sql << index.name unless index.name.nil?
68
- sql << "ON #{index.table_name}"
69
- sql << "USING #{index.type}" if INDEX_TYPES.include? index.type
70
- sql << "(#{index.columns.map(&:to_s).join ',' })"
71
- sql << "WITH (#{storage_params.sqlize})" unless storage_params.empty?
72
- sql << "TABLESPACE #{index.tablespace}" unless index.tablespace.nil?
73
- sql << "WHERE #{index.where}" unless index.where.nil?
74
- sql*' '
75
- end
76
-
77
- table do |table|
78
- sql = []
79
-
80
- if table.create?
81
- tbl = []
82
- tbl << "CREATE TABLE #{table.name} (#{table.columns.map(&:to_sql)*","})"
83
- tbl << "INHERITS #{table.inherits}" if table.inherits
84
- tbl << "TABLESPACE #{table.tablespace}" if table.tablespace
85
- sql << tbl*' '
86
- else
87
- sql << "ALTER TABLE #{table.name} #{table.columns.map{ |c| "ADD COLUMN #{c.to_sql}" }*', ' }"
88
- end
89
-
90
- sql.push(*table.indeces.map(&:to_sql)) unless table.indeces.empty?
91
- sql.push(*table.operations.map(&:to_sql)) unless table.operations.empty?
92
- sql*'; '
93
- end
94
- end
95
- end
@@ -1,11 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- module Mystic
4
- MysticError = Class.new StandardError
5
- RootError = Class.new StandardError
6
- EnvironmentError = Class.new StandardError
7
- AdapterError = Class.new StandardError
8
- CLIError = Class.new StandardError
9
- MIG_REGEX = /(?<num>\d+)_(?<name>[a-z]+)\.rb$/i # matches migration files (ex '1_MigrationClassName.rb')
10
- JSON_COL = "mystic_return_json89788"
11
- end