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.
Files changed (207) hide show
  1. data/Gemfile +8 -0
  2. data/Gemfile.lock +22 -0
  3. data/LICENSE.md +23 -0
  4. data/README.rdoc +59 -0
  5. data/Rakefile +32 -0
  6. data/VERSION +1 -0
  7. data/doc/BUGS +2 -0
  8. data/doc/examples/README +6 -0
  9. data/doc/examples/connection.rb +16 -0
  10. data/doc/examples/connection_auto.rb +22 -0
  11. data/doc/examples/connection_ctor.rb +18 -0
  12. data/doc/examples/connection_default.rb +15 -0
  13. data/doc/examples/connection_exec.rb +18 -0
  14. data/doc/examples/connection_manual.rb +12 -0
  15. data/doc/examples/connection_wrapped_new.rb +13 -0
  16. data/doc/examples/connection_wrapped_open.rb +13 -0
  17. data/doc/examples/cursor.rb +38 -0
  18. data/doc/examples/include_module.rb +9 -0
  19. data/doc/examples/include_module2.rb +12 -0
  20. data/doc/examples/insert.rb +30 -0
  21. data/doc/examples/insert2.rb +36 -0
  22. data/doc/examples/insert_bytea.rb +16 -0
  23. data/doc/examples/insert_bytea_array.rb +17 -0
  24. data/doc/examples/insert_default_values.rb +16 -0
  25. data/doc/examples/insert_insert.rb +16 -0
  26. data/doc/examples/insert_insert_default.rb +16 -0
  27. data/doc/examples/insert_insert_select.rb +20 -0
  28. data/doc/examples/insert_select.rb +20 -0
  29. data/doc/examples/interval.rb +17 -0
  30. data/doc/examples/savepoint.rb +38 -0
  31. data/doc/examples/select.rb +33 -0
  32. data/doc/examples/select2.rb +36 -0
  33. data/doc/examples/select_cross_join.rb +18 -0
  34. data/doc/examples/select_distinct.rb +18 -0
  35. data/doc/examples/select_distinct_on +19 -0
  36. data/doc/examples/select_for_update.rb +18 -0
  37. data/doc/examples/select_from.rb +17 -0
  38. data/doc/examples/select_from_subselect.rb +20 -0
  39. data/doc/examples/select_group_by.rb +19 -0
  40. data/doc/examples/select_having.rb +20 -0
  41. data/doc/examples/select_join_on.rb +18 -0
  42. data/doc/examples/select_join_using.rb +18 -0
  43. data/doc/examples/select_limit.rb +19 -0
  44. data/doc/examples/select_natural_join.rb +18 -0
  45. data/doc/examples/select_offset.rb +19 -0
  46. data/doc/examples/select_order_by.rb +20 -0
  47. data/doc/examples/select_select.rb +30 -0
  48. data/doc/examples/select_select_alias.rb +30 -0
  49. data/doc/examples/select_select_expression.rb +31 -0
  50. data/doc/examples/select_select_literal.rb +24 -0
  51. data/doc/examples/select_union.rb +21 -0
  52. data/doc/examples/select_where_array.rb +18 -0
  53. data/doc/examples/select_where_in.rb +18 -0
  54. data/doc/examples/select_where_string.rb +18 -0
  55. data/doc/examples/simple.rb +34 -0
  56. data/doc/examples/transaction.rb +30 -0
  57. data/doc/examples/transaction_abort.rb +30 -0
  58. data/doc/examples/transaction_commit.rb +34 -0
  59. data/doc/examples/translate_substitute_values.rb +17 -0
  60. data/doc/examples/update.rb +32 -0
  61. data/doc/examples/update2.rb +44 -0
  62. data/doc/examples/update_only.rb +17 -0
  63. data/doc/examples/update_set.rb +17 -0
  64. data/doc/examples/update_set_array.rb +16 -0
  65. data/doc/examples/update_set_bytea.rb +16 -0
  66. data/doc/examples/update_set_expression.rb +16 -0
  67. data/doc/examples/update_set_subselect.rb +20 -0
  68. data/doc/examples/update_where.rb +17 -0
  69. data/doc/examples/use_prefix.rb +8 -0
  70. data/doc/examples/use_prefix2.rb +11 -0
  71. data/doc/index.html +31 -0
  72. data/doc/insertexamples.rb +9 -0
  73. data/doc/makemanual +4 -0
  74. data/doc/makerdoc +5 -0
  75. data/doc/manual.dbk +622 -0
  76. data/lib/sqlpostgres/Connection.rb +198 -0
  77. data/lib/sqlpostgres/Cursor.rb +157 -0
  78. data/lib/sqlpostgres/Delete.rb +67 -0
  79. data/lib/sqlpostgres/Exceptions.rb +15 -0
  80. data/lib/sqlpostgres/Insert.rb +279 -0
  81. data/lib/sqlpostgres/NullConnection.rb +22 -0
  82. data/lib/sqlpostgres/PgBit.rb +73 -0
  83. data/lib/sqlpostgres/PgBox.rb +37 -0
  84. data/lib/sqlpostgres/PgCidr.rb +21 -0
  85. data/lib/sqlpostgres/PgCircle.rb +75 -0
  86. data/lib/sqlpostgres/PgInet.rb +21 -0
  87. data/lib/sqlpostgres/PgInterval.rb +208 -0
  88. data/lib/sqlpostgres/PgLineSegment.rb +37 -0
  89. data/lib/sqlpostgres/PgMacAddr.rb +21 -0
  90. data/lib/sqlpostgres/PgPath.rb +64 -0
  91. data/lib/sqlpostgres/PgPoint.rb +65 -0
  92. data/lib/sqlpostgres/PgPolygon.rb +56 -0
  93. data/lib/sqlpostgres/PgTime.rb +77 -0
  94. data/lib/sqlpostgres/PgTimeWithTimeZone.rb +98 -0
  95. data/lib/sqlpostgres/PgTimestamp.rb +93 -0
  96. data/lib/sqlpostgres/PgTwoPoints.rb +54 -0
  97. data/lib/sqlpostgres/PgType.rb +34 -0
  98. data/lib/sqlpostgres/PgWrapper.rb +41 -0
  99. data/lib/sqlpostgres/Savepoint.rb +98 -0
  100. data/lib/sqlpostgres/Select.rb +855 -0
  101. data/lib/sqlpostgres/Transaction.rb +120 -0
  102. data/lib/sqlpostgres/Translate.rb +436 -0
  103. data/lib/sqlpostgres/Update.rb +188 -0
  104. data/lib/sqlpostgres.rb +67 -0
  105. data/test/Assert.rb +72 -0
  106. data/test/Connection.test.rb +246 -0
  107. data/test/Cursor.test.rb +190 -0
  108. data/test/Delete.test.rb +68 -0
  109. data/test/Insert.test.rb +123 -0
  110. data/test/MockPGconn.rb +62 -0
  111. data/test/NullConnection.test.rb +32 -0
  112. data/test/PgBit.test.rb +98 -0
  113. data/test/PgBox.test.rb +108 -0
  114. data/test/PgCidr.test.rb +61 -0
  115. data/test/PgCircle.test.rb +107 -0
  116. data/test/PgInet.test.rb +61 -0
  117. data/test/PgInterval.test.rb +180 -0
  118. data/test/PgLineSegment.test.rb +108 -0
  119. data/test/PgMacAddr.test.rb +61 -0
  120. data/test/PgPath.test.rb +106 -0
  121. data/test/PgPoint.test.rb +100 -0
  122. data/test/PgPolygon.test.rb +95 -0
  123. data/test/PgTime.test.rb +120 -0
  124. data/test/PgTimeWithTimeZone.test.rb +117 -0
  125. data/test/PgTimestamp.test.rb +134 -0
  126. data/test/RandomThings.rb +25 -0
  127. data/test/Savepoint.test.rb +286 -0
  128. data/test/Select.test.rb +930 -0
  129. data/test/Test.rb +62 -0
  130. data/test/TestConfig.rb +21 -0
  131. data/test/TestSetup.rb +13 -0
  132. data/test/TestUtil.rb +92 -0
  133. data/test/Transaction.test.rb +275 -0
  134. data/test/Translate.test.rb +354 -0
  135. data/test/Update.test.rb +227 -0
  136. data/test/roundtrip.test.rb +565 -0
  137. data/test/test +34 -0
  138. data/tools/exampleinserter/ExampleInserter.rb +177 -0
  139. data/tools/rdoc/ChangeLog +796 -0
  140. data/tools/rdoc/EXAMPLE.rb +48 -0
  141. data/tools/rdoc/MANIFEST +58 -0
  142. data/tools/rdoc/Makefile +27 -0
  143. data/tools/rdoc/NEW_FEATURES +226 -0
  144. data/tools/rdoc/README +390 -0
  145. data/tools/rdoc/ToDo +6 -0
  146. data/tools/rdoc/contrib/Index +6 -0
  147. data/tools/rdoc/contrib/xslfo/ChangeLog +181 -0
  148. data/tools/rdoc/contrib/xslfo/README +106 -0
  149. data/tools/rdoc/contrib/xslfo/TODO +10 -0
  150. data/tools/rdoc/contrib/xslfo/convert.xsl +151 -0
  151. data/tools/rdoc/contrib/xslfo/demo/README +21 -0
  152. data/tools/rdoc/contrib/xslfo/demo/rdocfo +99 -0
  153. data/tools/rdoc/contrib/xslfo/fcm.xsl +54 -0
  154. data/tools/rdoc/contrib/xslfo/files.xsl +62 -0
  155. data/tools/rdoc/contrib/xslfo/labeled-lists.xsl +66 -0
  156. data/tools/rdoc/contrib/xslfo/lists.xsl +44 -0
  157. data/tools/rdoc/contrib/xslfo/modules.xsl +152 -0
  158. data/tools/rdoc/contrib/xslfo/rdoc.xsl +75 -0
  159. data/tools/rdoc/contrib/xslfo/source.xsl +66 -0
  160. data/tools/rdoc/contrib/xslfo/styles.xsl +69 -0
  161. data/tools/rdoc/contrib/xslfo/tables.xsl +67 -0
  162. data/tools/rdoc/contrib/xslfo/utils.xsl +21 -0
  163. data/tools/rdoc/debian/changelog +33 -0
  164. data/tools/rdoc/debian/compat +1 -0
  165. data/tools/rdoc/debian/control +20 -0
  166. data/tools/rdoc/debian/copyright +10 -0
  167. data/tools/rdoc/debian/dirs +2 -0
  168. data/tools/rdoc/debian/docs +2 -0
  169. data/tools/rdoc/debian/rdoc.1 +252 -0
  170. data/tools/rdoc/debian/rdoc.manpages +1 -0
  171. data/tools/rdoc/debian/rdoc.pod +149 -0
  172. data/tools/rdoc/debian/rules +9 -0
  173. data/tools/rdoc/dot/dot.rb +255 -0
  174. data/tools/rdoc/etc/rdoc.dtd +203 -0
  175. data/tools/rdoc/install.rb +137 -0
  176. data/tools/rdoc/markup/install.rb +43 -0
  177. data/tools/rdoc/markup/sample/sample.rb +42 -0
  178. data/tools/rdoc/markup/simple_markup/fragments.rb +323 -0
  179. data/tools/rdoc/markup/simple_markup/inline.rb +348 -0
  180. data/tools/rdoc/markup/simple_markup/lines.rb +147 -0
  181. data/tools/rdoc/markup/simple_markup/preprocess.rb +68 -0
  182. data/tools/rdoc/markup/simple_markup/to_html.rb +281 -0
  183. data/tools/rdoc/markup/simple_markup.rb +474 -0
  184. data/tools/rdoc/markup/test/AllTests.rb +2 -0
  185. data/tools/rdoc/markup/test/TestInline.rb +151 -0
  186. data/tools/rdoc/markup/test/TestParse.rb +411 -0
  187. data/tools/rdoc/rdoc/code_objects.rb +536 -0
  188. data/tools/rdoc/rdoc/diagram.rb +331 -0
  189. data/tools/rdoc/rdoc/generators/chm_generator.rb +112 -0
  190. data/tools/rdoc/rdoc/generators/html_generator.rb +1268 -0
  191. data/tools/rdoc/rdoc/generators/template/chm/chm.rb +86 -0
  192. data/tools/rdoc/rdoc/generators/template/html/html.rb +705 -0
  193. data/tools/rdoc/rdoc/generators/template/html/kilmer.rb +377 -0
  194. data/tools/rdoc/rdoc/generators/template/xml/rdf.rb +110 -0
  195. data/tools/rdoc/rdoc/generators/template/xml/xml.rb +110 -0
  196. data/tools/rdoc/rdoc/generators/xml_generator.rb +130 -0
  197. data/tools/rdoc/rdoc/options.rb +451 -0
  198. data/tools/rdoc/rdoc/parsers/parse_c.rb +287 -0
  199. data/tools/rdoc/rdoc/parsers/parse_f95.rb +118 -0
  200. data/tools/rdoc/rdoc/parsers/parse_rb.rb +2311 -0
  201. data/tools/rdoc/rdoc/parsers/parse_simple.rb +37 -0
  202. data/tools/rdoc/rdoc/parsers/parserfactory.rb +75 -0
  203. data/tools/rdoc/rdoc/rdoc.rb +219 -0
  204. data/tools/rdoc/rdoc/template.rb +234 -0
  205. data/tools/rdoc/rdoc/tokenstream.rb +25 -0
  206. data/tools/rdoc/rdoc.rb +9 -0
  207. metadata +291 -0
