amalgalite 0.4.2-x86-mswin32-60

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 (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