do_postgres 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README +4 -0
- data/Rakefile +51 -0
- data/TODO +5 -0
- data/ext/extconf.rb +29 -0
- data/ext/postgres_c.c +8185 -0
- data/ext/postgres_c.i +73 -0
- data/lib/do_postgres.rb +196 -0
- metadata +63 -0
data/ext/postgres_c.i
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
%module postgres_c
|
2
|
+
%{
|
3
|
+
#include "libpq-fe.h"
|
4
|
+
%}
|
5
|
+
|
6
|
+
%include "/opt/local/include/postgresql82/libpq-fe.h"
|
7
|
+
%include "/opt/local/include/postgresql82/postgres_ext.h"
|
8
|
+
|
9
|
+
#define BOOLOID 16
|
10
|
+
#define BYTEAOID 17
|
11
|
+
#define CHAROID 18
|
12
|
+
#define NAMEOID 19
|
13
|
+
#define INT8OID 20
|
14
|
+
#define INT2OID 21
|
15
|
+
#define INT2VECTOROID 22
|
16
|
+
#define INT4OID 23
|
17
|
+
#define REGPROCOID 24
|
18
|
+
#define TEXTOID 25
|
19
|
+
#define OIDOID 26
|
20
|
+
#define TIDOID 27
|
21
|
+
#define XIDOID 28
|
22
|
+
#define CIDOID 29
|
23
|
+
#define OIDVECTOROID 30
|
24
|
+
#define PG_TYPE_RELTYPE_OID 71
|
25
|
+
#define PG_ATTRIBUTE_RELTYPE_OID 75
|
26
|
+
#define PG_PROC_RELTYPE_OID 81
|
27
|
+
#define PG_CLASS_RELTYPE_OID 83
|
28
|
+
#define POINTOID 600
|
29
|
+
#define LSEGOID 601
|
30
|
+
#define PATHOID 602
|
31
|
+
#define BOXOID 603
|
32
|
+
#define POLYGONOID 604
|
33
|
+
#define LINEOID 628
|
34
|
+
#define FLOAT4OID 700
|
35
|
+
#define FLOAT8OID 701
|
36
|
+
#define ABSTIMEOID 702
|
37
|
+
#define RELTIMEOID 703
|
38
|
+
#define TINTERVALOID 704
|
39
|
+
#define UNKNOWNOID 705
|
40
|
+
#define CIRCLEOID 718
|
41
|
+
#define CASHOID 790
|
42
|
+
#define MACADDROID 829
|
43
|
+
#define INETOID 869
|
44
|
+
#define CIDROID 650
|
45
|
+
#define INT4ARRAYOID 1007
|
46
|
+
#define ACLITEMOID 1033
|
47
|
+
#define BPCHAROID 1042
|
48
|
+
#define VARCHAROID 1043
|
49
|
+
#define DATEOID 1082
|
50
|
+
#define TIMEOID 1083
|
51
|
+
#define TIMESTAMPOID 1114
|
52
|
+
#define TIMESTAMPTZOID 1184
|
53
|
+
#define INTERVALOID 1186
|
54
|
+
#define TIMETZOID 1266
|
55
|
+
#define BITOID 1560
|
56
|
+
#define VARBITOID 1562
|
57
|
+
#define NUMERICOID 1700
|
58
|
+
#define REFCURSOROID 1790
|
59
|
+
#define REGPROCEDUREOID 2202
|
60
|
+
#define REGOPEROID 2203
|
61
|
+
#define REGOPERATOROID 2204
|
62
|
+
#define REGCLASSOID 2205
|
63
|
+
#define REGTYPEOID 2206
|
64
|
+
#define RECORDOID 2249
|
65
|
+
#define CSTRINGOID 2275
|
66
|
+
#define ANYOID 2276
|
67
|
+
#define ANYARRAYOID 2277
|
68
|
+
#define VOIDOID 2278
|
69
|
+
#define TRIGGEROID 2279
|
70
|
+
#define LANGUAGE_HANDLEROID 2280
|
71
|
+
#define INTERNALOID 2281
|
72
|
+
#define OPAQUEOID 2282
|
73
|
+
#define ANYELEMENTOID 2283
|
data/lib/do_postgres.rb
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'postgres_c'
|
2
|
+
require 'data_objects'
|
3
|
+
|
4
|
+
module DataObject
|
5
|
+
module Postgres
|
6
|
+
TYPES = Hash[*Postgres_c.constants.select {|x| x.include?("OID")}.map {|x| [Postgres_c.const_get(x), x.gsub(/_?OID$/, "")]}.flatten]
|
7
|
+
QUOTE_STRING = "'"
|
8
|
+
QUOTE_COLUMN = "\""
|
9
|
+
|
10
|
+
class Connection < DataObject::Connection
|
11
|
+
attr_reader :db
|
12
|
+
|
13
|
+
def initialize(connection_string)
|
14
|
+
@state = STATE_CLOSED
|
15
|
+
@connection_string = connection_string
|
16
|
+
end
|
17
|
+
|
18
|
+
def open
|
19
|
+
@db = Postgres_c.PQconnectdb(@connection_string)
|
20
|
+
if Postgres_c.PQstatus(@db) != Postgres_c::CONNECTION_OK
|
21
|
+
raise ConnectionFailed, "The connection with connection string #{@connection_string} failed\n#{Postgres_c.PQerrorMessage(@db)}"
|
22
|
+
end
|
23
|
+
@state = STATE_OPEN
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
def close
|
28
|
+
Postgres_c.PQfinish(@db)
|
29
|
+
@state = STATE_CLOSED
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_command(text)
|
34
|
+
Command.new(self, text)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
class Reader < DataObject::Reader
|
40
|
+
|
41
|
+
def initialize(db, reader)
|
42
|
+
@reader = reader
|
43
|
+
case Postgres_c.PQresultStatus(reader)
|
44
|
+
when Postgres_c::PGRES_COMMAND_OK
|
45
|
+
@records_affected = Postgres_c.PQcmdTuples(reader).to_i
|
46
|
+
close
|
47
|
+
when Postgres_c::PGRES_TUPLES_OK
|
48
|
+
@fields, @field_types = [], []
|
49
|
+
@field_count = Postgres_c.PQnfields(@reader)
|
50
|
+
i = 0
|
51
|
+
while(i < @field_count)
|
52
|
+
@field_types.push(Postgres_c.PQftype(@reader, i))
|
53
|
+
@fields.push(Postgres_c.PQfname(@reader, i))
|
54
|
+
i += 1
|
55
|
+
end
|
56
|
+
@rows = Postgres_c.PQntuples(@reader)
|
57
|
+
@has_rows = @rows > 0
|
58
|
+
@cursor = 0
|
59
|
+
@state = STATE_OPEN
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def real_close
|
64
|
+
Postgres_c.PQclear(@reader)
|
65
|
+
end
|
66
|
+
|
67
|
+
def data_type_name(col)
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
def name(col)
|
72
|
+
super
|
73
|
+
Postgres_c.PQfname(@reader, col)
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_index(name)
|
77
|
+
super
|
78
|
+
@fields.index(name)
|
79
|
+
end
|
80
|
+
|
81
|
+
def null?(idx)
|
82
|
+
super
|
83
|
+
Postgres_c.PQgetisnull(@reader, @cursor, idx) != 0
|
84
|
+
end
|
85
|
+
|
86
|
+
def item(idx)
|
87
|
+
super
|
88
|
+
val = Postgres_c.PQgetvalue(@reader, @cursor, idx)
|
89
|
+
typecast(val, @field_types[idx])
|
90
|
+
end
|
91
|
+
|
92
|
+
def each
|
93
|
+
return unless has_rows?
|
94
|
+
|
95
|
+
while(true) do
|
96
|
+
yield
|
97
|
+
break unless self.next
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def next
|
102
|
+
super
|
103
|
+
if @cursor >= @rows - 1
|
104
|
+
@cursor = nil
|
105
|
+
close
|
106
|
+
return nil
|
107
|
+
end
|
108
|
+
@cursor += 1
|
109
|
+
true
|
110
|
+
end
|
111
|
+
|
112
|
+
protected
|
113
|
+
def native_type(col)
|
114
|
+
TYPES[Postgres_c.PQftype(@reader, col)]
|
115
|
+
end
|
116
|
+
|
117
|
+
def typecast(val, field_type)
|
118
|
+
return nil if val.nil?
|
119
|
+
case TYPES[field_type]
|
120
|
+
when "BOOL"
|
121
|
+
val == "t"
|
122
|
+
when "INT2", "INT4", "OID", "TID", "XID", "CID", "INT8"
|
123
|
+
val.to_i
|
124
|
+
when "FLOAT4", "FLOAT8", "NUMERIC", "CASH"
|
125
|
+
val.to_f
|
126
|
+
when "TIMESTAMP", "TIMETZ", "TIMESTAMPTZ"
|
127
|
+
DateTime.parse(val) rescue nil
|
128
|
+
when "TIME"
|
129
|
+
DateTime.parse(val).to_time rescue nil
|
130
|
+
when "DATE"
|
131
|
+
Date.parse(val) rescue nil
|
132
|
+
else
|
133
|
+
val
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
class ResultData < DataObject::ResultData
|
140
|
+
|
141
|
+
def last_insert_row
|
142
|
+
@last_insert_row ||= begin
|
143
|
+
reader = @conn.create_command("select lastval()").execute_reader
|
144
|
+
reader.item(0).to_i
|
145
|
+
rescue QueryError
|
146
|
+
raise NoInsertError, "You tried to get the last inserted row without doing an insert\n#{Postgres_c.PQerrorMessage(@conn.db)}"
|
147
|
+
ensure
|
148
|
+
reader and reader.close
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
class Command < DataObject::Command
|
155
|
+
|
156
|
+
def execute_reader(*args)
|
157
|
+
super
|
158
|
+
sql = escape_sql(args)
|
159
|
+
@connection.logger.debug { sql }
|
160
|
+
ptr = Postgres_c.PQexec(@connection.db, sql)
|
161
|
+
unless [Postgres_c::PGRES_COMMAND_OK, Postgres_c::PGRES_TUPLES_OK].include?(Postgres_c.PQresultStatus(ptr))
|
162
|
+
raise QueryError, "Your query failed.\n#{Postgres_c.PQerrorMessage(@connection.db)}QUERY: \"#{sql}\""
|
163
|
+
else
|
164
|
+
reader = Reader.new(@connection.db, ptr)
|
165
|
+
if block_given?
|
166
|
+
return_value = yield(reader)
|
167
|
+
reader.close
|
168
|
+
return_value
|
169
|
+
else
|
170
|
+
reader
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def execute_non_query(*args)
|
176
|
+
super
|
177
|
+
sql = escape_sql(args)
|
178
|
+
@connection.logger.debug { sql }
|
179
|
+
results = Postgres_c.PQexec(@connection.db, sql)
|
180
|
+
status = Postgres_c.PQresultStatus(results)
|
181
|
+
if status == Postgres_c::PGRES_TUPLES_OK
|
182
|
+
Postgres_c.PQclear(results)
|
183
|
+
raise QueryError, "Your query failed or you tried to execute a SELECT query through execute_non_reader\n#{Postgres_c.PQerrorMessage(@connection.db)}\nQUERY: \"#{sql}\""
|
184
|
+
elsif status != Postgres_c::PGRES_COMMAND_OK
|
185
|
+
Postgres_c.PQclear(results)
|
186
|
+
raise QueryError, "Your query failed.\n#{Postgres_c.PQerrorMessage(@connection.db)}\nQUERY: \"#{sql}\""
|
187
|
+
end
|
188
|
+
rows_affected = Postgres_c.PQcmdTuples(results).to_i
|
189
|
+
Postgres_c.PQclear(results)
|
190
|
+
ResultData.new(@connection, rows_affected)
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: do_postgres
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.2.0
|
7
|
+
date: 2007-11-11 00:00:00 -08:00
|
8
|
+
summary: A DataObject.rb driver for postgres
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: wycats@gmail.com
|
12
|
+
homepage: http://dataobjects.devjavu.com
|
13
|
+
rubyforge_project:
|
14
|
+
description: A DataObject.rb driver for postgres
|
15
|
+
autorequire: do_postgres
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Yehuda Katz
|
31
|
+
files:
|
32
|
+
- LICENSE
|
33
|
+
- README
|
34
|
+
- Rakefile
|
35
|
+
- TODO
|
36
|
+
- lib/do_postgres.rb
|
37
|
+
- ext/extconf.rb
|
38
|
+
- ext/postgres_c.c
|
39
|
+
- ext/postgres_c.i
|
40
|
+
test_files: []
|
41
|
+
|
42
|
+
rdoc_options: []
|
43
|
+
|
44
|
+
extra_rdoc_files:
|
45
|
+
- README
|
46
|
+
- LICENSE
|
47
|
+
- TODO
|
48
|
+
executables: []
|
49
|
+
|
50
|
+
extensions: []
|
51
|
+
|
52
|
+
requirements: []
|
53
|
+
|
54
|
+
dependencies:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: data_objects
|
57
|
+
version_requirement:
|
58
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.0.0
|
63
|
+
version:
|