@@ -0,0 +1,77 @@
1
+ require 'sqlpostgres/PgType'
2
+
3
+ module SqlPostgres
4
+
5
+ # This class holds the value of a "time" column.
6
+
7
+ class PgTime < PgType
8
+
9
+ # Return the hour (0..23)
10
+
11
+ attr_reader :hour
12
+
13
+ # Return the minute (0..59)
14
+
15
+ attr_reader :minute
16
+
17
+ # Return the second (0..59)
18
+
19
+ attr_reader :second
20
+
21
+ class << self
22
+
23
+ # Create a PgTime from a string in Postgres format (ie "12:00:00").
24
+
25
+ def from_sql(s)
26
+ PgTime.new(*s.split(":").collect do |p| p.to_i end)
27
+ end
28
+
29
+ end
30
+
31
+ # Constructor taking hour (0..23), minute (0..59), and second (0..59)
32
+
33
+ def initialize(hour = 0, minute = 0, second = 0)
34
+ @hour = hour
35
+ @minute = minute
36
+ @second = second
37
+ end
38
+
39
+ # Return a string representation (ie "12:00:00").
40
+
41
+ def to_s
42
+ "%02d:%02d:%02d" % [@hour, @minute, @second]
43
+ end
44
+
45
+ # Convert to an instance of Time on date 1970/01/01, local time zone.
46
+
47
+ def to_local_time
48
+ Time.local(1970, 1, 1, @hour, @minute, @second)
49
+ end
50
+
51
+ # Convert to an instance of Time on date 1970/01/01, utc time zone.
52
+
53
+ def to_utc_time
54
+ Time.utc(1970, 1, 1, @hour, @minute, @second)
55
+ end
56
+
57
+ protected
58
+
59
+ def parts
60
+ [hour, minute, second]
61
+ end
62
+
63
+ private
64
+
65
+ def column_type
66
+ 'time'
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+
73
+ # Local Variables:
74
+ # tab-width: 2
75
+ # ruby-indent-level: 2
76
+ # indent-tabs-mode: nil
77
+ # End:
@@ -0,0 +1,98 @@
1
+ require 'sqlpostgres/PgType'
2
+
3
+ module SqlPostgres
4
+
5
+ # This class holds the value of a "time" column.
6
+
7
+ class PgTimeWithTimeZone < PgType
8
+
9
+ # Return the hour (0..23)
10
+
11
+ attr_reader :hour
12
+
13
+ # Return the minute (0..59)
14
+
15
+ attr_reader :minute
16
+
17
+ # Return the second (0..59)
18
+
19
+ attr_reader :second
20
+
21
+ # Return the hours of the time-zone offset.
22
+
23
+ attr_reader :zone_hours
24
+
25
+ # Return the minutes of the time-zone offset.
26
+
27
+ attr_reader :zone_minutes
28
+
29
+ class << self
30
+
31
+ # Create a PgTimeWithTimeZone from a string in Postgres format
32
+ # (ie "12:00:00+0800").
33
+
34
+ def from_sql(s)
35
+ if s =~ /^(\d+):(\d+):(\d+)((?:\+|-)\d+)(?::(\d+))?$/
36
+ PgTimeWithTimeZone.new($1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i)
37
+ else
38
+ raise ArgumentError, "Invalid time with time zone: #{s.inspect}"
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ # Constructor.
45
+ #
46
+ # [hour]
47
+ # 0..23
48
+ # [minute]
49
+ # 0..59
50
+ # [second}
51
+ # 0..59
52
+ # [zone_hours]
53
+ # The hours of the time-zone offset (-23..23)
54
+ # [zone_minutes]
55
+ # The seconds of the time-zone offset (0..60)
56
+
57
+ def initialize(hour = 0, minute = 0, second = 0,
58
+ zone_hours = 0, zone_minutes = 0)
59
+ @hour = hour
60
+ @minute = minute
61
+ @second = second
62
+ @zone_hours = zone_hours
63
+ @zone_minutes = zone_minutes
64
+ end
65
+
66
+ # Return a string representation (ie "12:00:00-07:00").
67
+
68
+ def to_s
69
+ "%02d:%02d:%02d%+03d:%02d" % parts
70
+ end
71
+
72
+ # Convert to sql format (ie "timestamp '2001-01-01 12:00:00'").
73
+
74
+ def to_sql
75
+ "time with time zone '#{to_s}'"
76
+ end
77
+
78
+ protected
79
+
80
+ def parts
81
+ [@hour, @minute, @second, @zone_hours, @zone_minutes]
82
+ end
83
+
84
+ private
85
+
86
+ def column_type
87
+ 'time with time zone'
88
+ end
89
+
90
+ end
91
+
92
+ end
93
+
94
+ # Local Variables:
95
+ # tab-width: 2
96
+ # ruby-indent-level: 2
97
+ # indent-tabs-mode: nil
98
+ # End:
@@ -0,0 +1,93 @@
1
+ require 'sqlpostgres/PgType'
2
+
3
+ module SqlPostgres
4
+
5
+ # This class holds the value of a "timestamp" column.
6
+
7
+ class PgTimestamp < PgType
8
+
9
+ attr_reader :year
10
+ attr_reader :month
11
+ attr_reader :day
12
+ attr_reader :hour
13
+ attr_reader :minute
14
+ attr_reader :second
15
+ attr_reader :microseconds
16
+
17
+ class << self
18
+
19
+ # Convert from Postgres (ie '2001-01-01 12:00:01') to a PgTimestamp
20
+
21
+ def from_sql(s)
22
+ PgTimestamp.new(*s.gsub(/\D/, ' ').split.collect do |q| q.to_i end)
23
+ end
24
+
25
+ end
26
+
27
+ # Constructor taking all the pieces.
28
+
29
+ def initialize(year = 0, month = 0, day = 0,
30
+ hour = 0, minute = 0, second = 0,
31
+ microseconds = 0)
32
+ @year = year
33
+ @month = month
34
+ @day = day
35
+ @hour = hour
36
+ @minute = minute
37
+ @second = second
38
+ @microseconds = microseconds
39
+ end
40
+
41
+ # Convert to a string (ie '2001-01-01 12:00:00').
42
+
43
+ def to_s
44
+ "%04d-%02d-%02d %02d:%02d:%02d.%05d" % parts
45
+ end
46
+
47
+ # Convert to sql format (ie "timestamp '2001-01-01 12:00:00'").
48
+
49
+ def to_sql
50
+ "timestamp '#{to_s}'"
51
+ end
52
+
53
+ # Convert to an instance of Time in the local time zone.
54
+ #
55
+ # Note: Time can't take all the values that PgTimestamp can, so
56
+ # this method can easily raise an exception. Only use it if
57
+ # you're sure that the PgTimestamp will fit in a Time.
58
+
59
+ def to_local_time
60
+ Time.local(@year, @month, @day, @hour, @minute, @second)
61
+ end
62
+
63
+ # Convert to an instance of Time in the utc time zone.
64
+ #
65
+ # Note: Time can't take all the values that PgTimestamp can, so
66
+ # this method can easily raise an exception. Only use it if
67
+ # you're sure that the PgTimestamp will fit in a Time.
68
+
69
+ def to_utc_time
70
+ Time.utc(@year, @month, @day, @hour, @minute, @second)
71
+ end
72
+
73
+ protected
74
+
75
+ def parts
76
+ [@year, @month, @day, @hour, @minute, @second, @microseconds]
77
+ end
78
+
79
+ private
80
+
81
+ def column_type
82
+ 'timestamp'
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+
89
+ # Local Variables:
90
+ # tab-width: 2
91
+ # ruby-indent-level: 2
92
+ # indent-tabs-mode: nil
93
+ # End:
@@ -0,0 +1,54 @@
1
+ require 'sqlpostgres/PgType'
2
+
3
+ module SqlPostgres
4
+
5
+ # This is the base class for data types which have two points
6
+
7
+ class PgTwoPoints < PgType
8
+
9
+ # Return the first endpoint
10
+
11
+ attr_reader :p1
12
+
13
+ # Return the second endpoint
14
+
15
+ attr_reader :p2
16
+
17
+ # Constructor. Takes either 0 arguments, which sets both endpoints
18
+ # to (0, 0), or 2 PgPoint arguments, or 4 float arguments.
19
+
20
+ def initialize(*args)
21
+ case args.size
22
+ when 0
23
+ @p1 = PgPoint.new
24
+ @p2 = PgPoint.new
25
+ when 2
26
+ @p1 = args[0]
27
+ @p2 = args[1]
28
+ when 4
29
+ @p1 = PgPoint.new(*args[0..1])
30
+ @p2 = PgPoint.new(*args[2..3])
31
+ end
32
+ end
33
+
34
+ # Return a string representation (ie "((1, 2), (3, 4))").
35
+
36
+ def to_s
37
+ "(%s, %s)" % [p1, p2]
38
+ end
39
+
40
+ protected
41
+
42
+ def parts
43
+ [p1, p2]
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ # Local Variables:
51
+ # tab-width: 2
52
+ # ruby-indent-level: 2
53
+ # indent-tabs-mode: nil
54
+ # End:
@@ -0,0 +1,34 @@
1
+ module SqlPostgres
2
+
3
+ # This is the base class for the classes that represent column types.
4
+
5
+ class PgType
6
+
7
+ # Return true if +other+ is is equal to this object.
8
+
9
+ def eql?(other)
10
+ other.is_a?(self.class) && parts == other.parts
11
+ end
12
+ alias_method :==, :eql?
13
+
14
+ # Return the hash code.
15
+
16
+ def hash
17
+ parts.to_s.hash
18
+ end
19
+
20
+ # Return the SQL representation.
21
+
22
+ def to_sql
23
+ "#{column_type} '#{to_s}'"
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
30
+ # Local Variables:
31
+ # tab-width: 2
32
+ # ruby-indent-level: 2
33
+ # indent-tabs-mode: nil
34
+ # End:
@@ -0,0 +1,41 @@
1
+ require 'sqlpostgres/PgType'
2
+
3
+ module SqlPostgres
4
+
5
+ # This PgType is the base class of wrapper types that are merely
6
+ # wrappers around String. Its purpose is to identify the type of
7
+ # String (is it a mac address? An inet address? etc).
8
+
9
+ class PgWrapper < PgType
10
+
11
+ class << self
12
+
13
+ def from_sql(sql)
14
+ self.new(sql)
15
+ end
16
+
17
+ end
18
+
19
+ def initialize(value)
20
+ @value = value
21
+ end
22
+
23
+ def to_s
24
+ @value
25
+ end
26
+
27
+ protected
28
+
29
+ def parts
30
+ [@value]
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ # Local Variables:
38
+ # tab-width: 2
39
+ # ruby-indent-level: 2
40
+ # indent-tabs-mode: nil
41
+ # End:
@@ -0,0 +1,98 @@
1
+ module SqlPostgres
2
+
3
+ # This class handles a savepoint.
4
+ #
5
+ # Example:
6
+ #** example: savepoint
7
+ # Transaction.new(connection) do
8
+ #
9
+ # insert = Insert.new('foo', connection)
10
+ # insert.insert('i', 1)
11
+ # insert.exec
12
+ #
13
+ # Savepoint.new('bar', connection) do |sp|
14
+ # insert = Insert.new('foo', connection)
15
+ # insert.insert('i', 2)
16
+ # sp.abort
17
+ # end
18
+ #
19
+ # insert = Insert.new('foo', connection)
20
+ # insert.insert('i', 3)
21
+ # insert.exec
22
+ #
23
+ # end
24
+ #
25
+ # p connection.query("select i from foo order by i") #[["1"], ["3"]]
26
+ #**
27
+
28
+ class Savepoint
29
+
30
+ # Create an SQL savepoint, yield, and then commit the savepoint.
31
+ # If an exception occurs, the savepoint is aborted.
32
+ #
33
+ # If no connection is given, then the default connection is used.
34
+
35
+ def initialize(name, connection = Connection.default)
36
+ @name = name
37
+ @state = :open
38
+ @finished = false
39
+ @connection = connection
40
+ @connection.exec("savepoint #{name}")
41
+ begin
42
+ result = yield(self)
43
+ commit
44
+ result
45
+ rescue Exception
46
+ abort
47
+ raise
48
+ end
49
+ end
50
+
51
+ # Commit this savepoit. This is done for you unless an
52
+ # exception occurs within the block you passed to "new". Call
53
+ # this when you want to commit the savepoint before raising an
54
+ # exception -- in other words, when you want to keep your database
55
+ # changes even though an exception is about to occur.
56
+
57
+ def commit
58
+ unless @finished
59
+ do_commit
60
+ end
61
+ end
62
+
63
+ # Abort this savepoint. This is done for you when an exception
64
+ # occurs within the block you passed to "new". Call this when you
65
+ # want to abort a savepoint without throwing an exception.
66
+
67
+ def abort
68
+ unless @finished
69
+ do_abort
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def do_commit
76
+ release_savepoint
77
+ @finished = true
78
+ end
79
+
80
+ def do_abort
81
+ @connection.exec("rollback to #{@name}")
82
+ release_savepoint
83
+ @finished = true
84
+ end
85
+
86
+ def release_savepoint
87
+ @connection.exec("release savepoint #{@name}")
88
+ end
89
+
90
+ end
91
+
92
+ end
93
+
94
+ # Local Variables:
95
+ # tab-width: 2
96
+ # ruby-indent-level: 2
97
+ # indent-tabs-mode: nil
98
+ # End: