l.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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 DmClob struct {
  11. lob
  12. data []rune
  13. serverEncoding string
  14. }
  15. func newDmClob() *DmClob {
  16. return &DmClob{
  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. }
  33. }
  34. func newClobFromDB(value []byte, conn *DmConnection, column *column, fetchAll bool) *DmClob {
  35. var clob = newDmClob()
  36. clob.connection = conn
  37. clob.lobFlag = LOB_FLAG_CHAR
  38. clob.compatibleOracle = conn.CompatibleOracle()
  39. clob.local = false
  40. clob.updateable = !column.readonly
  41. clob.tabId = column.lobTabId
  42. clob.colId = column.lobColId
  43. clob.inRow = Dm_build_1.Dm_build_94(value, NBLOB_HEAD_IN_ROW_FLAG) == LOB_IN_ROW
  44. clob.blobId = Dm_build_1.Dm_build_108(value, NBLOB_HEAD_BLOBID)
  45. if !clob.inRow {
  46. clob.groupId = Dm_build_1.Dm_build_98(value, NBLOB_HEAD_OUTROW_GROUPID)
  47. clob.fileId = Dm_build_1.Dm_build_98(value, NBLOB_HEAD_OUTROW_FILEID)
  48. clob.pageNo = Dm_build_1.Dm_build_103(value, NBLOB_HEAD_OUTROW_PAGENO)
  49. }
  50. if conn.NewLobFlag {
  51. clob.tabId = Dm_build_1.Dm_build_103(value, NBLOB_EX_HEAD_TABLE_ID)
  52. clob.colId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_COL_ID)
  53. clob.rowId = Dm_build_1.Dm_build_108(value, NBLOB_EX_HEAD_ROW_ID)
  54. clob.exGroupId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_FPA_GRPID)
  55. clob.exFileId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_FPA_FILEID)
  56. clob.exPageNo = Dm_build_1.Dm_build_103(value, NBLOB_EX_HEAD_FPA_PAGENO)
  57. }
  58. clob.resetCurrentInfo()
  59. clob.serverEncoding = conn.getServerEncoding()
  60. if clob.inRow {
  61. if conn.NewLobFlag {
  62. clob.data = []rune(Dm_build_1.Dm_build_158(value, NBLOB_EX_HEAD_SIZE, int(clob.getLengthFromHead(value)), clob.serverEncoding, conn))
  63. } else {
  64. clob.data = []rune(Dm_build_1.Dm_build_158(value, NBLOB_INROW_HEAD_SIZE, int(clob.getLengthFromHead(value)), clob.serverEncoding, conn))
  65. }
  66. clob.length = int64(len(clob.data))
  67. } else if fetchAll {
  68. clob.loadAllData()
  69. }
  70. return clob
  71. }
  72. func newClobOfLocal(value string, conn *DmConnection) *DmClob {
  73. var clob = newDmClob()
  74. clob.connection = conn
  75. clob.lobFlag = LOB_FLAG_CHAR
  76. clob.data = []rune(value)
  77. clob.length = int64(len(clob.data))
  78. return clob
  79. }
  80. func NewClob(value string) *DmClob {
  81. var clob = newDmClob()
  82. clob.lobFlag = LOB_FLAG_CHAR
  83. clob.data = []rune(value)
  84. clob.length = int64(len(clob.data))
  85. return clob
  86. }
  87. func (clob *DmClob) ReadString(pos int, length int) (result string, err error) {
  88. if err = clob.checkValid(); err != nil {
  89. return
  90. }
  91. result, err = clob.getSubString(int64(pos), int32(length))
  92. if err != nil {
  93. return
  94. }
  95. if len(result) == 0 {
  96. err = io.EOF
  97. return
  98. }
  99. return
  100. }
  101. func (clob *DmClob) WriteString(pos int, s string) (n int, err error) {
  102. if err = clob.checkValid(); err != nil {
  103. return
  104. }
  105. if err = clob.checkFreed(); err != nil {
  106. return
  107. }
  108. if pos < 1 {
  109. err = ECGO_INVALID_LENGTH_OR_OFFSET.throw()
  110. return
  111. }
  112. if !clob.updateable {
  113. err = ECGO_RESULTSET_IS_READ_ONLY.throw()
  114. return
  115. }
  116. pos -= 1
  117. if clob.local || clob.fetchAll {
  118. if int64(pos) > clob.length {
  119. err = ECGO_INVALID_LENGTH_OR_OFFSET.throw()
  120. return
  121. }
  122. clob.setLocalData(pos, s)
  123. n = len(s)
  124. } else {
  125. if err = clob.connection.checkClosed(); err != nil {
  126. return -1, err
  127. }
  128. var writeLen, err = clob.connection.Access.dm_build_891(clob, pos, s, clob.serverEncoding)
  129. if err != nil {
  130. return -1, err
  131. }
  132. if clob.groupId == -1 {
  133. clob.setLocalData(pos, s)
  134. } else {
  135. clob.inRow = false
  136. clob.length = -1
  137. }
  138. n = writeLen
  139. }
  140. clob.modify = true
  141. return
  142. }
  143. func (clob *DmClob) Truncate(length int64) error {
  144. var err error
  145. if err = clob.checkValid(); err != nil {
  146. return err
  147. }
  148. if err = clob.checkFreed(); err != nil {
  149. return err
  150. }
  151. if length < 0 {
  152. return ECGO_INVALID_LENGTH_OR_OFFSET.throw()
  153. }
  154. if !clob.updateable {
  155. return ECGO_RESULTSET_IS_READ_ONLY.throw()
  156. }
  157. if clob.local || clob.fetchAll {
  158. if length >= int64(len(clob.data)) {
  159. return nil
  160. }
  161. clob.data = clob.data[0:length]
  162. clob.length = int64(len(clob.data))
  163. } else {
  164. if err = clob.connection.checkClosed(); err != nil {
  165. return err
  166. }
  167. clob.length, err = clob.connection.Access.dm_build_921(&clob.lob, int(length))
  168. if err != nil {
  169. return err
  170. }
  171. if clob.groupId == -1 {
  172. clob.data = clob.data[0:clob.length]
  173. }
  174. }
  175. clob.modify = true
  176. return nil
  177. }
  178. func (dest *DmClob) Scan(src interface{}) error {
  179. if dest == nil {
  180. return ECGO_STORE_IN_NIL_POINTER.throw()
  181. }
  182. switch src := src.(type) {
  183. case nil:
  184. *dest = *new(DmClob)
  185. (*dest).Valid = false
  186. return nil
  187. case string:
  188. *dest = *NewClob(src)
  189. return nil
  190. case *DmClob:
  191. *dest = *src
  192. return nil
  193. default:
  194. return UNSUPPORTED_SCAN.throw()
  195. }
  196. }
  197. func (clob DmClob) Value() (driver.Value, error) {
  198. if !clob.Valid {
  199. return nil, nil
  200. }
  201. return clob, nil
  202. }
  203. func (clob *DmClob) getSubString(pos int64, len int32) (string, error) {
  204. var err error
  205. var leaveLength int64
  206. if err = clob.checkFreed(); err != nil {
  207. return "", err
  208. }
  209. if pos < 1 || len < 0 {
  210. return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw()
  211. }
  212. pos = pos - 1
  213. if leaveLength, err = clob.GetLength(); err != nil {
  214. return "", err
  215. }
  216. if pos > leaveLength {
  217. pos = leaveLength
  218. }
  219. leaveLength -= pos
  220. if leaveLength < 0 {
  221. return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw()
  222. }
  223. if int64(len) > leaveLength {
  224. len = int32(leaveLength)
  225. }
  226. if clob.local || clob.inRow || clob.fetchAll {
  227. if pos > clob.length {
  228. return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw()
  229. }
  230. return string(clob.data[pos : pos+int64(len)]), nil
  231. } else {
  232. return clob.connection.Access.dm_build_880(clob, int32(pos), len)
  233. }
  234. }
  235. func (clob *DmClob) loadAllData() {
  236. clob.checkFreed()
  237. if clob.local || clob.inRow || clob.fetchAll {
  238. return
  239. }
  240. len, _ := clob.GetLength()
  241. s, _ := clob.getSubString(1, int32(len))
  242. clob.data = []rune(s)
  243. clob.fetchAll = true
  244. }
  245. func (clob *DmClob) setLocalData(pos int, str string) {
  246. if pos+len(str) >= int(clob.length) {
  247. clob.data = []rune(string(clob.data[0:pos]) + str)
  248. } else {
  249. clob.data = []rune(string(clob.data[0:pos]) + str + string(clob.data[pos+len(str):len(clob.data)]))
  250. }
  251. clob.length = int64(len(clob.data))
  252. }