gitee.com/curryzheng/dm@v0.0.1/zzo.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 = 7 162 163 DATETIME_TZ_PREC = 10 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 FLOAT_SCALE_MASK = 0x81 188 ) 189 190 func resetColType(stmt *DmStatement, i int, colType int32) bool { 191 192 parameter := &stmt.params[i] 193 194 if parameter.ioType == IO_TYPE_OUT { 195 stmt.curRowBindIndicator[i] |= BIND_OUT 196 return false 197 } else if parameter.ioType == IO_TYPE_IN { 198 stmt.curRowBindIndicator[i] |= BIND_IN 199 } else { 200 stmt.curRowBindIndicator[i] |= BIND_IN 201 stmt.curRowBindIndicator[i] |= BIND_OUT 202 } 203 204 if parameter.typeFlag != TYPE_FLAG_EXACT { 205 206 parameter.colType = colType 207 parameter.scale = 0 208 switch colType { 209 case BOOLEAN, BIT: 210 parameter.prec = BIT_PREC 211 case TINYINT: 212 parameter.prec = TINYINT_PREC 213 case SMALLINT: 214 parameter.prec = SMALLINT_PREC 215 case INT: 216 parameter.prec = INT_PREC 217 case BIGINT: 218 parameter.prec = BIGINT_PREC 219 case CHAR, VARCHAR, VARCHAR2: 220 parameter.prec = VARCHAR_PREC 221 case CLOB: 222 parameter.prec = CLOB_PREC 223 case BINARY, VARBINARY: 224 parameter.prec = VARBINARY_PREC 225 case BLOB: 226 parameter.prec = BLOB_PREC 227 case DATE: 228 parameter.prec = DATE_PREC 229 case TIME: 230 parameter.prec = TIME_PREC 231 parameter.scale = 6 232 case TIME_TZ: 233 parameter.prec = TIME_TZ_PREC 234 parameter.scale = 6 235 case DATETIME: 236 parameter.prec = DATETIME_PREC 237 parameter.scale = 6 238 case DATETIME_TZ: 239 parameter.prec = DATETIME_TZ_PREC 240 parameter.scale = 6 241 case REAL, DOUBLE, DECIMAL, INTERVAL_YM, INTERVAL_DT, ARRAY, CLASS, PLTYPE_RECORD, SARRAY: 242 parameter.prec = 0 243 case UNKNOWN, NULL: 244 parameter.colType = VARCHAR 245 parameter.prec = VARCHAR_PREC 246 } 247 } 248 249 return true 250 } 251 252 func isBFile(colType int, prec int, scale int) bool { 253 return colType == VARCHAR && prec == BFILE_PREC && scale == BFILE_SCALE 254 } 255 256 func isComplexType(colType int, scale int) bool { 257 return (colType == BLOB && scale == COMPLEX_SCALE) || colType == ARRAY || colType == SARRAY || colType == CLASS || colType == PLTYPE_RECORD 258 } 259 260 func isLocalTimeZone(colType int, scale int) bool { 261 return colType == DATETIME && (scale&LOCAL_TIME_ZONE_SCALE_MASK) != 0 262 } 263 264 func getLocalTimeZoneScale(colType int, scale int) int { 265 return scale & (^LOCAL_TIME_ZONE_SCALE_MASK) 266 } 267 268 func isFloat(colType int, scale int) bool { 269 return colType == DECIMAL && scale == FLOAT_SCALE_MASK 270 } 271 272 func getFloatPrec(prec int) int { 273 return int(math.Round(float64(prec)*0.30103)) + 1 274 } 275 276 func getFloatScale(scale int) int { 277 return scale & (^FLOAT_SCALE_MASK) 278 } 279 280 var ( 281 scanTypeFloat32 = reflect.TypeOf(float32(0)) 282 scanTypeFloat64 = reflect.TypeOf(float64(0)) 283 scanTypeBool = reflect.TypeOf(false) 284 scanTypeInt8 = reflect.TypeOf(int8(0)) 285 scanTypeInt16 = reflect.TypeOf(int16(0)) 286 scanTypeInt32 = reflect.TypeOf(int32(0)) 287 scanTypeInt64 = reflect.TypeOf(int64(0)) 288 scanTypeNullBool = reflect.TypeOf(sql.NullBool{}) 289 scanTypeNullFloat = reflect.TypeOf(sql.NullFloat64{}) 290 scanTypeNullInt = reflect.TypeOf(sql.NullInt64{}) 291 scanTypeNullString = reflect.TypeOf(sql.NullString{}) 292 scanTypeNullTime = reflect.TypeOf(sql.NullTime{}) 293 scanTypeRawBytes = reflect.TypeOf(sql.RawBytes{}) 294 scanTypeString = reflect.TypeOf("") 295 scanTypeTime = reflect.TypeOf(time.Now()) 296 scanTypeUnknown = reflect.TypeOf(new(interface{})) 297 ) 298 299 func (column *column) ScanType() reflect.Type { 300 301 switch column.colType { 302 case BOOLEAN: 303 if column.nullable { 304 return scanTypeNullBool 305 } 306 307 return scanTypeBool 308 309 case BIT: 310 if strings.ToLower(column.typeName) == "boolean" { 311 312 if column.nullable { 313 return scanTypeNullBool 314 } 315 316 return scanTypeBool 317 } else { 318 319 if column.nullable { 320 return scanTypeNullInt 321 } 322 return scanTypeInt8 323 } 324 325 case TINYINT: 326 if column.nullable { 327 return scanTypeNullInt 328 } 329 return scanTypeInt8 330 331 case SMALLINT: 332 if column.nullable { 333 return scanTypeNullInt 334 } 335 return scanTypeInt16 336 337 case INT: 338 if column.nullable { 339 return scanTypeNullInt 340 } 341 342 return scanTypeInt32 343 344 case BIGINT: 345 if column.nullable { 346 return scanTypeNullInt 347 } 348 return scanTypeInt64 349 350 case REAL: 351 if column.nullable { 352 return scanTypeNullFloat 353 } 354 355 return scanTypeFloat32 356 357 case DOUBLE: 358 359 if strings.ToLower(column.typeName) == "float" { 360 if column.nullable { 361 return scanTypeNullFloat 362 } 363 364 return scanTypeFloat32 365 } 366 367 if column.nullable { 368 return scanTypeNullFloat 369 } 370 371 return scanTypeFloat64 372 case DATE, TIME, DATETIME: 373 if column.nullable { 374 return scanTypeNullTime 375 } 376 377 return scanTypeTime 378 379 case DECIMAL, BINARY, VARBINARY, BLOB: 380 return scanTypeRawBytes 381 382 case CHAR, VARCHAR2, VARCHAR, CLOB: 383 if column.nullable { 384 return scanTypeNullString 385 } 386 return scanTypeString 387 } 388 389 return scanTypeUnknown 390 } 391 392 func (column *column) Length() (length int64, ok bool) { 393 394 switch column.colType { 395 case BINARY: 396 case VARBINARY: 397 case BLOB: 398 case CHAR: 399 case VARCHAR2: 400 case VARCHAR: 401 case CLOB: 402 return int64(column.prec), true 403 } 404 405 return int64(0), false 406 } 407 408 func (column *column) PrecisionScale() (precision, scale int64, ok bool) { 409 switch column.colType { 410 case DECIMAL: 411 return int64(column.prec), int64(column.scale), true 412 } 413 414 return int64(0), int64(0), false 415 } 416 417 func (column *column) getColumnData(bytes []byte, conn *DmConnection) (driver.Value, error) { 418 if bytes == nil { 419 return nil, nil 420 } 421 422 switch column.colType { 423 case BOOLEAN: 424 return bytes[0] != 0, nil 425 case BIT: 426 if strings.ToLower(column.typeName) == "boolean" { 427 return bytes[0] != 0, nil 428 } 429 430 return int8(bytes[0]), nil 431 case TINYINT: 432 return int8(bytes[0]), nil 433 case SMALLINT: 434 return Dm_build_1.Dm_build_98(bytes, 0), nil 435 case INT: 436 return Dm_build_1.Dm_build_103(bytes, 0), nil 437 case BIGINT: 438 return Dm_build_1.Dm_build_108(bytes, 0), nil 439 case REAL: 440 return Dm_build_1.Dm_build_113(bytes, 0), nil 441 case DOUBLE: 442 443 return Dm_build_1.Dm_build_117(bytes, 0), nil 444 case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ: 445 return DB2G.toTime(bytes, column, conn) 446 case INTERVAL_DT: 447 return newDmIntervalDTByBytes(bytes).String(), nil 448 case INTERVAL_YM: 449 return newDmIntervalYMByBytes(bytes).String(), nil 450 case DECIMAL: 451 tmp, err := DB2G.toDmDecimal(bytes, column, conn) 452 if err != nil { 453 return nil, err 454 } 455 return tmp.String(), nil 456 457 case BINARY, VARBINARY: 458 return bytes, nil 459 case BLOB: 460 blob := DB2G.toDmBlob(bytes, column, conn) 461 if conn.CompatibleMysql() { 462 l, err := blob.GetLength() 463 if err != nil { 464 return nil, err 465 } 466 return blob.getBytes(1, int32(l)) 467 } 468 return blob, nil 469 case CHAR, VARCHAR2, VARCHAR: 470 return Dm_build_1.Dm_build_158(bytes, 0, len(bytes), conn.getServerEncoding(), conn), nil 471 case CLOB: 472 clob := DB2G.toDmClob(bytes, conn, column) 473 if conn.CompatibleMysql() { 474 l, err := clob.GetLength() 475 if err != nil { 476 return nil, err 477 } 478 return clob.getSubString(1, int32(l)) 479 } 480 return clob, nil 481 } 482 483 return string(bytes), nil 484 } 485 486 func emptyStringToNil(t int32) bool { 487 switch t { 488 case BOOLEAN, BIT, TINYINT, SMALLINT, INT, BIGINT, REAL, DOUBLE, DECIMAL, 489 DATE, TIME, DATETIME, INTERVAL_DT, INTERVAL_YM, TIME_TZ, DATETIME_TZ: 490 return true 491 default: 492 return false 493 } 494 }