value.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. package sqlite3
  2. import (
  3. "encoding/json"
  4. "math"
  5. "strconv"
  6. "time"
  7. "github.com/ncruces/go-sqlite3/internal/util"
  8. )
  9. // Value is any value that can be stored in a database table.
  10. //
  11. // https://sqlite.org/c3ref/value.html
  12. type Value struct {
  13. c *Conn
  14. handle ptr_t
  15. unprot bool
  16. copied bool
  17. }
  18. func (v Value) protected() stk_t {
  19. if v.unprot {
  20. panic(util.ValueErr)
  21. }
  22. return stk_t(v.handle)
  23. }
  24. // Dup makes a copy of the SQL value and returns a pointer to that copy.
  25. //
  26. // https://sqlite.org/c3ref/value_dup.html
  27. func (v Value) Dup() *Value {
  28. ptr := ptr_t(v.c.call("sqlite3_value_dup", stk_t(v.handle)))
  29. return &Value{
  30. c: v.c,
  31. copied: true,
  32. handle: ptr,
  33. }
  34. }
  35. // Close frees an SQL value previously obtained by [Value.Dup].
  36. //
  37. // https://sqlite.org/c3ref/value_dup.html
  38. func (dup *Value) Close() error {
  39. if !dup.copied {
  40. panic(util.ValueErr)
  41. }
  42. dup.c.call("sqlite3_value_free", stk_t(dup.handle))
  43. dup.handle = 0
  44. return nil
  45. }
  46. // Type returns the initial datatype of the value.
  47. //
  48. // https://sqlite.org/c3ref/value_blob.html
  49. func (v Value) Type() Datatype {
  50. return Datatype(v.c.call("sqlite3_value_type", v.protected()))
  51. }
  52. // Type returns the numeric datatype of the value.
  53. //
  54. // https://sqlite.org/c3ref/value_blob.html
  55. func (v Value) NumericType() Datatype {
  56. return Datatype(v.c.call("sqlite3_value_numeric_type", v.protected()))
  57. }
  58. // Bool returns the value as a bool.
  59. // SQLite does not have a separate boolean storage class.
  60. // Instead, boolean values are retrieved as numbers,
  61. // with 0 converted to false and any other value to true.
  62. //
  63. // https://sqlite.org/c3ref/value_blob.html
  64. func (v Value) Bool() bool {
  65. return v.Float() != 0
  66. }
  67. // Int returns the value as an int.
  68. //
  69. // https://sqlite.org/c3ref/value_blob.html
  70. func (v Value) Int() int {
  71. return int(v.Int64())
  72. }
  73. // Int64 returns the value as an int64.
  74. //
  75. // https://sqlite.org/c3ref/value_blob.html
  76. func (v Value) Int64() int64 {
  77. return int64(v.c.call("sqlite3_value_int64", v.protected()))
  78. }
  79. // Float returns the value as a float64.
  80. //
  81. // https://sqlite.org/c3ref/value_blob.html
  82. func (v Value) Float() float64 {
  83. f := uint64(v.c.call("sqlite3_value_double", v.protected()))
  84. return math.Float64frombits(f)
  85. }
  86. // Time returns the value as a [time.Time].
  87. //
  88. // https://sqlite.org/c3ref/value_blob.html
  89. func (v Value) Time(format TimeFormat) time.Time {
  90. var a any
  91. switch v.Type() {
  92. case INTEGER:
  93. a = v.Int64()
  94. case FLOAT:
  95. a = v.Float()
  96. case TEXT, BLOB:
  97. a = v.Text()
  98. case NULL:
  99. return time.Time{}
  100. default:
  101. panic(util.AssertErr())
  102. }
  103. t, _ := format.Decode(a)
  104. return t
  105. }
  106. // Text returns the value as a string.
  107. //
  108. // https://sqlite.org/c3ref/value_blob.html
  109. func (v Value) Text() string {
  110. return string(v.RawText())
  111. }
  112. // Blob appends to buf and returns
  113. // the value as a []byte.
  114. //
  115. // https://sqlite.org/c3ref/value_blob.html
  116. func (v Value) Blob(buf []byte) []byte {
  117. return append(buf, v.RawBlob()...)
  118. }
  119. // RawText returns the value as a []byte.
  120. // The []byte is owned by SQLite and may be invalidated by
  121. // subsequent calls to [Value] methods.
  122. //
  123. // https://sqlite.org/c3ref/value_blob.html
  124. func (v Value) RawText() []byte {
  125. ptr := ptr_t(v.c.call("sqlite3_value_text", v.protected()))
  126. return v.rawBytes(ptr, 1)
  127. }
  128. // RawBlob returns the value as a []byte.
  129. // The []byte is owned by SQLite and may be invalidated by
  130. // subsequent calls to [Value] methods.
  131. //
  132. // https://sqlite.org/c3ref/value_blob.html
  133. func (v Value) RawBlob() []byte {
  134. ptr := ptr_t(v.c.call("sqlite3_value_blob", v.protected()))
  135. return v.rawBytes(ptr, 0)
  136. }
  137. func (v Value) rawBytes(ptr ptr_t, nul int32) []byte {
  138. if ptr == 0 {
  139. return nil
  140. }
  141. n := int32(v.c.call("sqlite3_value_bytes", v.protected()))
  142. return util.View(v.c.mod, ptr, int64(n+nul))[:n]
  143. }
  144. // Pointer gets the pointer associated with this value,
  145. // or nil if it has no associated pointer.
  146. func (v Value) Pointer() any {
  147. ptr := ptr_t(v.c.call("sqlite3_value_pointer_go", v.protected()))
  148. return util.GetHandle(v.c.ctx, ptr)
  149. }
  150. // JSON parses a JSON-encoded value
  151. // and stores the result in the value pointed to by ptr.
  152. func (v Value) JSON(ptr any) error {
  153. var data []byte
  154. switch v.Type() {
  155. case NULL:
  156. data = []byte("null")
  157. case TEXT:
  158. data = v.RawText()
  159. case BLOB:
  160. data = v.RawBlob()
  161. case INTEGER:
  162. data = strconv.AppendInt(nil, v.Int64(), 10)
  163. case FLOAT:
  164. data = util.AppendNumber(nil, v.Float())
  165. default:
  166. panic(util.AssertErr())
  167. }
  168. return json.Unmarshal(data, ptr)
  169. }
  170. // NoChange returns true if and only if the value is unchanged
  171. // in a virtual table update operatiom.
  172. //
  173. // https://sqlite.org/c3ref/value_blob.html
  174. func (v Value) NoChange() bool {
  175. b := int32(v.c.call("sqlite3_value_nochange", v.protected()))
  176. return b != 0
  177. }
  178. // FromBind returns true if value originated from a bound parameter.
  179. //
  180. // https://sqlite.org/c3ref/value_blob.html
  181. func (v Value) FromBind() bool {
  182. b := int32(v.c.call("sqlite3_value_frombind", v.protected()))
  183. return b != 0
  184. }
  185. // InFirst returns the first element
  186. // on the right-hand side of an IN constraint.
  187. //
  188. // https://sqlite.org/c3ref/vtab_in_first.html
  189. func (v Value) InFirst() (Value, error) {
  190. defer v.c.arena.mark()()
  191. valPtr := v.c.arena.new(ptrlen)
  192. rc := res_t(v.c.call("sqlite3_vtab_in_first", stk_t(v.handle), stk_t(valPtr)))
  193. if err := v.c.error(rc); err != nil {
  194. return Value{}, err
  195. }
  196. return Value{
  197. c: v.c,
  198. handle: util.Read32[ptr_t](v.c.mod, valPtr),
  199. }, nil
  200. }
  201. // InNext returns the next element
  202. // on the right-hand side of an IN constraint.
  203. //
  204. // https://sqlite.org/c3ref/vtab_in_first.html
  205. func (v Value) InNext() (Value, error) {
  206. defer v.c.arena.mark()()
  207. valPtr := v.c.arena.new(ptrlen)
  208. rc := res_t(v.c.call("sqlite3_vtab_in_next", stk_t(v.handle), stk_t(valPtr)))
  209. if err := v.c.error(rc); err != nil {
  210. return Value{}, err
  211. }
  212. return Value{
  213. c: v.c,
  214. handle: util.Read32[ptr_t](v.c.mod, valPtr),
  215. }, nil
  216. }