amalgalite 0.4.2-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/HISTORY +81 -0
  2. data/LICENSE +29 -0
  3. data/README +40 -0
  4. data/bin/amalgalite-pack-into-db +155 -0
  5. data/examples/a.rb +9 -0
  6. data/examples/blob.rb +105 -0
  7. data/examples/bootstrap.rb +36 -0
  8. data/examples/gem-db.rb +94 -0
  9. data/examples/requires.rb +54 -0
  10. data/examples/schema-info.rb +34 -0
  11. data/ext/amalgalite3.c +201 -0
  12. data/ext/amalgalite3.h +121 -0
  13. data/ext/amalgalite3_blob.c +241 -0
  14. data/ext/amalgalite3_constants.c +221 -0
  15. data/ext/amalgalite3_database.c +550 -0
  16. data/ext/amalgalite3_requires_bootstrap.c +210 -0
  17. data/ext/amalgalite3_statement.c +628 -0
  18. data/ext/extconf.rb +19 -0
  19. data/ext/gen_constants.rb +130 -0
  20. data/ext/rbconfig-mingw.rb +178 -0
  21. data/ext/sqlite3.c +97092 -0
  22. data/ext/sqlite3.h +6364 -0
  23. data/ext/sqlite3_options.h +4 -0
  24. data/ext/sqlite3ext.h +372 -0
  25. data/gemspec.rb +55 -0
  26. data/lib/amalgalite.rb +33 -0
  27. data/lib/amalgalite/blob.rb +186 -0
  28. data/lib/amalgalite/boolean.rb +42 -0
  29. data/lib/amalgalite/column.rb +86 -0
  30. data/lib/amalgalite/core_ext/kernel/require.rb +14 -0
  31. data/lib/amalgalite/database.rb +514 -0
  32. data/lib/amalgalite/index.rb +43 -0
  33. data/lib/amalgalite/paths.rb +70 -0
  34. data/lib/amalgalite/profile_tap.rb +130 -0
  35. data/lib/amalgalite/requires.rb +112 -0
  36. data/lib/amalgalite/schema.rb +115 -0
  37. data/lib/amalgalite/sqlite3.rb +6 -0
  38. data/lib/amalgalite/sqlite3/constants.rb +82 -0
  39. data/lib/amalgalite/sqlite3/database/status.rb +69 -0
  40. data/lib/amalgalite/sqlite3/status.rb +61 -0
  41. data/lib/amalgalite/sqlite3/version.rb +38 -0
  42. data/lib/amalgalite/statement.rb +394 -0
  43. data/lib/amalgalite/table.rb +36 -0
  44. data/lib/amalgalite/taps.rb +2 -0
  45. data/lib/amalgalite/taps/console.rb +27 -0
  46. data/lib/amalgalite/taps/io.rb +71 -0
  47. data/lib/amalgalite/trace_tap.rb +35 -0
  48. data/lib/amalgalite/type_map.rb +63 -0
  49. data/lib/amalgalite/type_maps/default_map.rb +167 -0
  50. data/lib/amalgalite/type_maps/storage_map.rb +41 -0
  51. data/lib/amalgalite/type_maps/text_map.rb +23 -0
  52. data/lib/amalgalite/version.rb +37 -0
  53. data/lib/amalgalite/view.rb +26 -0
  54. data/lib/amalgalite3.so +0 -0
  55. data/spec/amalgalite_spec.rb +4 -0
  56. data/spec/blob_spec.rb +81 -0
  57. data/spec/boolean_spec.rb +23 -0
  58. data/spec/database_spec.rb +238 -0
  59. data/spec/default_map_spec.rb +87 -0
  60. data/spec/integeration_spec.rb +111 -0
  61. data/spec/paths_spec.rb +28 -0
  62. data/spec/schema_spec.rb +60 -0
  63. data/spec/spec_helper.rb +25 -0
  64. data/spec/sqlite3/constants_spec.rb +65 -0
  65. data/spec/sqlite3/database_status_spec.rb +36 -0
  66. data/spec/sqlite3/status_spec.rb +18 -0
  67. data/spec/sqlite3/version_spec.rb +14 -0
  68. data/spec/sqlite3_spec.rb +23 -0
  69. data/spec/statement_spec.rb +134 -0
  70. data/spec/storage_map_spec.rb +41 -0
  71. data/spec/tap_spec.rb +59 -0
  72. data/spec/text_map_spec.rb +23 -0
  73. data/spec/type_map_spec.rb +17 -0
  74. data/spec/version_spec.rb +9 -0
  75. data/tasks/announce.rake +39 -0
  76. data/tasks/config.rb +110 -0
  77. data/tasks/distribution.rake +53 -0
  78. data/tasks/documentation.rake +33 -0
  79. data/tasks/extension.rake +100 -0
  80. data/tasks/rspec.rake +32 -0
  81. data/tasks/rubyforge.rake +59 -0
  82. data/tasks/utils.rb +80 -0
  83. metadata +192 -0
