k.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * Copyright (c) 2000-2018, 达梦数据库有限公司.
  3. * All rights reserved.
  4. */
  5. package dm
  6. import (
  7. "database/sql/driver"
  8. "io"
  9. )
  10. type DmBlob struct {
  11. lob
  12. data []byte
  13. offset int64
  14. }
  15. func newDmBlob() *DmBlob {
  16. return &DmBlob{
  17. lob: lob{
  18. inRow: true,
  19. groupId: -1,
  20. fileId: -1,
  21. pageNo: -1,
  22. readOver: false,
  23. local: true,
  24. updateable: true,
  25. length: -1,
  26. compatibleOracle: false,
  27. fetchAll: false,
  28. freed: false,
  29. modify: false,
  30. Valid: true,
  31. },
  32. offset: 1,
  33. }
  34. }
  35. func newBlobFromDB(value []byte, conn *DmConnection, column *column, fetchAll bool) *DmBlob {
  36. var blob = newDmBlob()
  37. blob.connection = conn
  38. blob.lobFlag = LOB_FLAG_BYTE
  39. blob.compatibleOracle = conn.CompatibleOracle()
  40. blob.local = false
  41. blob.updateable = !column.readonly
  42. blob.tabId = column.lobTabId
  43. blob.colId = column.lobColId
  44. blob.inRow = Dm_build_1.Dm_build_94(value, NBLOB_HEAD_IN_ROW_FLAG) == LOB_IN_ROW
  45. blob.blobId = Dm_build_1.Dm_build_108(value, NBLOB_HEAD_BLOBID)
  46. if !blob.inRow {
  47. blob.groupId = Dm_build_1.Dm_build_98(value, NBLOB_HEAD_OUTROW_GROUPID)
  48. blob.fileId = Dm_build_1.Dm_build_98(value, NBLOB_HEAD_OUTROW_FILEID)
  49. blob.pageNo = Dm_build_1.Dm_build_103(value, NBLOB_HEAD_OUTROW_PAGENO)
  50. }
  51. if conn.NewLobFlag {
  52. blob.tabId = Dm_build_1.Dm_build_103(value, NBLOB_EX_HEAD_TABLE_ID)
  53. blob.colId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_COL_ID)
  54. blob.rowId = Dm_build_1.Dm_build_108(value, NBLOB_EX_HEAD_ROW_ID)
  55. blob.exGroupId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_FPA_GRPID)
  56. blob.exFileId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_FPA_FILEID)
  57. blob.exPageNo = Dm_build_1.Dm_build_103(value, NBLOB_EX_HEAD_FPA_PAGENO)
  58. }
  59. blob.resetCurrentInfo()
  60. blob.length = blob.getLengthFromHead(value)
  61. if blob.inRow {
  62. blob.data = make([]byte, blob.length)
  63. if conn.NewLobFlag {
  64. Dm_build_1.Dm_build_57(blob.data, 0, value, NBLOB_EX_HEAD_SIZE, len(blob.data))
  65. } else {
  66. Dm_build_1.Dm_build_57(blob.data, 0, value, NBLOB_INROW_HEAD_SIZE, len(blob.data))
  67. }
  68. } else if fetchAll {
  69. blob.loadAllData()
  70. }
  71. return blob
  72. }
  73. func newBlobOfLocal(value []byte, conn *DmConnection) *DmBlob {
  74. var blob = newDmBlob()
  75. blob.connection = conn
  76. blob.lobFlag = LOB_FLAG_BYTE
  77. blob.data = value
  78. blob.length = int64(len(blob.data))
  79. return blob
  80. }
  81. func NewBlob(value []byte) *DmBlob {
  82. var blob = newDmBlob()
  83. blob.lobFlag = LOB_FLAG_BYTE
  84. blob.data = value
  85. blob.length = int64(len(blob.data))
  86. return blob
  87. }
  88. func (blob *DmBlob) Read(dest []byte) (n int, err error) {
  89. if err = blob.checkValid(); err != nil {
  90. return
  91. }
  92. result, err := blob.getBytes(blob.offset, int32(len(dest)))
  93. if err != nil {
  94. return 0, err
  95. }
  96. blob.offset += int64(len(result))
  97. copy(dest, result)
  98. if len(result) == 0 {
  99. return 0, io.EOF
  100. }
  101. return len(result), nil
  102. }
  103. func (blob *DmBlob) ReadAt(pos int, dest []byte) (n int, err error) {
  104. if err = blob.checkValid(); err != nil {
  105. return
  106. }
  107. result, err := blob.getBytes(int64(pos), int32(len(dest)))
  108. if err != nil {
  109. return 0, err
  110. }
  111. if len(result) == 0 {
  112. return 0, io.EOF
  113. }
  114. copy(dest[0:len(result)], result)
  115. return len(result), nil
  116. }
  117. func (blob *DmBlob) Write(pos int, src []byte) (n int, err error) {
  118. if err = blob.checkValid(); err != nil {
  119. return
  120. }
  121. if err = blob.checkFreed(); err != nil {
  122. return
  123. }
  124. if pos < 1 {
  125. err = ECGO_INVALID_LENGTH_OR_OFFSET.throw()
  126. return
  127. }
  128. if !blob.updateable {
  129. err = ECGO_RESULTSET_IS_READ_ONLY.throw()
  130. return
  131. }
  132. pos -= 1
  133. if blob.local || blob.fetchAll {
  134. if int64(pos) > blob.length {
  135. err = ECGO_INVALID_LENGTH_OR_OFFSET.throw()
  136. return
  137. }
  138. blob.setLocalData(pos, src)
  139. n = len(src)
  140. } else {
  141. if err = blob.connection.checkClosed(); err != nil {
  142. return -1, err
  143. }
  144. var writeLen, err = blob.connection.Access.dm_build_907(blob, pos, src)
  145. if err != nil {
  146. return -1, err
  147. }
  148. if blob.groupId == -1 {
  149. blob.setLocalData(pos, src)
  150. } else {
  151. blob.inRow = false
  152. blob.length = -1
  153. }
  154. n = writeLen
  155. }
  156. blob.modify = true
  157. return
  158. }
  159. func (blob *DmBlob) Truncate(length int64) error {
  160. var err error
  161. if err = blob.checkValid(); err != nil {
  162. return err
  163. }
  164. if err = blob.checkFreed(); err != nil {
  165. return err
  166. }
  167. if length < 0 {
  168. return ECGO_INVALID_LENGTH_OR_OFFSET.throw()
  169. }
  170. if !blob.updateable {
  171. return ECGO_RESULTSET_IS_READ_ONLY.throw()
  172. }
  173. if blob.local || blob.fetchAll {
  174. if length >= int64(len(blob.data)) {
  175. return nil
  176. }
  177. tmp := make([]byte, length)
  178. Dm_build_1.Dm_build_57(tmp, 0, blob.data, 0, len(tmp))
  179. blob.data = tmp
  180. blob.length = int64(len(tmp))
  181. } else {
  182. if err = blob.connection.checkClosed(); err != nil {
  183. return err
  184. }
  185. blob.length, err = blob.connection.Access.dm_build_921(&blob.lob, int(length))
  186. if err != nil {
  187. return err
  188. }
  189. if blob.groupId == -1 {
  190. tmp := make([]byte, blob.length)
  191. Dm_build_1.Dm_build_57(tmp, 0, blob.data, 0, int(blob.length))
  192. blob.data = tmp
  193. }
  194. }
  195. blob.modify = true
  196. return nil
  197. }
  198. func (dest *DmBlob) Scan(src interface{}) error {
  199. if dest == nil {
  200. return ECGO_STORE_IN_NIL_POINTER.throw()
  201. }
  202. switch src := src.(type) {
  203. case nil:
  204. *dest = *new(DmBlob)
  205. (*dest).Valid = false
  206. return nil
  207. case []byte:
  208. *dest = *NewBlob(src)
  209. return nil
  210. case *DmBlob:
  211. *dest = *src
  212. return nil
  213. default:
  214. return UNSUPPORTED_SCAN.throw()
  215. }
  216. }
  217. func (blob DmBlob) Value() (driver.Value, error) {
  218. if !blob.Valid {
  219. return nil, nil
  220. }
  221. return blob, nil
  222. }
  223. func (blob *DmBlob) getBytes(pos int64, length int32) ([]byte, error) {
  224. var err error
  225. var leaveLength int64
  226. if err = blob.checkFreed(); err != nil {
  227. return nil, err
  228. }
  229. if pos < 1 || length < 0 {
  230. return nil, ECGO_INVALID_LENGTH_OR_OFFSET.throw()
  231. }
  232. pos = pos - 1
  233. if leaveLength, err = blob.GetLength(); err != nil {
  234. return nil, err
  235. }
  236. leaveLength -= pos
  237. if leaveLength < 0 {
  238. return nil, ECGO_INVALID_LENGTH_OR_OFFSET.throw()
  239. }
  240. if int64(length) > leaveLength {
  241. length = int32(leaveLength)
  242. }
  243. if blob.local || blob.inRow || blob.fetchAll {
  244. return blob.data[pos : pos+int64(length)], nil
  245. } else {
  246. return blob.connection.Access.dm_build_870(blob, int32(pos), length)
  247. }
  248. }
  249. func (blob *DmBlob) loadAllData() {
  250. blob.checkFreed()
  251. if blob.local || blob.inRow || blob.fetchAll {
  252. return
  253. }
  254. len, _ := blob.GetLength()
  255. blob.data, _ = blob.getBytes(1, int32(len))
  256. blob.fetchAll = true
  257. }
  258. func (blob *DmBlob) setLocalData(pos int, p []byte) {
  259. if pos+len(p) >= int(blob.length) {
  260. var tmp = make([]byte, pos+len(p))
  261. Dm_build_1.Dm_build_57(tmp, 0, blob.data, 0, pos)
  262. Dm_build_1.Dm_build_57(tmp, pos, p, 0, len(p))
  263. blob.data = tmp
  264. } else {
  265. Dm_build_1.Dm_build_57(blob.data, pos, p, 0, len(p))
  266. }
  267. blob.length = int64(len(blob.data))
  268. }