em-postgres 0.0.1 → 0.0.2

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/README CHANGED
@@ -1,9 +1,8 @@
1
1
  Async PostgreSQL driver for Ruby/EventMachine
2
- based off Aman Gupta's mysql driver
3
-
4
2
 
5
3
  Requires pg
6
4
 
5
+ To run the specs, you will need rspec, run "rspec spec/postgres_spec.rb"
7
6
 
8
7
 
9
8
  TODOS:
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -83,7 +83,7 @@ module EventMachine
83
83
 
84
84
  def notify_readable
85
85
  if item = @current
86
- sql, cblk, eblk, retries = item
86
+ sql,params, cblk, eblk, retries = item
87
87
  #results = []
88
88
  #result = nil
89
89
  #@postgres.get_result{|r| result = r}
@@ -100,7 +100,6 @@ module EventMachine
100
100
  end
101
101
  #puts "\n\nQuery result:\n%p\n" % [ result.values ]
102
102
  end
103
-
104
103
  unless @postgres.error_message == ""
105
104
  #TODO this is wrong
106
105
  eb = (eblk || @opts[:on_error])
@@ -130,7 +129,7 @@ module EventMachine
130
129
  next_query
131
130
 
132
131
  elsif DisconnectErrors.include? e.message
133
- @queue << [sql, cblk, eblk, retries + 1]
132
+ @queue << [sql,params, cblk, eblk, retries + 1]
134
133
  return #close
135
134
 
136
135
  elsif cb = (eblk || @opts[:on_error])
@@ -158,7 +157,6 @@ module EventMachine
158
157
  end
159
158
 
160
159
  def reconnect
161
- puts "DDDDD"
162
160
  @processing = false
163
161
  @postgres = @conn.connect_socket(@opts)
164
162
  @fd = @postgres.socket
@@ -173,35 +171,41 @@ module EventMachine
173
171
  EM.add_timer(1) { reconnect }
174
172
  end
175
173
 
176
-
177
- def execute(sql, cblk = nil, eblk = nil, retries = 0)
178
-
174
+ def execute(sql,params=nil, cblk = nil, eblk = nil, retries = 0)
179
175
  begin
180
176
  if not @processing or not @connected
181
177
  #if !@processing || !@connected
182
178
  @processing = true
183
-
184
- @postgres.send_query(sql)
179
+
180
+ if sql =~ /\s+/
181
+ @postgres.send_query(sql,params)
182
+ else
183
+ @postgres.send_query_prepared(sql,params)
184
+ end
185
185
  else
186
- @queue << [sql, cblk, eblk, retries]
186
+ @queue << [sql,params, cblk, eblk, retries]
187
187
  return
188
188
  end
189
189
 
190
190
  rescue Exception => e
191
191
  puts "error in execute #{e}"
192
192
  if DisconnectErrors.include? e.message
193
- @queue << [sql, cblk, eblk, retries]
193
+ @queue << [sql,params, cblk, eblk, retries]
194
194
  return #close
195
195
  else
196
196
  raise e
197
197
  end
198
198
  end
199
- @current = [sql, cblk, eblk, retries]
199
+ @current = [sql,params, cblk, eblk, retries]
200
200
  end
201
201
 
202
202
  # act like the pg driver
203
203
  def method_missing(method, *args, &blk)
204
- @postgres.send(method, *args, &blk) if @postres.respond_to? method
204
+ if @postgres.respond_to? method
205
+ @postgres.send(method, *args, &blk)
206
+ else
207
+ super
208
+ end
205
209
  end
206
210
 
207
211
  def close
@@ -215,8 +219,8 @@ module EventMachine
215
219
 
216
220
  def next_query
217
221
  if @connected and !@processing and pending = @queue.shift
218
- sql, cblk, eblk = pending
219
- execute(sql, cblk, eblk)
222
+ sql, params, cblk, eblk = pending
223
+ execute(sql, params, cblk, eblk)
220
224
  end
221
225
  end
222
226
 
@@ -56,13 +56,12 @@ module EventMachine
56
56
  @connection.close
57
57
  end
58
58
 
59
- def query(sql, &blk)
59
+ def query(sql,params=[], &blk)
60
60
  df = EventMachine::DefaultDeferrable.new
61
61
  cb = blk || Proc.new { |r| df.succeed(r) }
62
62
  eb = Proc.new { |r| df.fail(r) }
63
-
64
- @connection.execute(sql, cb, eb)
65
-
63
+
64
+ @connection.execute(sql,params,cb,eb)
66
65
  df
67
66
  end
68
67
  alias :real_query :query