@@ -0,0 +1,6 @@
1
+ require 'amalgalite3'
2
+ require 'amalgalite/version'
3
+ require 'amalgalite/sqlite3/version'
4
+ require 'amalgalite/sqlite3/constants'
5
+ require 'amalgalite/sqlite3/status'
6
+ require 'amalgalite/sqlite3/database/status'
@@ -0,0 +1,82 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ require 'amalgalite3'
7
+ module Amalgalite::SQLite3
8
+ module Constants
9
+ module Helpers
10
+ #
11
+ # convert an integer value into the string representation of the associated
12
+ # constant. this is a helper method used by some of the other modules
13
+ #
14
+ def name_from_value( value )
15
+ unless @const_map_from_value
16
+ @const_map_from_value = {}
17
+ constants.each do |const_name|
18
+ c_int = const_get( const_name )
19
+ @const_map_from_value[c_int] = const_name
20
+ end
21
+ end
22
+ return @const_map_from_value[ value ]
23
+ end
24
+
25
+ #
26
+ # convert a string into the constant value. This is helper method used by
27
+ # some of the other modules
28
+ #
29
+ def value_from_name( name )
30
+ unless @const_map_from_name
31
+ @const_map_from_name = {}
32
+ constants.each do |const_name|
33
+ c_int = const_get( const_name )
34
+ @const_map_from_name[ const_name ] = c_int
35
+ end
36
+ end
37
+ return @const_map_from_name[ name.upcase ]
38
+ end
39
+ end
40
+
41
+
42
+ ##
43
+ # DataType defines the namespace for all possible SQLite data types.
44
+ #
45
+ module DataType
46
+ end
47
+ DataType.freeze
48
+
49
+ ##
50
+ # Open defines the namespace for all possible flags to the Database.open
51
+ # method
52
+ #
53
+ module Open
54
+ end
55
+ Open.freeze
56
+
57
+ ##
58
+ # Status defines the namespace for all the possible status flags for
59
+ # Amalgalite::SQLite3::Status objects
60
+ #
61
+ module Status
62
+ extend Helpers
63
+ end
64
+
65
+
66
+ ##
67
+ # DBStatus defines the namespace for all the possible status codes for the
68
+ # Amalgalite::SQlite3::Database::Status objects.
69
+ #
70
+ module DBStatus
71
+ extend Helpers
72
+ end
73
+
74
+ ##
75
+ # ResultCode defines the namespace for all possible result codes from an
76
+ # SQLite API call.
77
+ #
78
+ module ResultCode
79
+ extend Helpers
80
+ end # end ResultCode
81
+ end
82
+ end
@@ -0,0 +1,69 @@
1
+ require 'amalgalite3'
2
+ require 'amalgalite/sqlite3/constants'
3
+ module Amalgalite::SQLite3
4
+ class Database
5
+ #
6
+ # A Stat represents a single Database Status code and its current highwater mark.
7
+ #
8
+ # Some stats may not have a current or a highwater value, in those cases
9
+ # the associated _has_current?_ or _has_highwater?_ method returns false and the
10
+ # _current_ or _highwater_ method also returns +nil+.
11
+ #
12
+ class Stat
13
+ attr_reader :name
14
+ attr_reader :code
15
+
16
+ def initialize( api_db, name )
17
+ @name = name
18
+ @code = ::Amalgalite::SQLite3::Constants::DBStatus.value_from_name( name )
19
+ @current = nil
20
+ @highwater = nil
21
+ @api_db = api_db
22
+ end
23
+
24
+ def current
25
+ update!
26
+ return @current
27
+ end
28
+
29
+ def highwater
30
+ update!
31
+ return @highwater
32
+ end
33
+
34
+ #
35
+ # reset the given stat's highwater mark. This will also populate the
36
+ # _@current_ and _@highwater_ instance variables
37
+ #
38
+ def reset!
39
+ update!( true )
40
+ end
41
+ end
42
+
43
+ #
44
+ # Top level Status object holding all the Stat objects indicating the DBStatus
45
+ # of the SQLite3 C library.
46
+ #
47
+ class DBStatus
48
+ ::Amalgalite::SQLite3::Constants::DBStatus.constants.each do |const_name|
49
+ method_name = const_name.downcase
50
+ module_eval( <<-code, __FILE__, __LINE__ )
51
+ def #{method_name}
52
+ @#{method_name} ||= Amalgalite::SQLite3::Database::Stat.new( self.api_db, '#{method_name}' )
53
+ end
54
+ code
55
+ end
56
+
57
+ attr_reader :api_db
58
+
59
+ def initialize( api_db )
60
+ @api_db = api_db
61
+ end
62
+ end
63
+
64
+ # return the DBstatus object for the sqlite database
65
+ def status
66
+ @status ||= DBStatus.new( self )
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,61 @@
1
+ require 'amalgalite3'
2
+ require 'amalgalite/sqlite3/constants'
3
+ module Amalgalite::SQLite3
4
+
5
+ #
6
+ # A Stat represents a single Status code and its current highwater mark.
7
+ #
8
+ # Some stats may not have a current or a highwater value, in those cases
9
+ # the associated _has_current?_ or _has_highwater?_ method returns false and the
10
+ # _current_ or _highwater_ method also returns +nil+.
11
+ #
12
+ class Stat
13
+ attr_reader :name
14
+ attr_reader :code
15
+
16
+ def initialize( name )
17
+ @name = name
18
+ @code = ::Amalgalite::SQLite3::Constants::Status.value_from_name( name )
19
+ @current = nil
20
+ @highwater = nil
21
+ end
22
+
23
+ def current
24
+ update!
25
+ return @current
26
+ end
27
+
28
+ def highwater
29
+ update!
30
+ return @highwater
31
+ end
32
+
33
+ #
34
+ # reset the given stat's highwater mark. This will also populate the
35
+ # _@current_ and _@highwater_ instance variables
36
+ #
37
+ def reset!
38
+ update!( true )
39
+ end
40
+ end
41
+
42
+ #
43
+ # Top level Status object holding all the Stat objects indicating the Status
44
+ # of the SQLite3 C library.
45
+ #
46
+ class Status
47
+ ::Amalgalite::SQLite3::Constants::Status.constants.each do |const_name|
48
+ method_name = const_name.downcase
49
+ module_eval( <<-code, __FILE__, __LINE__ )
50
+ def #{method_name}
51
+ @#{method_name} ||= Amalgalite::SQLite3::Stat.new( '#{method_name}' )
52
+ end
53
+ code
54
+ end
55
+ end
56
+
57
+ # return the status object for the sqlite database
58
+ def self.status
59
+ @status ||= Status.new
60
+ end
61
+ end
@@ -0,0 +1,38 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+ require 'amalgalite3'
6
+ module Amalgalite
7
+ module SQLite3
8
+ module Version
9
+ # Sqlite3 version number is equal to
10
+ # MAJOR * 1_000_000 + MINOR * 1_000 + RELEASE
11
+
12
+ # major version number of the SQLite C library
13
+ MAJOR = (to_i / 1_000_000).freeze
14
+
15
+ # minor version number of the SQLite C library
16
+ MINOR = ((to_i % 1_000_000) / 1_000).freeze
17
+
18
+ # release version number of the SQLite C library
19
+ RELEASE = (to_i % 1_000).freeze
20
+
21
+ #
22
+ # call-seq:
23
+ # Amalgalite::SQLite3::Version.to_a -> [ MAJOR, MINOR, RELEASE ]
24
+ #
25
+ # Return the SQLite C library version number as an array of MAJOR, MINOR,
26
+ # RELEASE
27
+ #
28
+ def self.to_a
29
+ [ MAJOR, MINOR, RELEASE ]
30
+ end
31
+
32
+ end
33
+
34
+ # Version of SQLite that ships with Amalgalite
35
+ VERSION = Version.to_s.freeze
36
+ end
37
+ Version.freeze
38
+ end
@@ -0,0 +1,394 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+ #
6
+ require 'amalgalite3'
7
+ require 'date'
8
+ require 'arrayfields'
9
+ require 'ostruct'
10
+
11
+ module Amalgalite
12
+ class Statement
13
+
14
+ include ::Amalgalite::SQLite3::Constants
15
+
16
+ attr_reader :db
17
+ attr_reader :sql
18
+ attr_reader :api
19
+
20
+ class << self
21
+ # special column names that indicate that indicate the column is a rowid
22
+ def rowid_column_names
23
+ @rowid_column_names ||= %w[ ROWID OID _ROWID_ ]
24
+ end
25
+ end
26
+
27
+ ##
28
+ # Initialize a new statement on the database.
29
+ #
30
+ def initialize( db, sql )
31
+ @db = db
32
+ prepare_method = @db.utf16? ? :prepare16 : :prepare
33
+ @param_positions = {}
34
+ @stmt_api = @db.api.send( prepare_method, sql )
35
+ @blobs_to_write = []
36
+ @rowid_index = nil
37
+ end
38
+
39
+ ##
40
+ # Is the special column "ROWID", "OID", or "_ROWID_" used?
41
+ #
42
+ def using_rowid_column?
43
+ not @rowid_index.nil?
44
+ end
45
+
46
+ ##
47
+ # reset the Statement back to it state right after the constructor returned,
48
+ # except if any variables have been bound to parameters, those are still
49
+ # bound.
50
+ #
51
+ def reset!
52
+ @stmt_api.reset!
53
+ @param_positions = {}
54
+ @blobs_to_write.clear
55
+ @rowid_index = nil
56
+ end
57
+
58
+ ##
59
+ # reset the Statement back to it state right after the constructor returned,
60
+ # AND clear all parameter bindings.
61
+ #
62
+ def reset_and_clear_bindings!
63
+ reset!
64
+ @stmt_api.clear_bindings!
65
+ end
66
+
67
+ ##
68
+ # reset the statment in preparation for executing it again
69
+ #
70
+ def reset_for_next_execute!
71
+ @stmt_api.reset!
72
+ @stmt_api.clear_bindings!
73
+ @blobs_to_write.clear
74
+ end
75
+
76
+ ##
77
+ # Execute the statement with the given parameters
78
+ #
79
+ # If a block is given, then yield each returned row to the block. If no
80
+ # block is given then return all rows from the result. No matter what the
81
+ # prepared statement should be reset before returning the final time.
82
+ #
83
+ def execute( *params )
84
+ bind( *params )
85
+ begin
86
+ if block_given? then
87
+ while row = next_row
88
+ yield row
89
+ end
90
+ else
91
+ all_rows
92
+ end
93
+ ensure
94
+ s = $!
95
+ begin
96
+ reset_for_next_execute!
97
+ rescue => e
98
+ end
99
+ raise s if s
100
+ end
101
+ end
102
+
103
+ ##
104
+ # Bind parameters to the sql statement.
105
+ #
106
+ # Bindings in SQLite can have a number of formats:
107
+ #
108
+ # ?
109
+ # ?num
110
+ # :var
111
+ # @var
112
+ # $var
113
+ #
114
+ # Where 'num' is an Integer and 'var'is an alphanumerical variable.
115
+ # They may exist in the SQL for which this Statement was created.
116
+ #
117
+ # Amalgalite binds parameters to these variables in the following manner:
118
+ #
119
+ # If bind is passed in an Array, either as +bind( "foo", "bar", "baz")+ or
120
+ # as bind( ["foo", "bar", "baz"] ) then each of the params is assumed to be
121
+ # positionally bound to the statement( ?, ?num ).
122
+ #
123
+ # If bind is passed a Hash, either as +bind( :foo => 1, :bar => 'sqlite' )+
124
+ # or as bind( { :foo => 1, 'bar' => 'sqlite' }) then it is assumed that each
125
+ # parameter should be bound as a named parameter (:var, @var, $var).
126
+ #
127
+ # If bind is not passed any parameters, or nil, then nothing happens.
128
+ #
129
+ def bind( *params )
130
+ if params.nil? or params.empty? then
131
+ check_parameter_count!( 0 )
132
+ return nil
133
+ end
134
+
135
+ if params.first.instance_of?( Hash ) then
136
+ bind_named_parameters( params.first )
137
+ else
138
+ bind_positional_parameters( params )
139
+ end
140
+ end
141
+
142
+ ##
143
+ # Bind parameters to the statement based upon named parameters
144
+ #
145
+ def bind_named_parameters( params )
146
+ check_parameter_count!( params.size )
147
+ params.each_pair do | param, value |
148
+ position = param_position_of( param )
149
+ if position > 0 then
150
+ bind_parameter_to( position, value )
151
+ else
152
+ raise Amalgalite::Error, "Unable to find parameter '#{param}' in SQL statement [#{sql}]"
153
+ end
154
+ end
155
+ end
156
+
157
+ ##
158
+ # Bind parameters to the statements based upon positions.
159
+ #
160
+ def bind_positional_parameters( params )
161
+ check_parameter_count!( params.size )
162
+ params.each_with_index do |value, index|
163
+ position = index + 1
164
+ bind_parameter_to( position, value )
165
+ end
166
+ end
167
+
168
+ ##
169
+ # bind a single parameter to a particular position
170
+ #
171
+ def bind_parameter_to( position, value )
172
+ bind_type = db.type_map.bind_type_of( value )
173
+ case bind_type
174
+ when DataType::FLOAT
175
+ @stmt_api.bind_double( position, value )
176
+ when DataType::INTEGER
177
+ @stmt_api.bind_int64( position, value )
178
+ when DataType::NULL
179
+ @stmt_api.bind_null( position )
180
+ when DataType::TEXT
181
+ @stmt_api.bind_text( position, value.to_s )
182
+ when DataType::BLOB
183
+ if value.incremental? then
184
+ @stmt_api.bind_zeroblob( position, value.length )
185
+ @blobs_to_write << value
186
+ else
187
+ @stmt_api.bind_blob( position, value.source )
188
+ end
189
+ else
190
+ raise ::Amalgalite::Error, "Unknown binding type of #{bind_type} from #{db.type_map.class.name}.bind_type_of"
191
+ end
192
+ end
193
+
194
+
195
+ ##
196
+ # Find and cache the binding parameter indexes
197
+ #
198
+ def param_position_of( name )
199
+ ns = name.to_s
200
+ unless pos = @param_positions[ns]
201
+ pos = @param_positions[ns] = @stmt_api.parameter_index( ns )
202
+ end
203
+ return pos
204
+ end
205
+
206
+ ##
207
+ # Check and make sure that the number of parameters aligns with the number
208
+ # that sqlite expects
209
+ #
210
+ def check_parameter_count!( num )
211
+ expected = @stmt_api.parameter_count
212
+ if num != expected then
213
+ raise Amalgalite::Error, "#{sql} has #{expected} parameters, but #{num} were passed to bind."
214
+ end
215
+ return expected
216
+ end
217
+
218
+ ##
219
+ # Write any blobs that have been bound to parameters to the database. This
220
+ # assumes that the blobs go into the last inserted row
221
+ #
222
+ def write_blobs
223
+ unless @blobs_to_write.empty?
224
+ @blobs_to_write.each do |blob|
225
+ blob.write_to_column!
226
+ end
227
+ end
228
+ end
229
+
230
+ ##
231
+ # Iterate over the results of the statement returning each row of results
232
+ # as a hash by +column_name+. The column names are the value after an
233
+ # 'AS' in the query or default chosen by sqlite.
234
+ #
235
+ def each
236
+ while row = next_row
237
+ yield row
238
+ end
239
+ return self
240
+ end
241
+
242
+ ##
243
+ # Return the next row of data, with type conversion as indicated by the
244
+ # Database#type_map
245
+ #
246
+ def next_row
247
+ row = []
248
+ case rc = @stmt_api.step
249
+ when ResultCode::ROW
250
+ result_meta.each_with_index do |col, idx|
251
+ value = nil
252
+ column_type = @stmt_api.column_type( idx )
253
+ case column_type
254
+ when DataType::TEXT
255
+ value = @stmt_api.column_text( idx )
256
+ when DataType::FLOAT
257
+ value = @stmt_api.column_double( idx )
258
+ when DataType::INTEGER
259
+ value = @stmt_api.column_int64( idx )
260
+ when DataType::NULL
261
+ value = nil
262
+ when DataType::BLOB
263
+ # if the rowid column is encountered, then we can use an incremental
264
+ # blob api, otherwise we have to use the all at once version.
265
+ if using_rowid_column? then
266
+ value = Amalgalite::Blob.new( :db_blob => SQLite3::Blob.new( db.api,
267
+ col.schema.db,
268
+ col.schema.table,
269
+ col.schema.name,
270
+ @stmt_api.column_int64( @rowid_index ),
271
+ "r"),
272
+ :column => col.schema)
273
+ else
274
+ value = Amalgalite::Blob.new( :string => @stmt_api.column_blob( idx ), :column => col.schema )
275
+ end
276
+ else
277
+ raise ::Amalgalite::Error, "BUG! : Unknown SQLite column type of #{column_type}"
278
+ end
279
+
280
+ row << db.type_map.result_value_of( col.schema.declared_data_type, value )
281
+ end
282
+ row.fields = result_fields
283
+ when ResultCode::DONE
284
+ row = nil
285
+ write_blobs
286
+ else
287
+ raise Amalgalite::SQLite3::Error,
288
+ "SQLITE ERROR #{rc} (#{Amalgalite::SQLite3::Constants::ResultCode.from_int( rc )}) : #{@db.api.last_error_message}"
289
+ end
290
+ return row
291
+ end
292
+
293
+ ##
294
+ # Return all rows from the statement as one array
295
+ #
296
+ def all_rows
297
+ rows = []
298
+ while row = next_row
299
+ rows << row
300
+ end
301
+ return rows
302
+ end
303
+
304
+ ##
305
+ # Inspect the statement and gather all the meta information about the
306
+ # results, include the name of the column result column and the origin
307
+ # column. The origin column is the original database.table.column the value
308
+ # comes from.
309
+ #
310
+ # The full meta information from teh origin column is also obtained for help
311
+ # in doing type conversion.
312
+ #
313
+ # As iteration over the row meta informatio happens, record if the special
314
+ # "ROWID", "OID", or "_ROWID_" column is encountered. If that column is
315
+ # encountered then we make note of it.
316
+ #
317
+ def result_meta
318
+ unless @result_meta
319
+ meta = []
320
+ column_count.times do |idx|
321
+ column_meta = ::OpenStruct.new
322
+ column_meta.name = @stmt_api.column_name( idx )
323
+
324
+ db_name = @stmt_api.column_database_name( idx )
325
+ tbl_name = @stmt_api.column_table_name( idx )
326
+ col_name = @stmt_api.column_origin_name( idx )
327
+
328
+ column_meta.schema = ::Amalgalite::Column.new( db_name, tbl_name, col_name )
329
+ column_meta.schema.declared_data_type = @stmt_api.column_declared_type( idx )
330
+
331
+ # only check for rowid if we have a table name and it is not the
332
+ # sqlite_master table. We could get recursion in those cases.
333
+ if not using_rowid_column? and tbl_name and tbl_name != 'sqlite_master' and is_column_rowid?( tbl_name, col_name ) then
334
+ @rowid_index = idx
335
+ end
336
+
337
+ meta << column_meta
338
+ end
339
+
340
+ @result_meta = meta
341
+ end
342
+ return @result_meta
343
+ end
344
+
345
+ ##
346
+ # is the column indicated by the Column a 'rowid' column
347
+ #
348
+ def is_column_rowid?( table_name, column_name )
349
+ column_schema = @db.schema.tables[table_name].columns[column_name]
350
+ if column_schema.primary_key? and column_schema.declared_data_type and column_schema.declared_data_type.upcase == "INTEGER" then
351
+ return true
352
+ end
353
+ return false
354
+ end
355
+
356
+ ##
357
+ # Return the array of field names for the result set, the field names are
358
+ # all strings
359
+ #
360
+ def result_fields
361
+ @fields ||= result_meta.collect { |m| m.name }
362
+ end
363
+
364
+ ##
365
+ # Return any unsued SQL from the statement
366
+ #
367
+ def remaining_sql
368
+ @stmt_api.remaining_sql
369
+ end
370
+
371
+
372
+ ##
373
+ # return the number of columns in the result of this query
374
+ #
375
+ def column_count
376
+ @stmt_api.column_count
377
+ end
378
+
379
+ ##
380
+ # return the raw sql that was originally used to prepare the statement
381
+ #
382
+ def sql
383
+ @stmt_api.sql
384
+ end
385
+
386
+ ##
387
+ # Close the statement. The statement is no longer valid for use after it
388
+ # has been closed.
389
+ #
390
+ def close
391
+ @stmt_api.close
392
+ end
393
+ end
394
+ end