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  }