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  }