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.
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