github.com/wanlay/gorm-dm8@v1.0.5/dmr/zzn.go (about) 1 /* 2 * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 * All rights reserved. 4 */ 5 package dmr 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 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 CHAR, VARCHAR, VARCHAR2: 210 parameter.prec = VARCHAR_PREC 211 case CLOB: 212 parameter.prec = CLOB_PREC 213 case BINARY, VARBINARY: 214 parameter.prec = VARBINARY_PREC 215 case BLOB: 216 parameter.prec = BLOB_PREC 217 case BOOLEAN, BIT: 218 parameter.prec = BIT_PREC 219 } 220 } 221 222 return true 223 } 224 225 func isBFile(colType int, prec int, scale int) bool { 226 return colType == VARCHAR && prec == BFILE_PREC && scale == BFILE_SCALE 227 } 228 229 func isComplexType(colType int, scale int) bool { 230 return (colType == BLOB && scale == COMPLEX_SCALE) || colType == ARRAY || colType == SARRAY || colType == CLASS || colType == PLTYPE_RECORD 231 } 232 233 func isLocalTimeZone(colType int, scale int) bool { 234 return colType == DATETIME && (scale&LOCAL_TIME_ZONE_SCALE_MASK) != 0 235 } 236 237 func getLocalTimeZoneScale(colType int, scale int) int { 238 return scale & (^LOCAL_TIME_ZONE_SCALE_MASK) 239 } 240 241 func isFloat(colType int, scale int) bool { 242 return colType == DECIMAL && scale == FLOAT_SCALE_MASK 243 } 244 245 func getFloatPrec(prec int) int { 246 return int(math.Round(float64(prec)*0.30103)) + 1 247 } 248 249 func getFloatScale(scale int) int { 250 return scale & (^FLOAT_SCALE_MASK) 251 } 252 253 var ( 254 scanTypeFloat32 = reflect.TypeOf(float32(0)) 255 scanTypeFloat64 = reflect.TypeOf(float64(0)) 256 scanTypeBool = reflect.TypeOf(false) 257 scanTypeInt8 = reflect.TypeOf(int8(0)) 258 scanTypeInt16 = reflect.TypeOf(int16(0)) 259 scanTypeInt32 = reflect.TypeOf(int32(0)) 260 scanTypeInt64 = reflect.TypeOf(int64(0)) 261 scanTypeNullBool = reflect.TypeOf(sql.NullBool{}) 262 scanTypeNullFloat = reflect.TypeOf(sql.NullFloat64{}) 263 scanTypeNullInt = reflect.TypeOf(sql.NullInt64{}) 264 scanTypeNullString = reflect.TypeOf(sql.NullString{}) 265 scanTypeNullTime = reflect.TypeOf(sql.NullTime{}) 266 scanTypeRawBytes = reflect.TypeOf(sql.RawBytes{}) 267 scanTypeString = reflect.TypeOf("") 268 scanTypeTime = reflect.TypeOf(time.Now()) 269 scanTypeUnknown = reflect.TypeOf(new(interface{})) 270 ) 271 272 func (column *column) ScanType() reflect.Type { 273 274 switch column.colType { 275 case BOOLEAN: 276 if column.nullable { 277 return scanTypeNullBool 278 } 279 280 return scanTypeBool 281 282 case BIT: 283 if strings.ToLower(column.typeName) == "boolean" { 284 285 if column.nullable { 286 return scanTypeNullBool 287 } 288 289 return scanTypeBool 290 } else { 291 292 if column.nullable { 293 return scanTypeNullInt 294 } 295 return scanTypeInt8 296 } 297 298 case TINYINT: 299 if column.nullable { 300 return scanTypeNullInt 301 } 302 return scanTypeInt8 303 304 case SMALLINT: 305 if column.nullable { 306 return scanTypeNullInt 307 } 308 return scanTypeInt16 309 310 case INT: 311 if column.nullable { 312 return scanTypeNullInt 313 } 314 315 return scanTypeInt32 316 317 case BIGINT: 318 if column.nullable { 319 return scanTypeNullInt 320 } 321 return scanTypeInt64 322 323 case REAL: 324 if column.nullable { 325 return scanTypeNullFloat 326 } 327 328 return scanTypeFloat32 329 330 case DOUBLE: 331 332 if strings.ToLower(column.typeName) == "float" { 333 if column.nullable { 334 return scanTypeNullFloat 335 } 336 337 return scanTypeFloat32 338 } 339 340 if column.nullable { 341 return scanTypeNullFloat 342 } 343 344 return scanTypeFloat64 345 case DATE, TIME, DATETIME: 346 if column.nullable { 347 return scanTypeNullTime 348 } 349 350 return scanTypeTime 351 352 case DECIMAL, BINARY, VARBINARY, BLOB: 353 return scanTypeRawBytes 354 355 case CHAR, VARCHAR2, VARCHAR, CLOB: 356 if column.nullable { 357 return scanTypeNullString 358 } 359 return scanTypeString 360 } 361 362 return scanTypeUnknown 363 } 364 365 func (column *column) Length() (length int64, ok bool) { 366 367 switch column.colType { 368 case BINARY: 369 case VARBINARY: 370 case BLOB: 371 case CHAR: 372 case VARCHAR2: 373 case VARCHAR: 374 case CLOB: 375 return int64(column.prec), true 376 } 377 378 return int64(0), false 379 } 380 381 func (column *column) PrecisionScale() (precision, scale int64, ok bool) { 382 switch column.colType { 383 case DECIMAL: 384 return int64(column.prec), int64(column.scale), true 385 } 386 387 return int64(0), int64(0), false 388 } 389 390 func (column *column) getColumnData(bytes []byte, conn *DmConnection) (driver.Value, error) { 391 if bytes == nil { 392 return nil, nil 393 } 394 395 switch column.colType { 396 case BOOLEAN: 397 return bytes[0] != 0, nil 398 case BIT: 399 if strings.ToLower(column.typeName) == "boolean" { 400 return bytes[0] != 0, nil 401 } 402 403 return int8(bytes[0]), nil 404 case TINYINT: 405 return int8(bytes[0]), nil 406 case SMALLINT: 407 return Dm_build_1220.Dm_build_1317(bytes, 0), nil 408 case INT: 409 return Dm_build_1220.Dm_build_1322(bytes, 0), nil 410 case BIGINT: 411 return Dm_build_1220.Dm_build_1327(bytes, 0), nil 412 case REAL: 413 return Dm_build_1220.Dm_build_1332(bytes, 0), nil 414 case DOUBLE: 415 416 return Dm_build_1220.Dm_build_1336(bytes, 0), nil 417 case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ: 418 return DB2G.toTime(bytes, column, conn) 419 case INTERVAL_DT: 420 return newDmIntervalDTByBytes(bytes).String(), nil 421 case INTERVAL_YM: 422 return newDmIntervalYMByBytes(bytes).String(), nil 423 case DECIMAL: 424 tmp, err := DB2G.toDmDecimal(bytes, column, conn) 425 if err != nil { 426 return nil, err 427 } 428 return tmp.String(), nil 429 430 case BINARY, VARBINARY: 431 return bytes, nil 432 case BLOB: 433 return DB2G.toDmBlob(bytes, column, conn), nil 434 case CHAR, VARCHAR2, VARCHAR: 435 return Dm_build_1220.Dm_build_1377(bytes, 0, len(bytes), conn.getServerEncoding(), conn), nil 436 case CLOB: 437 return DB2G.toDmClob(bytes, conn, column), nil 438 } 439 440 return string(bytes), nil 441 } 442 443 func emptyStringToNil(t int32) bool { 444 switch t { 445 case BOOLEAN, BIT, TINYINT, SMALLINT, INT, BIGINT, REAL, DOUBLE, DECIMAL, 446 DATE, TIME, DATETIME, INTERVAL_DT, INTERVAL_YM, TIME_TZ, DATETIME_TZ: 447 return true 448 default: 449 return false 450 } 451 }