pragmas.rb 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. require 'sqlite3/errors'
  2. module SQLite3
  3. # This module is intended for inclusion solely by the Database class. It
  4. # defines convenience methods for the various pragmas supported by SQLite3.
  5. #
  6. # For a detailed description of these pragmas, see the SQLite3 documentation
  7. # at http://sqlite.org/pragma.html.
  8. module Pragmas
  9. # Returns +true+ or +false+ depending on the value of the named pragma.
  10. def get_boolean_pragma( name )
  11. get_first_value( "PRAGMA #{name}" ) != "0"
  12. end
  13. private :get_boolean_pragma
  14. # Sets the given pragma to the given boolean value. The value itself
  15. # may be +true+ or +false+, or any other commonly used string or
  16. # integer that represents truth.
  17. def set_boolean_pragma( name, mode )
  18. case mode
  19. when String
  20. case mode.downcase
  21. when "on", "yes", "true", "y", "t"; mode = "'ON'"
  22. when "off", "no", "false", "n", "f"; mode = "'OFF'"
  23. else
  24. raise Exception,
  25. "unrecognized pragma parameter #{mode.inspect}"
  26. end
  27. when true, 1
  28. mode = "ON"
  29. when false, 0, nil
  30. mode = "OFF"
  31. else
  32. raise Exception,
  33. "unrecognized pragma parameter #{mode.inspect}"
  34. end
  35. execute( "PRAGMA #{name}=#{mode}" )
  36. end
  37. private :set_boolean_pragma
  38. # Requests the given pragma (and parameters), and if the block is given,
  39. # each row of the result set will be yielded to it. Otherwise, the results
  40. # are returned as an array.
  41. def get_query_pragma( name, *parms, &block ) # :yields: row
  42. if parms.empty?
  43. execute( "PRAGMA #{name}", &block )
  44. else
  45. args = "'" + parms.join("','") + "'"
  46. execute( "PRAGMA #{name}( #{args} )", &block )
  47. end
  48. end
  49. private :get_query_pragma
  50. # Return the value of the given pragma.
  51. def get_enum_pragma( name )
  52. get_first_value( "PRAGMA #{name}" )
  53. end
  54. private :get_enum_pragma
  55. # Set the value of the given pragma to +mode+. The +mode+ parameter must
  56. # conform to one of the values in the given +enum+ array. Each entry in
  57. # the array is another array comprised of elements in the enumeration that
  58. # have duplicate values. See #synchronous, #default_synchronous,
  59. # #temp_store, and #default_temp_store for usage examples.
  60. def set_enum_pragma( name, mode, enums )
  61. match = enums.find { |p| p.find { |i| i.to_s.downcase == mode.to_s.downcase } }
  62. raise Exception,
  63. "unrecognized #{name} #{mode.inspect}" unless match
  64. execute( "PRAGMA #{name}='#{match.first.upcase}'" )
  65. end
  66. private :set_enum_pragma
  67. # Returns the value of the given pragma as an integer.
  68. def get_int_pragma( name )
  69. get_first_value( "PRAGMA #{name}" ).to_i
  70. end
  71. private :get_int_pragma
  72. # Set the value of the given pragma to the integer value of the +value+
  73. # parameter.
  74. def set_int_pragma( name, value )
  75. execute( "PRAGMA #{name}=#{value.to_i}" )
  76. end
  77. private :set_int_pragma
  78. # The enumeration of valid synchronous modes.
  79. SYNCHRONOUS_MODES = [ [ 'full', 2 ], [ 'normal', 1 ], [ 'off', 0 ] ]
  80. # The enumeration of valid temp store modes.
  81. TEMP_STORE_MODES = [ [ 'default', 0 ], [ 'file', 1 ], [ 'memory', 2 ] ]
  82. # Does an integrity check on the database. If the check fails, a
  83. # SQLite3::Exception will be raised. Otherwise it
  84. # returns silently.
  85. def integrity_check
  86. execute( "PRAGMA integrity_check" ) do |row|
  87. raise Exception, row[0] if row[0] != "ok"
  88. end
  89. end
  90. def auto_vacuum
  91. get_boolean_pragma "auto_vacuum"
  92. end
  93. def auto_vacuum=( mode )
  94. set_boolean_pragma "auto_vacuum", mode
  95. end
  96. def schema_cookie
  97. get_int_pragma "schema_cookie"
  98. end
  99. def schema_cookie=( cookie )
  100. set_int_pragma "schema_cookie", cookie
  101. end
  102. def user_cookie
  103. get_int_pragma "user_cookie"
  104. end
  105. def user_cookie=( cookie )
  106. set_int_pragma "user_cookie", cookie
  107. end
  108. def cache_size
  109. get_int_pragma "cache_size"
  110. end
  111. def cache_size=( size )
  112. set_int_pragma "cache_size", size
  113. end
  114. def default_cache_size
  115. get_int_pragma "default_cache_size"
  116. end
  117. def default_cache_size=( size )
  118. set_int_pragma "default_cache_size", size
  119. end
  120. def default_synchronous
  121. get_enum_pragma "default_synchronous"
  122. end
  123. def default_synchronous=( mode )
  124. set_enum_pragma "default_synchronous", mode, SYNCHRONOUS_MODES
  125. end
  126. def synchronous
  127. get_enum_pragma "synchronous"
  128. end
  129. def synchronous=( mode )
  130. set_enum_pragma "synchronous", mode, SYNCHRONOUS_MODES
  131. end
  132. def default_temp_store
  133. get_enum_pragma "default_temp_store"
  134. end
  135. def default_temp_store=( mode )
  136. set_enum_pragma "default_temp_store", mode, TEMP_STORE_MODES
  137. end
  138. def temp_store
  139. get_enum_pragma "temp_store"
  140. end
  141. def temp_store=( mode )
  142. set_enum_pragma "temp_store", mode, TEMP_STORE_MODES
  143. end
  144. def full_column_names
  145. get_boolean_pragma "full_column_names"
  146. end
  147. def full_column_names=( mode )
  148. set_boolean_pragma "full_column_names", mode
  149. end
  150. def parser_trace
  151. get_boolean_pragma "parser_trace"
  152. end
  153. def parser_trace=( mode )
  154. set_boolean_pragma "parser_trace", mode
  155. end
  156. def vdbe_trace
  157. get_boolean_pragma "vdbe_trace"
  158. end
  159. def vdbe_trace=( mode )
  160. set_boolean_pragma "vdbe_trace", mode
  161. end
  162. def database_list( &block ) # :yields: row
  163. get_query_pragma "database_list", &block
  164. end
  165. def foreign_key_list( table, &block ) # :yields: row
  166. get_query_pragma "foreign_key_list", table, &block
  167. end
  168. def index_info( index, &block ) # :yields: row
  169. get_query_pragma "index_info", index, &block
  170. end
  171. def index_list( table, &block ) # :yields: row
  172. get_query_pragma "index_list", table, &block
  173. end
  174. ###
  175. # Returns information about +table+. Yields each row of table information
  176. # if a block is provided.
  177. def table_info table
  178. stmt = prepare "PRAGMA table_info(#{table})"
  179. columns = stmt.columns
  180. needs_tweak_default =
  181. version_compare(SQLite3.libversion.to_s, "3.3.7") > 0
  182. result = [] unless block_given?
  183. stmt.each do |row|
  184. new_row = Hash[columns.zip(row)]
  185. # FIXME: This should be removed but is required for older versions
  186. # of rails
  187. if(Object.const_defined?(:ActiveRecord))
  188. new_row['notnull'] = new_row['notnull'].to_s
  189. end
  190. tweak_default(new_row) if needs_tweak_default
  191. if block_given?
  192. yield new_row
  193. else
  194. result << new_row
  195. end
  196. end
  197. stmt.close
  198. result
  199. end
  200. private
  201. # Compares two version strings
  202. def version_compare(v1, v2)
  203. v1 = v1.split(".").map { |i| i.to_i }
  204. v2 = v2.split(".").map { |i| i.to_i }
  205. parts = [v1.length, v2.length].max
  206. v1.push 0 while v1.length < parts
  207. v2.push 0 while v2.length < parts
  208. v1.zip(v2).each do |a,b|
  209. return -1 if a < b
  210. return 1 if a > b
  211. end
  212. return 0
  213. end
  214. # Since SQLite 3.3.8, the table_info pragma has returned the default
  215. # value of the row as a quoted SQL value. This method essentially
  216. # unquotes those values.
  217. def tweak_default(hash)
  218. case hash["dflt_value"]
  219. when /^null$/i
  220. hash["dflt_value"] = nil
  221. when /^'(.*)'$/
  222. hash["dflt_value"] = $1.gsub(/''/, "'")
  223. when /^"(.*)"$/
  224. hash["dflt_value"] = $1.gsub(/""/, '"')
  225. end
  226. end
  227. end
  228. end