sqlpostgres 1.2.4
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/Gemfile +8 -0
- data/Gemfile.lock +22 -0
- data/LICENSE.md +23 -0
- data/README.rdoc +59 -0
- data/Rakefile +32 -0
- data/VERSION +1 -0
- data/doc/BUGS +2 -0
- data/doc/examples/README +6 -0
- data/doc/examples/connection.rb +16 -0
- data/doc/examples/connection_auto.rb +22 -0
- data/doc/examples/connection_ctor.rb +18 -0
- data/doc/examples/connection_default.rb +15 -0
- data/doc/examples/connection_exec.rb +18 -0
- data/doc/examples/connection_manual.rb +12 -0
- data/doc/examples/connection_wrapped_new.rb +13 -0
- data/doc/examples/connection_wrapped_open.rb +13 -0
- data/doc/examples/cursor.rb +38 -0
- data/doc/examples/include_module.rb +9 -0
- data/doc/examples/include_module2.rb +12 -0
- data/doc/examples/insert.rb +30 -0
- data/doc/examples/insert2.rb +36 -0
- data/doc/examples/insert_bytea.rb +16 -0
- data/doc/examples/insert_bytea_array.rb +17 -0
- data/doc/examples/insert_default_values.rb +16 -0
- data/doc/examples/insert_insert.rb +16 -0
- data/doc/examples/insert_insert_default.rb +16 -0
- data/doc/examples/insert_insert_select.rb +20 -0
- data/doc/examples/insert_select.rb +20 -0
- data/doc/examples/interval.rb +17 -0
- data/doc/examples/savepoint.rb +38 -0
- data/doc/examples/select.rb +33 -0
- data/doc/examples/select2.rb +36 -0
- data/doc/examples/select_cross_join.rb +18 -0
- data/doc/examples/select_distinct.rb +18 -0
- data/doc/examples/select_distinct_on +19 -0
- data/doc/examples/select_for_update.rb +18 -0
- data/doc/examples/select_from.rb +17 -0
- data/doc/examples/select_from_subselect.rb +20 -0
- data/doc/examples/select_group_by.rb +19 -0
- data/doc/examples/select_having.rb +20 -0
- data/doc/examples/select_join_on.rb +18 -0
- data/doc/examples/select_join_using.rb +18 -0
- data/doc/examples/select_limit.rb +19 -0
- data/doc/examples/select_natural_join.rb +18 -0
- data/doc/examples/select_offset.rb +19 -0
- data/doc/examples/select_order_by.rb +20 -0
- data/doc/examples/select_select.rb +30 -0
- data/doc/examples/select_select_alias.rb +30 -0
- data/doc/examples/select_select_expression.rb +31 -0
- data/doc/examples/select_select_literal.rb +24 -0
- data/doc/examples/select_union.rb +21 -0
- data/doc/examples/select_where_array.rb +18 -0
- data/doc/examples/select_where_in.rb +18 -0
- data/doc/examples/select_where_string.rb +18 -0
- data/doc/examples/simple.rb +34 -0
- data/doc/examples/transaction.rb +30 -0
- data/doc/examples/transaction_abort.rb +30 -0
- data/doc/examples/transaction_commit.rb +34 -0
- data/doc/examples/translate_substitute_values.rb +17 -0
- data/doc/examples/update.rb +32 -0
- data/doc/examples/update2.rb +44 -0
- data/doc/examples/update_only.rb +17 -0
- data/doc/examples/update_set.rb +17 -0
- data/doc/examples/update_set_array.rb +16 -0
- data/doc/examples/update_set_bytea.rb +16 -0
- data/doc/examples/update_set_expression.rb +16 -0
- data/doc/examples/update_set_subselect.rb +20 -0
- data/doc/examples/update_where.rb +17 -0
- data/doc/examples/use_prefix.rb +8 -0
- data/doc/examples/use_prefix2.rb +11 -0
- data/doc/index.html +31 -0
- data/doc/insertexamples.rb +9 -0
- data/doc/makemanual +4 -0
- data/doc/makerdoc +5 -0
- data/doc/manual.dbk +622 -0
- data/lib/sqlpostgres/Connection.rb +198 -0
- data/lib/sqlpostgres/Cursor.rb +157 -0
- data/lib/sqlpostgres/Delete.rb +67 -0
- data/lib/sqlpostgres/Exceptions.rb +15 -0
- data/lib/sqlpostgres/Insert.rb +279 -0
- data/lib/sqlpostgres/NullConnection.rb +22 -0
- data/lib/sqlpostgres/PgBit.rb +73 -0
- data/lib/sqlpostgres/PgBox.rb +37 -0
- data/lib/sqlpostgres/PgCidr.rb +21 -0
- data/lib/sqlpostgres/PgCircle.rb +75 -0
- data/lib/sqlpostgres/PgInet.rb +21 -0
- data/lib/sqlpostgres/PgInterval.rb +208 -0
- data/lib/sqlpostgres/PgLineSegment.rb +37 -0
- data/lib/sqlpostgres/PgMacAddr.rb +21 -0
- data/lib/sqlpostgres/PgPath.rb +64 -0
- data/lib/sqlpostgres/PgPoint.rb +65 -0
- data/lib/sqlpostgres/PgPolygon.rb +56 -0
- data/lib/sqlpostgres/PgTime.rb +77 -0
- data/lib/sqlpostgres/PgTimeWithTimeZone.rb +98 -0
- data/lib/sqlpostgres/PgTimestamp.rb +93 -0
- data/lib/sqlpostgres/PgTwoPoints.rb +54 -0
- data/lib/sqlpostgres/PgType.rb +34 -0
- data/lib/sqlpostgres/PgWrapper.rb +41 -0
- data/lib/sqlpostgres/Savepoint.rb +98 -0
- data/lib/sqlpostgres/Select.rb +855 -0
- data/lib/sqlpostgres/Transaction.rb +120 -0
- data/lib/sqlpostgres/Translate.rb +436 -0
- data/lib/sqlpostgres/Update.rb +188 -0
- data/lib/sqlpostgres.rb +67 -0
- data/test/Assert.rb +72 -0
- data/test/Connection.test.rb +246 -0
- data/test/Cursor.test.rb +190 -0
- data/test/Delete.test.rb +68 -0
- data/test/Insert.test.rb +123 -0
- data/test/MockPGconn.rb +62 -0
- data/test/NullConnection.test.rb +32 -0
- data/test/PgBit.test.rb +98 -0
- data/test/PgBox.test.rb +108 -0
- data/test/PgCidr.test.rb +61 -0
- data/test/PgCircle.test.rb +107 -0
- data/test/PgInet.test.rb +61 -0
- data/test/PgInterval.test.rb +180 -0
- data/test/PgLineSegment.test.rb +108 -0
- data/test/PgMacAddr.test.rb +61 -0
- data/test/PgPath.test.rb +106 -0
- data/test/PgPoint.test.rb +100 -0
- data/test/PgPolygon.test.rb +95 -0
- data/test/PgTime.test.rb +120 -0
- data/test/PgTimeWithTimeZone.test.rb +117 -0
- data/test/PgTimestamp.test.rb +134 -0
- data/test/RandomThings.rb +25 -0
- data/test/Savepoint.test.rb +286 -0
- data/test/Select.test.rb +930 -0
- data/test/Test.rb +62 -0
- data/test/TestConfig.rb +21 -0
- data/test/TestSetup.rb +13 -0
- data/test/TestUtil.rb +92 -0
- data/test/Transaction.test.rb +275 -0
- data/test/Translate.test.rb +354 -0
- data/test/Update.test.rb +227 -0
- data/test/roundtrip.test.rb +565 -0
- data/test/test +34 -0
- data/tools/exampleinserter/ExampleInserter.rb +177 -0
- data/tools/rdoc/ChangeLog +796 -0
- data/tools/rdoc/EXAMPLE.rb +48 -0
- data/tools/rdoc/MANIFEST +58 -0
- data/tools/rdoc/Makefile +27 -0
- data/tools/rdoc/NEW_FEATURES +226 -0
- data/tools/rdoc/README +390 -0
- data/tools/rdoc/ToDo +6 -0
- data/tools/rdoc/contrib/Index +6 -0
- data/tools/rdoc/contrib/xslfo/ChangeLog +181 -0
- data/tools/rdoc/contrib/xslfo/README +106 -0
- data/tools/rdoc/contrib/xslfo/TODO +10 -0
- data/tools/rdoc/contrib/xslfo/convert.xsl +151 -0
- data/tools/rdoc/contrib/xslfo/demo/README +21 -0
- data/tools/rdoc/contrib/xslfo/demo/rdocfo +99 -0
- data/tools/rdoc/contrib/xslfo/fcm.xsl +54 -0
- data/tools/rdoc/contrib/xslfo/files.xsl +62 -0
- data/tools/rdoc/contrib/xslfo/labeled-lists.xsl +66 -0
- data/tools/rdoc/contrib/xslfo/lists.xsl +44 -0
- data/tools/rdoc/contrib/xslfo/modules.xsl +152 -0
- data/tools/rdoc/contrib/xslfo/rdoc.xsl +75 -0
- data/tools/rdoc/contrib/xslfo/source.xsl +66 -0
- data/tools/rdoc/contrib/xslfo/styles.xsl +69 -0
- data/tools/rdoc/contrib/xslfo/tables.xsl +67 -0
- data/tools/rdoc/contrib/xslfo/utils.xsl +21 -0
- data/tools/rdoc/debian/changelog +33 -0
- data/tools/rdoc/debian/compat +1 -0
- data/tools/rdoc/debian/control +20 -0
- data/tools/rdoc/debian/copyright +10 -0
- data/tools/rdoc/debian/dirs +2 -0
- data/tools/rdoc/debian/docs +2 -0
- data/tools/rdoc/debian/rdoc.1 +252 -0
- data/tools/rdoc/debian/rdoc.manpages +1 -0
- data/tools/rdoc/debian/rdoc.pod +149 -0
- data/tools/rdoc/debian/rules +9 -0
- data/tools/rdoc/dot/dot.rb +255 -0
- data/tools/rdoc/etc/rdoc.dtd +203 -0
- data/tools/rdoc/install.rb +137 -0
- data/tools/rdoc/markup/install.rb +43 -0
- data/tools/rdoc/markup/sample/sample.rb +42 -0
- data/tools/rdoc/markup/simple_markup/fragments.rb +323 -0
- data/tools/rdoc/markup/simple_markup/inline.rb +348 -0
- data/tools/rdoc/markup/simple_markup/lines.rb +147 -0
- data/tools/rdoc/markup/simple_markup/preprocess.rb +68 -0
- data/tools/rdoc/markup/simple_markup/to_html.rb +281 -0
- data/tools/rdoc/markup/simple_markup.rb +474 -0
- data/tools/rdoc/markup/test/AllTests.rb +2 -0
- data/tools/rdoc/markup/test/TestInline.rb +151 -0
- data/tools/rdoc/markup/test/TestParse.rb +411 -0
- data/tools/rdoc/rdoc/code_objects.rb +536 -0
- data/tools/rdoc/rdoc/diagram.rb +331 -0
- data/tools/rdoc/rdoc/generators/chm_generator.rb +112 -0
- data/tools/rdoc/rdoc/generators/html_generator.rb +1268 -0
- data/tools/rdoc/rdoc/generators/template/chm/chm.rb +86 -0
- data/tools/rdoc/rdoc/generators/template/html/html.rb +705 -0
- data/tools/rdoc/rdoc/generators/template/html/kilmer.rb +377 -0
- data/tools/rdoc/rdoc/generators/template/xml/rdf.rb +110 -0
- data/tools/rdoc/rdoc/generators/template/xml/xml.rb +110 -0
- data/tools/rdoc/rdoc/generators/xml_generator.rb +130 -0
- data/tools/rdoc/rdoc/options.rb +451 -0
- data/tools/rdoc/rdoc/parsers/parse_c.rb +287 -0
- data/tools/rdoc/rdoc/parsers/parse_f95.rb +118 -0
- data/tools/rdoc/rdoc/parsers/parse_rb.rb +2311 -0
- data/tools/rdoc/rdoc/parsers/parse_simple.rb +37 -0
- data/tools/rdoc/rdoc/parsers/parserfactory.rb +75 -0
- data/tools/rdoc/rdoc/rdoc.rb +219 -0
- data/tools/rdoc/rdoc/template.rb +234 -0
- data/tools/rdoc/rdoc/tokenstream.rb +25 -0
- data/tools/rdoc/rdoc.rb +9 -0
- metadata +291 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
module SqlPostgres
|
|
2
|
+
|
|
3
|
+
# This class holds a connection to the database.
|
|
4
|
+
|
|
5
|
+
class Connection
|
|
6
|
+
|
|
7
|
+
require 'pg'
|
|
8
|
+
|
|
9
|
+
# If true, then PGError exceptions have the offending statement
|
|
10
|
+
# added to them.
|
|
11
|
+
|
|
12
|
+
attr_accessor 'statement_in_exception'
|
|
13
|
+
|
|
14
|
+
# The underlying instance of PGconn. This is for when PGconn does
|
|
15
|
+
# something that this library doesn't do.
|
|
16
|
+
|
|
17
|
+
attr_reader :pgconn
|
|
18
|
+
|
|
19
|
+
@@pgClass = PG
|
|
20
|
+
@@default = nil
|
|
21
|
+
|
|
22
|
+
# Get the default connection. If there isn't one, returns the
|
|
23
|
+
# NullConnection instead.
|
|
24
|
+
|
|
25
|
+
def Connection.default
|
|
26
|
+
if @@default.nil?
|
|
27
|
+
NullConnection.new
|
|
28
|
+
else
|
|
29
|
+
@@default
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Set the default connection.
|
|
34
|
+
|
|
35
|
+
def Connection.default=(value)
|
|
36
|
+
@@default = value
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Open a connection, pass it to the block, then close it.
|
|
40
|
+
# The connection is closed even if an exception occurs.
|
|
41
|
+
# Returns the result of the block.
|
|
42
|
+
#
|
|
43
|
+
# Takes the same arguments as new.
|
|
44
|
+
#
|
|
45
|
+
# Note: If an exception occurs, then any exception from closing
|
|
46
|
+
# the connection is ignored. This is to avoid masking the original
|
|
47
|
+
# (and presumably more important) exception.
|
|
48
|
+
|
|
49
|
+
def Connection.open(*args)
|
|
50
|
+
connection = Connection.new(*args)
|
|
51
|
+
begin
|
|
52
|
+
result = yield(connection)
|
|
53
|
+
rescue
|
|
54
|
+
begin
|
|
55
|
+
connection.close
|
|
56
|
+
rescue
|
|
57
|
+
end
|
|
58
|
+
raise
|
|
59
|
+
else
|
|
60
|
+
connection.close
|
|
61
|
+
end
|
|
62
|
+
result
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Create a connection.
|
|
66
|
+
#
|
|
67
|
+
# To create a new connection, pass zero or more of the following
|
|
68
|
+
# arguments They get passed through to PGconn.connect.
|
|
69
|
+
#
|
|
70
|
+
# 'host_name'::
|
|
71
|
+
# The host to connect to. Defaults to 'localhost'
|
|
72
|
+
# 'port'::
|
|
73
|
+
# The port to connect to. Defaults to 5432
|
|
74
|
+
# 'options'::
|
|
75
|
+
# Back end options. Defaults to ''
|
|
76
|
+
# 'tty'::
|
|
77
|
+
# Name of TTY for back end messages. Defaults to ''
|
|
78
|
+
# 'db_name'::
|
|
79
|
+
# Database name. '', the default, means to use the database
|
|
80
|
+
# with the same name as the user.
|
|
81
|
+
# 'login'::
|
|
82
|
+
# Login name. nil, the default, means to use the user's name.
|
|
83
|
+
# to nil.
|
|
84
|
+
# 'password'::
|
|
85
|
+
# Password. nil, the default, means no password.
|
|
86
|
+
#
|
|
87
|
+
# To wrap an existing connection, pass this argument:
|
|
88
|
+
#
|
|
89
|
+
# 'connection'::
|
|
90
|
+
# The PGConn instance to wrap.
|
|
91
|
+
#
|
|
92
|
+
# The following arguments influence SqlPostgres's behavior;
|
|
93
|
+
# they're not actually used to establish the connection to postgres:
|
|
94
|
+
#
|
|
95
|
+
# 'statement_in_exception'::
|
|
96
|
+
# If true, add the offending statement PGError exceptions. Defaults
|
|
97
|
+
# to true.
|
|
98
|
+
|
|
99
|
+
def initialize(args = {})
|
|
100
|
+
raise ArgumentError, "Block not allowed" if block_given?
|
|
101
|
+
@pgconn = args['connection']
|
|
102
|
+
if @pgconn.nil?
|
|
103
|
+
hostName = args['host_name'] || "localhost"
|
|
104
|
+
dbName = args['db_name'] || ""
|
|
105
|
+
port = args['port'] || 5432
|
|
106
|
+
options = args['options'] || ""
|
|
107
|
+
tty = args['tty'] || ""
|
|
108
|
+
login = args['login']
|
|
109
|
+
password = args['password']
|
|
110
|
+
@pgconn = @@pgClass.connect(hostName, port, options, tty, dbName,
|
|
111
|
+
login, password)
|
|
112
|
+
end
|
|
113
|
+
@statement_in_exception = args['statement_in_exception']
|
|
114
|
+
@statement_in_exception = true if @statement_in_exception.nil?
|
|
115
|
+
@pgconn.set_client_encoding("unicode")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# close the connection. If it's already closed, do nothing.
|
|
119
|
+
|
|
120
|
+
def close
|
|
121
|
+
return if @pgconn.nil?
|
|
122
|
+
@pgconn.close
|
|
123
|
+
@pgconn = nil
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Send an SQL statement to the backend. Returns a PGResult. This
|
|
127
|
+
# is just a thin wrapper around PGConn.exec, and exists for when
|
|
128
|
+
# you want to do some SQL that Insert, Update, Select, or
|
|
129
|
+
# Transaction won't do for you (ie, "create temporary table").
|
|
130
|
+
#
|
|
131
|
+
# If a PGError exception occurs and statement_in_exception is
|
|
132
|
+
# true, then statement is added to the exception.
|
|
133
|
+
|
|
134
|
+
def exec(statement)
|
|
135
|
+
begin
|
|
136
|
+
@pgconn.exec(statement)
|
|
137
|
+
rescue PGError => e
|
|
138
|
+
if statement_in_exception
|
|
139
|
+
e = e.exception(e.message +
|
|
140
|
+
"The offending statement is: #{statement.inspect}")
|
|
141
|
+
end
|
|
142
|
+
raise e
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Send an SQL statement to the backend. Returns an array of arrays.
|
|
147
|
+
#
|
|
148
|
+
# If a PGError exception occurs and statement_in_exception is
|
|
149
|
+
# true, then statement is added to the exception.
|
|
150
|
+
|
|
151
|
+
def query(statement)
|
|
152
|
+
result = exec(statement)
|
|
153
|
+
result.send(result_method(result))
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# This is a hook for rspec (mock this method to find out what sql
|
|
157
|
+
# is being executed, and to inject translated results).
|
|
158
|
+
|
|
159
|
+
def exec_and_translate(statement, columns)
|
|
160
|
+
translate_pgresult(exec(statement), columns)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
private
|
|
164
|
+
|
|
165
|
+
def result_method(result)
|
|
166
|
+
if result.respond_to?(:result)
|
|
167
|
+
:result
|
|
168
|
+
else
|
|
169
|
+
:values
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def translate_pgresult(pgresult, columns)
|
|
174
|
+
pgresult.values.collect do |row|
|
|
175
|
+
hash = {}
|
|
176
|
+
columns.each_with_index do |column, i|
|
|
177
|
+
unless column.converter.nil?
|
|
178
|
+
typeCode = pgresult.ftype(i)
|
|
179
|
+
value = row[i]
|
|
180
|
+
args = [value]
|
|
181
|
+
args << typeCode if column.converter.arity == 2
|
|
182
|
+
hash[column.as || column.value] =
|
|
183
|
+
value && column.converter.call(*args)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
hash
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Local Variables:
|
|
195
|
+
# tab-width: 2
|
|
196
|
+
# ruby-indent-level: 2
|
|
197
|
+
# indent-tabs-mode: nil
|
|
198
|
+
# End:
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
module SqlPostgres
|
|
2
|
+
|
|
3
|
+
# This class creates and manages a cursor.
|
|
4
|
+
#
|
|
5
|
+
# Example:
|
|
6
|
+
#** example: cursor
|
|
7
|
+
# Transaction.new(connection) do
|
|
8
|
+
# select = Select.new(connection)
|
|
9
|
+
# select.select('i')
|
|
10
|
+
# select.from('foo')
|
|
11
|
+
# Cursor.new('my_cursor', select, {}, connection) do |cursor|
|
|
12
|
+
# while !(rows = cursor.fetch).empty?
|
|
13
|
+
# for row in rows
|
|
14
|
+
# p row # {"i"=>0}
|
|
15
|
+
# # {"i"=>1}
|
|
16
|
+
# # {"i"=>2}
|
|
17
|
+
# # {"i"=>3}
|
|
18
|
+
# # {"i"=>4}
|
|
19
|
+
# end
|
|
20
|
+
# end
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
#**
|
|
24
|
+
#
|
|
25
|
+
# Fetching a single row at a time, the default for fetch, is slow.
|
|
26
|
+
# Usually you will want to speed things up by calling, for example,
|
|
27
|
+
# fetch(1000).
|
|
28
|
+
|
|
29
|
+
class Cursor
|
|
30
|
+
|
|
31
|
+
# Create a cursor. If a block is given, yield the cursor to the
|
|
32
|
+
# block, closing the cursor when the block returns, and returning
|
|
33
|
+
# results of the block.
|
|
34
|
+
#
|
|
35
|
+
# If no connection is given, then the default connection is used.
|
|
36
|
+
#
|
|
37
|
+
# [name]
|
|
38
|
+
# The cursor's name
|
|
39
|
+
# [select]
|
|
40
|
+
# a Select statement
|
|
41
|
+
# [opts]
|
|
42
|
+
# Options hash. Keys are:
|
|
43
|
+
# :scroll=>(boolean) If true, create a SCROLL cursor. If false,
|
|
44
|
+
# create a NO SCROLL cursor. If not specified,
|
|
45
|
+
# the default is to allow scrolling in cases
|
|
46
|
+
# where performance will not suffer.
|
|
47
|
+
# :hold=>(boolean) If true, create a WITH HOLD cursor. If
|
|
48
|
+
# false, create a HOLD cursor. WITHOUT HOLD
|
|
49
|
+
# is the default. A HOLD cursor can be used
|
|
50
|
+
# outside of the transaction that created it.
|
|
51
|
+
# [connection]
|
|
52
|
+
# The database connection
|
|
53
|
+
|
|
54
|
+
def initialize(name, select, opts = {}, connection = Connection.default)
|
|
55
|
+
if block_given?
|
|
56
|
+
cursor = self.class.new(name, select, opts, connection)
|
|
57
|
+
result = yield(cursor)
|
|
58
|
+
cursor.close
|
|
59
|
+
result
|
|
60
|
+
else
|
|
61
|
+
@name = name
|
|
62
|
+
@select = select
|
|
63
|
+
@opts = opts
|
|
64
|
+
@connection = connection
|
|
65
|
+
declare_cursor
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Fetch a row or rows from the cursor.
|
|
70
|
+
#
|
|
71
|
+
# [direction]
|
|
72
|
+
# A string specifying which row or rows to fetch. See the
|
|
73
|
+
# postgres documentation for the "DECLARE" statement.
|
|
74
|
+
# NEXT
|
|
75
|
+
# PRIOR
|
|
76
|
+
# FIRST
|
|
77
|
+
# LAST
|
|
78
|
+
# ABSOLUTE count
|
|
79
|
+
# RELATIVE count
|
|
80
|
+
# count
|
|
81
|
+
# ALL
|
|
82
|
+
# FORWARD
|
|
83
|
+
# FORWARD count
|
|
84
|
+
# FORWARD ALL
|
|
85
|
+
# BACKWARD
|
|
86
|
+
# BACKWARD count
|
|
87
|
+
# BACKWARD ALL
|
|
88
|
+
|
|
89
|
+
def fetch(direction = 'NEXT')
|
|
90
|
+
@select.fetch_by_cursor(@name, direction, @connection)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Seek a cursor. Works exactly the same (and takes the same
|
|
94
|
+
# arguments) as fetch, but returns no rows.
|
|
95
|
+
#
|
|
96
|
+
# [direction]
|
|
97
|
+
# See #fetch
|
|
98
|
+
|
|
99
|
+
def move(direction = 'NEXT')
|
|
100
|
+
statement = "move #{direction} from #{@name}"
|
|
101
|
+
@connection.exec(statement)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Close the cursor. Once closed, it may closed or fetched from
|
|
105
|
+
# again.
|
|
106
|
+
|
|
107
|
+
def close
|
|
108
|
+
statement = "close #{@name}"
|
|
109
|
+
@connection.exec(statement)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
private
|
|
113
|
+
|
|
114
|
+
def declare_cursor
|
|
115
|
+
statement = [
|
|
116
|
+
'declare',
|
|
117
|
+
@name,
|
|
118
|
+
scroll_declaration,
|
|
119
|
+
'cursor',
|
|
120
|
+
hold_declaration,
|
|
121
|
+
'for',
|
|
122
|
+
@select.statement
|
|
123
|
+
].compact.join(' ')
|
|
124
|
+
@connection.exec(statement)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def scroll_declaration
|
|
128
|
+
value = @opts.fetch(:scroll, :default)
|
|
129
|
+
if value == :default
|
|
130
|
+
nil
|
|
131
|
+
elsif value
|
|
132
|
+
"SCROLL"
|
|
133
|
+
else
|
|
134
|
+
"NO SCROLL"
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def hold_declaration
|
|
139
|
+
value = @opts.fetch(:hold, :default)
|
|
140
|
+
if value == :default
|
|
141
|
+
nil
|
|
142
|
+
elsif value
|
|
143
|
+
"WITH HOLD"
|
|
144
|
+
else
|
|
145
|
+
"WITHOUT HOLD"
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Local Variables:
|
|
154
|
+
# tab-width: 2
|
|
155
|
+
# ruby-indent-level: 2
|
|
156
|
+
# indent-tabs-mode: nil
|
|
157
|
+
# End:
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module SqlPostgres
|
|
2
|
+
|
|
3
|
+
# This class creates and executes an SQL delete statement.
|
|
4
|
+
|
|
5
|
+
class Delete
|
|
6
|
+
|
|
7
|
+
# Create a delete statement
|
|
8
|
+
#
|
|
9
|
+
# [table]
|
|
10
|
+
# The table name
|
|
11
|
+
# [connection]
|
|
12
|
+
# If supplied, the connection to use. If not supplied, use the
|
|
13
|
+
# default.
|
|
14
|
+
|
|
15
|
+
def initialize(table, connection = Connection.default)
|
|
16
|
+
@table = table
|
|
17
|
+
@connection = connection
|
|
18
|
+
@where = []
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Add a "where" condition to this statement.
|
|
22
|
+
#
|
|
23
|
+
# [expression]
|
|
24
|
+
# The condition. Should be one of:
|
|
25
|
+
# [A string] The expression
|
|
26
|
+
# [An array] An expression converted using #substitute_values
|
|
27
|
+
|
|
28
|
+
def where(expression)
|
|
29
|
+
@where << Translate.substitute_values(expression)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Return the SQL statement
|
|
33
|
+
|
|
34
|
+
def statement
|
|
35
|
+
"delete from #{@table}#{where_clause}"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Execute the delete statement
|
|
39
|
+
#
|
|
40
|
+
# [connection]
|
|
41
|
+
# If present, the connection to use.
|
|
42
|
+
# If nil, uses the connection passed to new, or if no connection was
|
|
43
|
+
# passed to new, uses the default connection.
|
|
44
|
+
|
|
45
|
+
def exec(connection = @connection)
|
|
46
|
+
connection.exec(statement)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def where_clause
|
|
52
|
+
if @where.empty?
|
|
53
|
+
""
|
|
54
|
+
else
|
|
55
|
+
" where " + @where.join(' and ')
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Local Variables:
|
|
64
|
+
# tab-width: 2
|
|
65
|
+
# ruby-indent-level: 2
|
|
66
|
+
# indent-tabs-mode: nil
|
|
67
|
+
# End:
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module SqlPostgres
|
|
2
|
+
|
|
3
|
+
# A function requiring a database connection was called, but the object
|
|
4
|
+
# didn't have a database connection.
|
|
5
|
+
|
|
6
|
+
class NoConnection < Exception
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Local Variables:
|
|
12
|
+
# tab-width: 2
|
|
13
|
+
# ruby-indent-level: 2
|
|
14
|
+
# indent-tabs-mode: nil
|
|
15
|
+
# End:
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
module SqlPostgres
|
|
2
|
+
|
|
3
|
+
# This class creates and executes an SQL insert statement.
|
|
4
|
+
#
|
|
5
|
+
# Example:
|
|
6
|
+
#** Example: insert
|
|
7
|
+
# insert = Insert.new('foo', connection)
|
|
8
|
+
# insert.insert('i', 1)
|
|
9
|
+
# insert.insert('t', 'foo')
|
|
10
|
+
# p insert.statement # "insert into foo (i, t) values (1,
|
|
11
|
+
# # E'foo')"
|
|
12
|
+
# insert.exec
|
|
13
|
+
#**
|
|
14
|
+
|
|
15
|
+
class Insert
|
|
16
|
+
|
|
17
|
+
# Create an insert statement
|
|
18
|
+
#
|
|
19
|
+
# [table]
|
|
20
|
+
# The table name
|
|
21
|
+
# [connection]
|
|
22
|
+
# If supplied, the connection to use. If not supplied, use the
|
|
23
|
+
# default.
|
|
24
|
+
|
|
25
|
+
def initialize(table, connection = Connection.default)
|
|
26
|
+
@table = table
|
|
27
|
+
@connection = connection
|
|
28
|
+
@columns = []
|
|
29
|
+
@values = []
|
|
30
|
+
@query = nil
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Add a column to the statement. This is for all column types
|
|
34
|
+
# *except* bytea.
|
|
35
|
+
#
|
|
36
|
+
# [column]
|
|
37
|
+
# The column name
|
|
38
|
+
# [value]
|
|
39
|
+
# The value to add. The value is SQL escaped.
|
|
40
|
+
# Should be one of:
|
|
41
|
+
# * a String
|
|
42
|
+
# * an Integer
|
|
43
|
+
# * a Float
|
|
44
|
+
# * a Time
|
|
45
|
+
# * false
|
|
46
|
+
# * true
|
|
47
|
+
# * nil
|
|
48
|
+
# * a Select
|
|
49
|
+
# * :default
|
|
50
|
+
# * :no_value
|
|
51
|
+
#
|
|
52
|
+
# Special values:
|
|
53
|
+
# [a Select]
|
|
54
|
+
# The select's SQL is added in parentheses
|
|
55
|
+
# [:default]
|
|
56
|
+
# Add the SQL keyword "default" to the statement.
|
|
57
|
+
# [:no_value]
|
|
58
|
+
# Do not add a value for this column. This is used when the
|
|
59
|
+
# values are being provided by a Select statement.
|
|
60
|
+
#
|
|
61
|
+
# Example (simple)
|
|
62
|
+
#** Example: insert_insert
|
|
63
|
+
# insert = Insert.new('foo')
|
|
64
|
+
# insert.insert('t', 'bar')
|
|
65
|
+
# p insert.statement # "insert into foo (t) values (E'bar')"
|
|
66
|
+
#**
|
|
67
|
+
#
|
|
68
|
+
# Example (select)
|
|
69
|
+
#** Example: insert_insert_select
|
|
70
|
+
# select = Select.new
|
|
71
|
+
# select.select('j')
|
|
72
|
+
# select.from('bar')
|
|
73
|
+
# select.limit(1)
|
|
74
|
+
# insert = Insert.new('foo')
|
|
75
|
+
# insert.insert('i', select)
|
|
76
|
+
# p insert.statement # "insert into foo (i) values ((select j
|
|
77
|
+
# # from bar limit 1))"
|
|
78
|
+
#**
|
|
79
|
+
#
|
|
80
|
+
# Example (default)
|
|
81
|
+
#** Example: insert_insert_default
|
|
82
|
+
# insert = Insert.new('foo')
|
|
83
|
+
# insert.insert('i', :default)
|
|
84
|
+
# p insert.statement # "insert into foo (i) values
|
|
85
|
+
# # (default)"
|
|
86
|
+
#**
|
|
87
|
+
|
|
88
|
+
def insert(column, value = :no_value)
|
|
89
|
+
@columns << column
|
|
90
|
+
@values << Translate.escape_sql(value) unless value == :no_value
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Insert into an array (int[], text[], etc) column. This is not
|
|
94
|
+
# for byte array (bytea) column types: For that, call
|
|
95
|
+
# #insert_bytea.
|
|
96
|
+
#
|
|
97
|
+
# [column]
|
|
98
|
+
# The column name
|
|
99
|
+
# [value]
|
|
100
|
+
# The value to add.
|
|
101
|
+
#
|
|
102
|
+
# This is used for inserting literals and expressions. To insert
|
|
103
|
+
# the result of an SQL query, or to insert the default value,
|
|
104
|
+
# call #insert.
|
|
105
|
+
|
|
106
|
+
def insert_array(column, value)
|
|
107
|
+
@columns << column
|
|
108
|
+
@values << Translate.escape_array(value)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Insert into a bytea column. You must use this function, not
|
|
112
|
+
# #insert, when inserting a string into a bytea column. That's
|
|
113
|
+
# because bytea columns need special escaping.
|
|
114
|
+
#
|
|
115
|
+
# [column]
|
|
116
|
+
# The column name
|
|
117
|
+
# [value]
|
|
118
|
+
# The value to add.
|
|
119
|
+
# Should be one of:
|
|
120
|
+
# * a String
|
|
121
|
+
# * :default
|
|
122
|
+
# * :no_value
|
|
123
|
+
#
|
|
124
|
+
# Special values:
|
|
125
|
+
# [a Select]
|
|
126
|
+
# The select's SQL is added in parentheses
|
|
127
|
+
# [:default]
|
|
128
|
+
# Add the SQL keyword "default" to the statement.
|
|
129
|
+
# [:no_value]
|
|
130
|
+
# Do not add a value for this column. This is used when the
|
|
131
|
+
# values are being provided by a Select statement.
|
|
132
|
+
#
|
|
133
|
+
# Example:
|
|
134
|
+
#** Example: insert_bytea
|
|
135
|
+
# insert = Insert.new('foo')
|
|
136
|
+
# insert.insert_bytea('t', "\000\001\002\003")
|
|
137
|
+
# p insert.statement # "insert into foo (t) values
|
|
138
|
+
# # (E'\\\\000\\\\001\\\\002\\\\003')"
|
|
139
|
+
#**
|
|
140
|
+
|
|
141
|
+
def insert_bytea(column, value = :no_value)
|
|
142
|
+
@columns << column
|
|
143
|
+
@values << Translate.escape_bytea(value) unless value == :no_value
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Insert into a bytea[] (bytea array) column. You must use this
|
|
147
|
+
# function, not #insert or #insert_array, because bytea[] columns
|
|
148
|
+
# need special escaping.
|
|
149
|
+
#
|
|
150
|
+
#** Example: insert_bytea_array
|
|
151
|
+
# insert = Insert.new('foo')
|
|
152
|
+
# insert.insert_bytea_array('t', ["foo", "\000bar\nbaz"])
|
|
153
|
+
# p insert.statement # "insert into foo (t) values
|
|
154
|
+
# # ('{\"foo\",\"\\\\\\\\000bar\nbaz\"}')"
|
|
155
|
+
#
|
|
156
|
+
#**
|
|
157
|
+
|
|
158
|
+
def insert_bytea_array(column, value = :no_value)
|
|
159
|
+
@columns << column
|
|
160
|
+
@values << Translate.escape_bytea_array(value) unless value == :no_value
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Insert into a "char" column. This is a Postgres specific data
|
|
164
|
+
# type that is different than char or character (yes, the quotes
|
|
165
|
+
# are part of the type name). "char" values are escaped
|
|
166
|
+
# differently than normal test, so be sure to use this method and
|
|
167
|
+
# not #insert when inserting into a "char" column.
|
|
168
|
+
#
|
|
169
|
+
# [column]
|
|
170
|
+
# The column name
|
|
171
|
+
# [value]
|
|
172
|
+
# A string of length 1
|
|
173
|
+
#
|
|
174
|
+
# Example:
|
|
175
|
+
#** Example: insert_qchar
|
|
176
|
+
#**
|
|
177
|
+
|
|
178
|
+
def insert_qchar(column, value = :no_value)
|
|
179
|
+
@columns << column
|
|
180
|
+
@values << Translate.escape_qchar(value)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Insert the results of a select statement
|
|
184
|
+
#
|
|
185
|
+
# Example:
|
|
186
|
+
#** Example: insert_select
|
|
187
|
+
# select = Select.new
|
|
188
|
+
# select.select('i')
|
|
189
|
+
# select.from('bar')
|
|
190
|
+
# insert = Insert.new('foo')
|
|
191
|
+
# insert.insert('i')
|
|
192
|
+
# insert.select(select)
|
|
193
|
+
# p insert.statement # "insert into foo (i) select i from bar"
|
|
194
|
+
#**
|
|
195
|
+
|
|
196
|
+
def select(select)
|
|
197
|
+
@query = select.statement
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Define return clause
|
|
201
|
+
#
|
|
202
|
+
# Example: (simple)
|
|
203
|
+
#** Example: insert_returning
|
|
204
|
+
# insert = Insert.new('foo')
|
|
205
|
+
# insert.insert('i', 3)
|
|
206
|
+
# insert.returning('i')
|
|
207
|
+
# p insert.statement # "insert into foo (i) values (3) returning i
|
|
208
|
+
#
|
|
209
|
+
# Example: (expression_with_alias)
|
|
210
|
+
#** Example: insert_returning_with_alias
|
|
211
|
+
# insert = Insert.new('foo')
|
|
212
|
+
# insert.insert('i', 3)
|
|
213
|
+
# insert.returning('i*3', 'calc')
|
|
214
|
+
# p insert.statement # "insert into foo (i) values (3) returning i*3 as calc
|
|
215
|
+
|
|
216
|
+
def returning(expression, name=nil)
|
|
217
|
+
str = "returning #{expression}"
|
|
218
|
+
str += " as #{name}" if name
|
|
219
|
+
@returning_expression = str
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# insert default values
|
|
223
|
+
#
|
|
224
|
+
# Example:
|
|
225
|
+
#** Example: insert_default_values
|
|
226
|
+
# insert = Insert.new('foo')
|
|
227
|
+
# insert.default_values
|
|
228
|
+
# p insert.statement # "insert into foo default values"
|
|
229
|
+
#**
|
|
230
|
+
|
|
231
|
+
def default_values
|
|
232
|
+
@query = "default values"
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Return the SQL statement. Especially useful for debugging.
|
|
236
|
+
|
|
237
|
+
def statement
|
|
238
|
+
[
|
|
239
|
+
"insert into",
|
|
240
|
+
@table,
|
|
241
|
+
column_list,
|
|
242
|
+
query_expression,
|
|
243
|
+
].compact.join(' ')
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# Execute the statement.
|
|
247
|
+
#
|
|
248
|
+
# [connection]
|
|
249
|
+
# If present, the connection to use.
|
|
250
|
+
# If nil, uses the connection passed to new or, if no connection was
|
|
251
|
+
# passed to new, uses the default connection.
|
|
252
|
+
|
|
253
|
+
def exec(connection = @connection)
|
|
254
|
+
connection.exec(statement)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
private
|
|
258
|
+
|
|
259
|
+
def query_expression
|
|
260
|
+
@query || source
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def column_list
|
|
264
|
+
"(#{@columns.join(', ')})" unless @columns.empty?
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def source
|
|
268
|
+
"values (#{@values.join(', ')}) #{@returning_expression}".strip
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Local Variables:
|
|
276
|
+
# tab-width: 2
|
|
277
|
+
# ruby-indent-level: 2
|
|
278
|
+
# indent-tabs-mode: nil
|
|
279
|
+
# End:
|