/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb

https://github.com/Tho85/rails · Ruby · 168 lines · 149 code · 19 blank · 0 comment · 22 complexity · b5b8e40d7f36e432729868b7913f6d5e MD5 · raw file

  1. module ActiveRecord
  2. module ConnectionAdapters
  3. class PostgreSQLColumn < Column
  4. module Cast
  5. def point_to_string(point)
  6. "(#{point[0]},#{point[1]})"
  7. end
  8. def string_to_point(string)
  9. if string[0] == '(' && string[-1] == ')'
  10. string = string[1...-1]
  11. end
  12. string.split(',').map{ |v| Float(v) }
  13. end
  14. def string_to_time(string)
  15. return string unless String === string
  16. case string
  17. when 'infinity'; Float::INFINITY
  18. when '-infinity'; -Float::INFINITY
  19. when / BC$/
  20. super("-" + string.sub(/ BC$/, ""))
  21. else
  22. super
  23. end
  24. end
  25. def string_to_bit(value)
  26. case value
  27. when /^0x/i
  28. value[2..-1].hex.to_s(2) # Hexadecimal notation
  29. else
  30. value # Bit-string notation
  31. end
  32. end
  33. def hstore_to_string(object, array_member = false)
  34. if Hash === object
  35. string = object.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(',')
  36. string = escape_hstore(string) if array_member
  37. string
  38. else
  39. object
  40. end
  41. end
  42. def string_to_hstore(string)
  43. if string.nil?
  44. nil
  45. elsif String === string
  46. Hash[string.scan(HstorePair).map { |k, v|
  47. v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
  48. k = k.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
  49. [k, v]
  50. }]
  51. else
  52. string
  53. end
  54. end
  55. def json_to_string(object)
  56. if Hash === object || Array === object
  57. ActiveSupport::JSON.encode(object)
  58. else
  59. object
  60. end
  61. end
  62. def array_to_string(value, column, adapter)
  63. casted_values = value.map do |val|
  64. if String === val
  65. if val == "NULL"
  66. "\"#{val}\""
  67. else
  68. quote_and_escape(adapter.type_cast(val, column, true))
  69. end
  70. else
  71. adapter.type_cast(val, column, true)
  72. end
  73. end
  74. "{#{casted_values.join(',')}}"
  75. end
  76. def range_to_string(object)
  77. from = object.begin.respond_to?(:infinite?) && object.begin.infinite? ? '' : object.begin
  78. to = object.end.respond_to?(:infinite?) && object.end.infinite? ? '' : object.end
  79. "[#{from},#{to}#{object.exclude_end? ? ')' : ']'}"
  80. end
  81. def string_to_json(string)
  82. if String === string
  83. ActiveSupport::JSON.decode(string)
  84. else
  85. string
  86. end
  87. end
  88. def string_to_cidr(string)
  89. if string.nil?
  90. nil
  91. elsif String === string
  92. begin
  93. IPAddr.new(string)
  94. rescue ArgumentError
  95. nil
  96. end
  97. else
  98. string
  99. end
  100. end
  101. def cidr_to_string(object)
  102. if IPAddr === object
  103. "#{object.to_s}/#{object.instance_variable_get(:@mask_addr).to_s(2).count('1')}"
  104. else
  105. object
  106. end
  107. end
  108. def string_to_array(string, oid)
  109. parse_pg_array(string).map {|val| type_cast_array(oid, val)}
  110. end
  111. private
  112. HstorePair = begin
  113. quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/
  114. unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
  115. /(#{quoted_string}|#{unquoted_string})\s*=>\s*(#{quoted_string}|#{unquoted_string})/
  116. end
  117. def escape_hstore(value)
  118. if value.nil?
  119. 'NULL'
  120. else
  121. if value == ""
  122. '""'
  123. else
  124. '"%s"' % value.to_s.gsub(/(["\\])/, '\\\\\1')
  125. end
  126. end
  127. end
  128. ARRAY_ESCAPE = "\\" * 2 * 2 # escape the backslash twice for PG arrays
  129. def quote_and_escape(value)
  130. case value
  131. when "NULL", Numeric
  132. value
  133. else
  134. value = value.gsub(/\\/, ARRAY_ESCAPE)
  135. value.gsub!(/"/,"\\\"")
  136. "\"#{value}\""
  137. end
  138. end
  139. def type_cast_array(oid, value)
  140. if ::Array === value
  141. value.map {|item| type_cast_array(oid, item)}
  142. else
  143. oid.type_cast value
  144. end
  145. end
  146. end
  147. end
  148. end
  149. end