do_postgres 0.2.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.
- 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:
|