github.com/xiyichan/dm8@v0.0.0-20211213021639-be727be3e136/zzm.go (about) 1 /* 2 * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 * All rights reserved. 4 */ 5 package dm 6 7 import ( 8 "database/sql" 9 "database/sql/driver" 10 "math" 11 "reflect" 12 "strings" 13 "time" 14 ) 15 16 const ( 17 INT8_MAX int8 = math.MaxInt8 18 19 INT8_MIN int8 = math.MinInt8 20 21 BYTE_MAX byte = math.MaxUint8 22 23 BYTE_MIN byte = 0 24 25 INT16_MAX int16 = math.MaxInt16 26 27 INT16_MIN int16 = math.MinInt16 28 29 UINT16_MAX uint16 = math.MaxUint16 30 31 UINT16_MIN uint16 = 0 32 33 INT32_MAX int32 = math.MaxInt32 34 35 INT32_MIN int32 = math.MinInt32 36 37 UINT32_MAX uint32 = math.MaxUint32 38 39 UINT32_MIN uint32 = 0 40 41 INT64_MAX int64 = math.MaxInt64 42 43 INT64_MIN int64 = math.MinInt64 44 45 UINT64_MAX uint64 = math.MaxUint64 46 47 UINT64_MIN uint64 = 0 48 49 FLOAT32_MAX float32 = 3.4e+38 50 51 FLOAT32_MIN float32 = -3.4e+38 52 53 BYTE_SIZE = 1 54 55 USINT_SIZE = 2 56 57 ULINT_SIZE = 4 58 59 DDWORD_SIZE = 8 60 61 LINT64_SIZE = 8 62 63 CHAR = 0 64 65 VARCHAR2 = 1 66 67 VARCHAR = 2 68 69 BIT = 3 70 71 TINYINT = 5 72 73 SMALLINT = 6 74 75 INT = 7 76 77 BIGINT = 8 78 79 DECIMAL = 9 80 81 REAL = 10 82 83 DOUBLE = 11 84 85 BLOB = 12 86 87 BOOLEAN = 13 88 89 DATE = 14 90 91 TIME = 15 92 93 DATETIME = 16 94 95 BINARY = 17 96 97 VARBINARY = 18 98 99 CLOB = 19 100 101 INTERVAL_YM = 20 102 103 INTERVAL_DT = 21 104 105 TIME_TZ = 22 106 107 DATETIME_TZ = 23 108 109 NULL = 25 110 111 ANY = 31 112 113 STAR_ALL = 32 114 115 STAR = 33 116 117 RECORD = 40 118 119 TYPE = 41 120 121 TYPE_REF = 42 122 123 UNKNOWN = 54 124 125 ARRAY = 117 126 127 CLASS = 119 128 129 CURSOR = 120 130 131 PLTYPE_RECORD = 121 132 133 SARRAY = 122 134 135 CURSOR_ORACLE = -10 136 137 BIT_PREC = BYTE_SIZE 138 139 TINYINT_PREC = BYTE_SIZE 140 141 SMALLINT_PREC = USINT_SIZE 142 143 INT_PREC = ULINT_SIZE 144 145 BIGINT_PREC = LINT64_SIZE 146 147 REAL_PREC = 4 148 149 DOUBLE_PREC = 8 150 151 DATE_PREC = 3 152 153 TIME_PREC = 5 154 155 DATETIME_PREC = 8 156 157 INTERVAL_YM_PREC = 3 * ULINT_SIZE 158 159 INTERVAL_DT_PREC = 6 * ULINT_SIZE 160 161 TIME_TZ_PREC = 12 162 163 DATETIME_TZ_PREC = 12 164 165 VARCHAR_PREC = 8188 166 167 VARBINARY_PREC = 8188 168 169 BLOB_PREC int32 = INT32_MAX 170 171 CLOB_PREC int32 = INT32_MAX 172 173 NULL_PREC = 0 174 175 LOCAL_TIME_ZONE_SCALE_MASK = 0x00001000 176 177 BFILE_PREC = 512 178 179 BFILE_SCALE = 6 180 181 COMPLEX_SCALE = 5 182 183 CURRENCY_PREC = 19 184 185 CURRENCY_SCALE = 4 186 ) 187 188 func resetColType(stmt *DmStatement, i int, colType int32) bool { 189 190 parameter := &stmt.params[i] 191 192 if parameter.ioType == IO_TYPE_OUT { 193 stmt.curRowBindIndicator[i] |= BIND_OUT 194 return false 195 } else if parameter.ioType == IO_TYPE_IN { 196 stmt.curRowBindIndicator[i] |= BIND_IN 197 } else { 198 stmt.curRowBindIndicator[i] |= BIND_IN 199 stmt.curRowBindIndicator[i] |= BIND_OUT 200 } 201 202 if parameter.typeFlag != TYPE_FLAG_EXACT { 203 204 parameter.colType = colType 205 parameter.scale = 0 206 switch colType { 207 case CHAR, VARCHAR, VARCHAR2: 208 parameter.prec = VARCHAR_PREC 209 case CLOB: 210 parameter.prec = CLOB_PREC 211 case BINARY, VARBINARY: 212 parameter.prec = VARBINARY_PREC 213 case BLOB: 214 parameter.prec = BLOB_PREC 215 case BOOLEAN, BIT: 216 parameter.prec = BIT_PREC 217 } 218 } 219 220 return true 221 } 222 223 func isBFile(colType int, prec int, scale int) bool { 224 return colType == VARCHAR && prec == BFILE_PREC && scale == BFILE_SCALE 225 } 226 227 func isComplexType(colType int, scale int) bool { 228 return (colType == BLOB && scale == COMPLEX_SCALE) || colType == ARRAY || colType == SARRAY || colType == CLASS || colType == PLTYPE_RECORD 229 } 230 231 func isLocalTimeZone(colType int, scale int) bool { 232 return colType == DATETIME && (scale&LOCAL_TIME_ZONE_SCALE_MASK) != 0 233 } 234 235 func getLocalTimeZoneScale(colType int, scale int) int { 236 return scale & (^LOCAL_TIME_ZONE_SCALE_MASK) 237 } 238 239 var ( 240 scanTypeFloat32 = reflect.TypeOf(float32(0)) 241 scanTypeFloat64 = reflect.TypeOf(float64(0)) 242 scanTypeBool = reflect.TypeOf(false) 243 scanTypeInt8 = reflect.TypeOf(int8(0)) 244 scanTypeInt16 = reflect.TypeOf(int16(0)) 245 scanTypeInt32 = reflect.TypeOf(int32(0)) 246 scanTypeInt64 = reflect.TypeOf(int64(0)) 247 scanTypeNullBool = reflect.TypeOf(sql.NullBool{}) 248 scanTypeNullFloat = reflect.TypeOf(sql.NullFloat64{}) 249 scanTypeNullInt = reflect.TypeOf(sql.NullInt64{}) 250 scanTypeNullString = reflect.TypeOf(sql.NullString{}) 251 scanTypeNullTime = reflect.TypeOf(sql.NullTime{}) 252 scanTypeRawBytes = reflect.TypeOf(sql.RawBytes{}) 253 scanTypeString = reflect.TypeOf("") 254 scanTypeTime = reflect.TypeOf(time.Now()) 255 scanTypeUnknown = reflect.TypeOf(new(interface{})) 256 ) 257 258 func (column *column) ScanType() reflect.Type { 259 260 switch column.colType { 261 case BOOLEAN: 262 if column.nullable { 263 return scanTypeNullBool 264 } 265 266 return scanTypeBool 267 268 case BIT: 269 if strings.ToLower(column.typeName) == "boolean" { 270 271 if column.nullable { 272 return scanTypeNullBool 273 } 274 275 return scanTypeBool 276 } else { 277 278 if column.nullable { 279 return scanTypeNullInt 280 } 281 return scanTypeInt8 282 } 283 284 case TINYINT: 285 if column.nullable { 286 return scanTypeNullInt 287 } 288 return scanTypeInt8 289 290 case SMALLINT: 291 if column.nullable { 292 return scanTypeNullInt 293 } 294 return scanTypeInt16 295 296 case INT: 297 if column.nullable { 298 return scanTypeNullInt 299 } 300 301 return scanTypeInt32 302 303 case BIGINT: 304 if column.nullable { 305 return scanTypeNullInt 306 } 307 return scanTypeInt64 308 309 case REAL: 310 if column.nullable { 311 return scanTypeNullFloat 312 } 313 314 return scanTypeFloat32 315 316 case DOUBLE: 317 318 if strings.ToLower(column.typeName) == "float" { 319 if column.nullable { 320 return scanTypeNullFloat 321 } 322 323 return scanTypeFloat32 324 } 325 326 if column.nullable { 327 return scanTypeNullFloat 328 } 329 330 return scanTypeFloat64 331 case DATE, TIME, DATETIME: 332 if column.nullable { 333 return scanTypeNullTime 334 } 335 336 return scanTypeTime 337 338 case DECIMAL, BINARY, VARBINARY, BLOB: 339 return scanTypeRawBytes 340 341 case CHAR, VARCHAR2, VARCHAR, CLOB: 342 if column.nullable { 343 return scanTypeNullString 344 } 345 return scanTypeString 346 } 347 348 return scanTypeUnknown 349 } 350 351 func (column *column) Length() (length int64, ok bool) { 352 353 switch column.colType { 354 case BINARY: 355 case VARBINARY: 356 case BLOB: 357 case CHAR: 358 case VARCHAR2: 359 case VARCHAR: 360 case CLOB: 361 return int64(column.prec), true 362 } 363 364 return int64(0), false 365 } 366 367 func (column *column) PrecisionScale() (precision, scale int64, ok bool) { 368 switch column.colType { 369 case DECIMAL: 370 return int64(column.prec), int64(column.scale), true 371 } 372 373 return int64(0), int64(0), false 374 } 375 376 func (column *column) getColumnData(bytes []byte, conn *DmConnection) (driver.Value, error) { 377 if bytes == nil { 378 return nil, nil 379 } 380 381 switch column.colType { 382 case BOOLEAN: 383 return bytes[0] != 0, nil 384 case BIT: 385 if strings.ToLower(column.typeName) == "boolean" { 386 return bytes[0] != 0, nil 387 } 388 389 return int8(bytes[0]), nil 390 case TINYINT: 391 return int8(bytes[0]), nil 392 case SMALLINT: 393 return Dm_build_599.Dm_build_696(bytes, 0), nil 394 case INT: 395 return Dm_build_599.Dm_build_701(bytes, 0), nil 396 case BIGINT: 397 return Dm_build_599.Dm_build_706(bytes, 0), nil 398 case REAL: 399 return Dm_build_599.Dm_build_711(bytes, 0), nil 400 case DOUBLE: 401 402 return Dm_build_599.Dm_build_715(bytes, 0), nil 403 case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ: 404 return DB2G.toTime(bytes, column, conn) 405 case INTERVAL_DT: 406 return newDmIntervalDTByBytes(bytes).String(), nil 407 case INTERVAL_YM: 408 return newDmIntervalYMByBytes(bytes).String(), nil 409 case DECIMAL: 410 tmp, err := DB2G.toDmDecimal(bytes, column, conn) 411 if err != nil { 412 return nil, err 413 } 414 return tmp.ToBigFloat().Text('f', -1), nil 415 case BINARY, VARBINARY: 416 return bytes, nil 417 case BLOB: 418 return DB2G.toDmBlob(bytes, column, conn), nil 419 case CHAR, VARCHAR2, VARCHAR: 420 return Dm_build_599.Dm_build_753(bytes, 0, len(bytes), conn.getServerEncoding(), conn), nil 421 case CLOB: 422 return DB2G.toDmClob(bytes, conn, column), nil 423 } 424 425 return string(bytes), nil 426 } 427 428 func emptyStringToNil(t int32) bool { 429 switch t { 430 case BOOLEAN, BIT, TINYINT, SMALLINT, INT, BIGINT, REAL, DOUBLE, DECIMAL, 431 DATE, TIME, DATETIME, INTERVAL_DT, INTERVAL_YM, TIME_TZ, DATETIME_TZ: 432 return true 433 default: 434 return false 435 } 436 }