@@ -0,0 +1,184 @@
1
+ # async sequel extensions, for use with em-mysql
2
+ #
3
+ # require 'em/mysql'
4
+ # DB = Sequel.connect(:adapter => 'mysql', :user => 'root', :database => 'test', ...)
5
+ # EventedMysql.settings.update(..., :on_error => proc{|e| log 'error', e })
6
+ #
7
+ # def log *args
8
+ # p [Time.now, *args]
9
+ # end
10
+ #
11
+ # DB[:table].where(:id < 100).async_update(:field => 'new value') do |num_updated|
12
+ # log "done updating #{num_updated} rows"
13
+ # end
14
+ #
15
+ # DB[:table].async_insert(:field => 'value') do |insert_id|
16
+ # log "inserted row #{insert_id}"
17
+ # end
18
+ #
19
+ # DB[:table].async_multi_insert([:field], [ ['one'], ['two'], ['three'] ]) do
20
+ # log "done inserting 3 rows"
21
+ # end
22
+ #
23
+ # DB[:table].limit(10).async_each do |row|
24
+ # log "got a row", row
25
+ # end; log "this will be printed before the query returns"
26
+ #
27
+ # DB[:table].async_all do |rows|
28
+ # DB[:table].async_multi_insert([:field], rows.map{|r| "new_#{r[:field]}" })
29
+ # end
30
+ #
31
+ # DB[:table].async_all do |rows|
32
+ # num = rows.size
33
+ #
34
+ # rows.each{ |r|
35
+ # DB[:table].where(:id => r[:id]).async_update(:field => rand(10000).to_s) do
36
+ # num = num-1
37
+ # if num == 0
38
+ # log "last update completed"
39
+ # end
40
+ # end
41
+ # }
42
+ # end
43
+ #
44
+ # DB[:table].async_count do |num_rows|
45
+ # log "table has #{num_rows} rows"
46
+ # end
47
+
48
+ require 'sequel'
49
+ raise 'need Sequel >= 3.2.0' unless Sequel::MAJOR == 3 and Sequel::MINOR >= 2
50
+
51
+ module Sequel
52
+ class Dataset
53
+ def async_insert *args, &cb
54
+ EventedMysql.insert insert_sql(*args), &cb
55
+ nil
56
+ end
57
+
58
+ def async_insert_ignore *args, &cb
59
+ EventedMysql.insert insert_ignore.insert_sql(*args), &cb
60
+ nil
61
+ end
62
+
63
+ def async_update *args, &cb
64
+ EventedMysql.update update_sql(*args), &cb
65
+ nil
66
+ end
67
+
68
+ def async_delete &cb
69
+ EventedMysql.execute delete_sql, &cb
70
+ nil
71
+ end
72
+
73
+ def async_multi_insert *args, &cb
74
+ EventedMysql.execute multi_insert_sql(*args).first, &cb
75
+ nil
76
+ end
77
+
78
+ def async_multi_insert_ignore *args, &cb
79
+ EventedMysql.execute insert_ignore.multi_insert_sql(*args).first, &cb
80
+ nil
81
+ end
82
+
83
+ def async_fetch_rows sql, iter = :each
84
+ EventedMysql.raw(sql) do |m|
85
+ r = m.result
86
+
87
+ i = -1
88
+ cols = r.fetch_fields.map{|f| [output_identifier(f.name), Sequel::MySQL::MYSQL_TYPES[f.type], i+=1]}
89
+ @columns = cols.map{|c| c.first}
90
+ rows = []
91
+ while row = r.fetch_row
92
+ h = {}
93
+ cols.each{|n, p, i| v = row[i]; h[n] = (v && p) ? p.call(v) : v}
94
+ if iter == :each
95
+ yield h
96
+ else
97
+ rows << h
98
+ end
99
+ end
100
+ yield rows if iter == :all
101
+ end
102
+ nil
103
+ end
104
+
105
+ def async_each
106
+ async_fetch_rows(select_sql, :each) do |r|
107
+ if row_proc = @row_proc
108
+ yield row_proc.call(r)
109
+ else
110
+ yield r
111
+ end
112
+ end
113
+ nil
114
+ end
115
+
116
+ def async_all
117
+ async_fetch_rows(sql, :all) do |rows|
118
+ if row_proc = @row_proc
119
+ yield(rows.map{|r| row_proc.call(r) })
120
+ else
121
+ yield(rows)
122
+ end
123
+ end
124
+ nil
125
+ end
126
+
127
+ def async_count &cb
128
+ if options_overlap(COUNT_FROM_SELF_OPTS)
129
+ from_self.async_count(&cb)
130
+ else
131
+ clone(STOCK_COUNT_OPTS).async_each{|r|
132
+ yield r.is_a?(Hash) ? r.values.first.to_i : r.values.values.first.to_i
133
+ }
134
+ end
135
+ nil
136
+ end
137
+ end
138
+
139
+ class Model
140
+ def async_update *args, &cb
141
+ this.async_update(*args, &cb)
142
+ set(*args)
143
+ self
144
+ end
145
+
146
+ def async_delete &cb
147
+ this.async_delete(&cb)
148
+ nil
149
+ end
150
+
151
+ class << self
152
+ [ :async_insert,
153
+ :async_insert_ignore,
154
+ :async_multi_insert,
155
+ :async_multi_insert_ignore,
156
+ :async_each,
157
+ :async_all,
158
+ :async_update,
159
+ :async_count ].each do |method|
160
+ class_eval %[
161
+ def #{method} *args, &cb
162
+ dataset.#{method}(*args, &cb)
163
+ end
164
+ ]
165
+ end
166
+
167
+ # async version of Model#[]
168
+ def async_lookup args
169
+ unless Hash === args
170
+ args = primary_key_hash(args)
171
+ end
172
+
173
+ dataset.where(args).limit(1).async_all{ |rows|
174
+ if rows.any?
175
+ yield rows.first
176
+ else
177
+ yield nil
178
+ end
179
+ }
180
+ nil
181
+ end
182
+ end
183
+ end
184
+ end
@@ -3,4 +3,4 @@ require "rubygems"
3
3
  require "eventmachine"
4
4
  require "rspec"
5
5
  require "em-postgres"
6
- require "ruby-debug"
6
+ #require "ruby-debug"
@@ -1,6 +1,5 @@
1
1
  $LOAD_PATH << File.join(File.dirname(__FILE__))
2
2
  require "helper"
3
- require "ruby-debug"
4
3
  describe EventMachine::Postgres do
5
4
 
6
5
  it "should be true" do
@@ -54,7 +53,17 @@ describe EventMachine::Postgres do
54
53
  }
55
54
  end
56
55
 
57
-
56
+ it "should accept paramaters" do
57
+ EventMachine.run {
58
+ conn = EventMachine::Postgres.new(:database => 'test')
59
+ conn.execute("select $1::int AS first,$2::int AS second,$3::varchar AS third;",[1,nil,'']) { |res|
60
+ res.first["first"].should == "1"
61
+ res.first["second"].should == nil
62
+ res.first["third"].should == ""
63
+ EventMachine.stop
64
+ }
65
+ }
66
+ end
58
67
 
59
68
  it "allow custom error callbacks for each query" do
60
69
  EventMachine.run {
@@ -75,11 +84,9 @@ describe EventMachine::Postgres do
75
84
  conn = EventMachine::Postgres.new(:database => 'test')
76
85
 
77
86
  results = []
78
- #debugger
79
87
  conn.execute("select 1 AS x;") {|res| puts res.inspect; results.push(res.first["x"].to_i)}
80
88
  conn.execute("select 2 AS x;") {|res| puts res.inspect;results.push(res.first["x"].to_i)}
81
89
  conn.execute("select 3 AS x;") {|res| puts res.inspect;results.push(res.first["x"].to_i)}
82
- #debugger
83
90
  EventMachine.add_timer(0.05) {
84
91
  results.should == [1,2,3]
85
92
  #conn.connection_pool.first.close
@@ -124,6 +131,35 @@ describe EventMachine::Postgres do
124
131
  }
125
132
  end
126
133
 
134
+ it "should work with bind parameters" do
135
+ EventMachine.run {
136
+ conn = EventMachine::Postgres.new(:database=> 'test')
137
+ conn.execute("select $1::int as bind1;",[4]){|r|
138
+ r.first["bind1"].to_i.should == 4
139
+ }
140
+ conn.execute("select $1::text as bind1;",['four']){|r|
141
+ r.first["bind1"].should == 'four'
142
+ EventMachine.stop
143
+ }
144
+
145
+ }
146
+ end
147
+
148
+ it "should allow the creation of a prepare statement" do
149
+ EventMachine.run {
150
+ conn = EventMachine::Postgres.new(:database=> 'test')
151
+ prepare_name = "random#{rand(69)}"
152
+ i = rand(69)
153
+ conn.prepare(prepare_name,"select #{i};")
154
+ conn.execute(prepare_name){|r|
155
+ r.first["?column?"].to_i.should == i
156
+ EventMachine.stop
157
+ }
158
+ }
159
+ end
160
+
161
+
162
+
127
163
  =begin
128
164
  it "should work with synchronous commands" do
129
165
  EventMachine.run {
data/test.rb ADDED
@@ -0,0 +1,59 @@
1
+ require 'lib/em/postgres'
2
+
3
+ # EM.kqueue
4
+ # EM.epoll
5
+ EM.run{
6
+ EM.start_server '127.0.0.1', 12345 do |c|
7
+ def c.receive_data data
8
+ p 'sending http response'
9
+ send_data "hello"
10
+ close_connection_after_writing
11
+ end
12
+ end
13
+
14
+ SQL = EventedPostgres
15
+ def SQL(query, &blk) SQL.select(query, &blk) end
16
+
17
+ if true
18
+
19
+ SQL.settings.update :logging => true,
20
+ :database => 'test',
21
+ :connections => 1
22
+
23
+ SQL.execute('select 1+2')
24
+
25
+ EM.add_timer(1){
26
+ 3.times do SQL.select('select sleep(0.5)+1'){|r| p(r) } end
27
+ }
28
+
29
+ elsif false
30
+
31
+ SQL.settings.update :logging => true,
32
+ :database => 'test',
33
+ :connections => 10
34
+
35
+ EM.add_timer(2.5){ SQL.all('use test') }
36
+
37
+ else
38
+
39
+ SQL.settings.update :logging => true,
40
+ :database => 'test',
41
+ :connections => 10,
42
+ :timeout => 1
43
+
44
+ n = 0
45
+
46
+ SQL.execute('drop table if exists testingabc'){
47
+ SQL.execute('create table testingabc (a int, b int, c int)'){
48
+ EM.add_periodic_timer(0.2) do
49
+ cur_num = n+=1
50
+ SQL.execute("insert into testingabc values (1,2,#{cur_num})"){
51
+ SQL("select * from testingabc where c = #{cur_num} limit 1"){ |res| puts;puts }
52
+ }
53
+ end
54
+ }
55
+ }
56
+
57
+ end
58
+
59
+ }
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-postgres
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 1
9
- version: 0.0.1
4
+ prerelease:
5
+ version: 0.0.2
10
6
  platform: ruby
11
7
  authors:
12
8
  - Jason Toy
@@ -14,8 +10,7 @@ autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
12
 
17
- date: 2011-08-25 00:00:00 -07:00
18
- default_executable:
13
+ date: 2012-01-20 00:00:00 Z
19
14
  dependencies:
20
15
  - !ruby/object:Gem::Dependency
21
16
  name: eventmachine
@@ -25,31 +20,29 @@ dependencies:
25
20
  requirements:
26
21
  - - ">="
27
22
  - !ruby/object:Gem::Version
28
- segments:
29
- - 0
30
- - 12
31
- - 9
32
23
  version: 0.12.9
33
24
  type: :runtime
34
25
  version_requirements: *id001
35
- description: Async PostgreSQL client API for Ruby/EventMachine
26
+ description: Async PostgreSQL driver for Ruby/Eventmachine
36
27
  email: jtoy@jtoy.net
37
28
  executables: []
38
29
 
39
30
  extensions: []
40
31
 
41
- extra_rdoc_files: []
42
-
32
+ extra_rdoc_files:
33
+ - README
43
34
  files:
44
35
  - README
45
36
  - Rakefile
37
+ - VERSION
46
38
  - em-postgres.gemspec
47
- - lib/em-postgres/postgres.rb
48
- - lib/em-postgres/connection.rb
49
39
  - lib/em-postgres.rb
40
+ - lib/em-postgres/connection.rb
41
+ - lib/em-postgres/postgres.rb
42
+ - lib/sequel/async.rb
50
43
  - spec/helper.rb
51
44
  - spec/postgres_spec.rb
52
- has_rdoc: true
45
+ - test.rb
53
46
  homepage: http://github.com/jtoy/em-postgres
54
47
  licenses: []
55
48
 
@@ -63,23 +56,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
63
56
  requirements:
64
57
  - - ">="
65
58
  - !ruby/object:Gem::Version
66
- segments:
67
- - 0
68
59
  version: "0"
69
60
  required_rubygems_version: !ruby/object:Gem::Requirement
70
61
  none: false
71
62
  requirements:
72
63
  - - ">="
73
64
  - !ruby/object:Gem::Version
74
- segments:
75
- - 0
76
65
  version: "0"
77
66
  requirements: []
78
67
 
79
- rubyforge_project:
80
- rubygems_version: 1.3.7
68
+ rubyforge_project: em-postgres
69
+ rubygems_version: 1.8.11
81
70
  signing_key:
82
71
  specification_version: 3
83
- summary: Async PostgreSQL client API for Ruby/EventMachine
72
+ summary: Async PostgreSQL driver for Ruby/Eventmachine
84
73
  test_files: []
85
74