github.com/nakagami/firebirdsql@v0.9.10/xsqlvar.go (about)

     1  /*******************************************************************************
     2  The MIT License (MIT)
     3  
     4  Copyright (c) 2013-2020 Hajime Nakagami
     5  
     6  Permission is hereby granted, free of charge, to any person obtaining a copy of
     7  this software and associated documentation files (the "Software"), to deal in
     8  the Software without restriction, including without limitation the rights to
     9  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
    10  the Software, and to permit persons to whom the Software is furnished to do so,
    11  subject to the following conditions:
    12  
    13  The above copyright notice and this permission notice shall be included in all
    14  copies or substantial portions of the Software.
    15  
    16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
    18  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
    19  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    20  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    21  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    22  *******************************************************************************/
    23  
    24  package firebirdsql
    25  
    26  import (
    27  	"bytes"
    28  	"encoding/binary"
    29  	"github.com/shopspring/decimal"
    30  	"golang.org/x/text/encoding/charmap"
    31  	"golang.org/x/text/encoding/japanese"
    32  	"golang.org/x/text/encoding/korean"
    33  	"golang.org/x/text/encoding/simplifiedchinese"
    34  	"golang.org/x/text/encoding/traditionalchinese"
    35  	"math"
    36  	"math/big"
    37  	"reflect"
    38  	"strings"
    39  	"time"
    40  )
    41  
    42  const (
    43  	SQL_TYPE_TEXT         = 452
    44  	SQL_TYPE_VARYING      = 448
    45  	SQL_TYPE_SHORT        = 500
    46  	SQL_TYPE_LONG         = 496
    47  	SQL_TYPE_FLOAT        = 482
    48  	SQL_TYPE_DOUBLE       = 480
    49  	SQL_TYPE_D_FLOAT      = 530
    50  	SQL_TYPE_TIMESTAMP    = 510
    51  	SQL_TYPE_BLOB         = 520
    52  	SQL_TYPE_ARRAY        = 540
    53  	SQL_TYPE_QUAD         = 550
    54  	SQL_TYPE_TIME         = 560
    55  	SQL_TYPE_DATE         = 570
    56  	SQL_TYPE_INT64        = 580
    57  	SQL_TYPE_INT128       = 32752
    58  	SQL_TYPE_TIMESTAMP_TZ = 32754
    59  	SQL_TYPE_TIME_TZ      = 32756
    60  	SQL_TYPE_DEC_FIXED    = 32758
    61  	SQL_TYPE_DEC64        = 32760
    62  	SQL_TYPE_DEC128       = 32762
    63  	SQL_TYPE_BOOLEAN      = 32764
    64  	SQL_TYPE_NULL         = 32766
    65  )
    66  
    67  var xsqlvarTypeLength = map[int]int{
    68  	SQL_TYPE_TEXT:         -1,
    69  	SQL_TYPE_VARYING:      -1,
    70  	SQL_TYPE_SHORT:        4,
    71  	SQL_TYPE_LONG:         4,
    72  	SQL_TYPE_FLOAT:        4,
    73  	SQL_TYPE_TIME:         4,
    74  	SQL_TYPE_DATE:         4,
    75  	SQL_TYPE_DOUBLE:       8,
    76  	SQL_TYPE_TIMESTAMP:    8,
    77  	SQL_TYPE_BLOB:         8,
    78  	SQL_TYPE_ARRAY:        8,
    79  	SQL_TYPE_QUAD:         8,
    80  	SQL_TYPE_INT64:        8,
    81  	SQL_TYPE_INT128:       16,
    82  	SQL_TYPE_TIMESTAMP_TZ: 10,
    83  	SQL_TYPE_TIME_TZ:      6,
    84  	SQL_TYPE_DEC64:        8,
    85  	SQL_TYPE_DEC128:       16,
    86  	SQL_TYPE_DEC_FIXED:    16,
    87  	SQL_TYPE_BOOLEAN:      1,
    88  }
    89  
    90  var xsqlvarTypeDisplayLength = map[int]int{
    91  	SQL_TYPE_TEXT:         -1,
    92  	SQL_TYPE_VARYING:      -1,
    93  	SQL_TYPE_SHORT:        6,
    94  	SQL_TYPE_LONG:         11,
    95  	SQL_TYPE_FLOAT:        17,
    96  	SQL_TYPE_TIME:         11,
    97  	SQL_TYPE_DATE:         10,
    98  	SQL_TYPE_DOUBLE:       17,
    99  	SQL_TYPE_TIMESTAMP:    22,
   100  	SQL_TYPE_BLOB:         0,
   101  	SQL_TYPE_ARRAY:        -1,
   102  	SQL_TYPE_QUAD:         20,
   103  	SQL_TYPE_INT64:        20,
   104  	SQL_TYPE_INT128:       20,
   105  	SQL_TYPE_TIMESTAMP_TZ: 28,
   106  	SQL_TYPE_TIME_TZ:      17,
   107  	SQL_TYPE_DEC64:        16,
   108  	SQL_TYPE_DEC128:       34,
   109  	SQL_TYPE_DEC_FIXED:    34,
   110  	SQL_TYPE_BOOLEAN:      5,
   111  }
   112  
   113  var xsqlvarTypeName = map[int]string{
   114  	SQL_TYPE_TEXT:         "TEXT",
   115  	SQL_TYPE_VARYING:      "VARYING",
   116  	SQL_TYPE_SHORT:        "SHORT",
   117  	SQL_TYPE_LONG:         "LONG",
   118  	SQL_TYPE_FLOAT:        "FLOAT",
   119  	SQL_TYPE_TIME:         "TIME",
   120  	SQL_TYPE_DATE:         "DATE",
   121  	SQL_TYPE_DOUBLE:       "DOUBLE",
   122  	SQL_TYPE_TIMESTAMP:    "TIMESTAMP",
   123  	SQL_TYPE_BLOB:         "BLOB",
   124  	SQL_TYPE_ARRAY:        "ARRAY",
   125  	SQL_TYPE_QUAD:         "QUAD",
   126  	SQL_TYPE_INT64:        "INT64",
   127  	SQL_TYPE_INT128:       "INT128",
   128  	SQL_TYPE_TIMESTAMP_TZ: "TIMESTAMP WITH TIMEZONE",
   129  	SQL_TYPE_TIME_TZ:      "TIME WITH TIMEZONE",
   130  	SQL_TYPE_DEC64:        "DECFLOAT(16)",
   131  	SQL_TYPE_DEC128:       "DECFLOAT(34)",
   132  	SQL_TYPE_DEC_FIXED:    "DECFIXED",
   133  	SQL_TYPE_BOOLEAN:      "BOOLEAN",
   134  }
   135  
   136  type xSQLVAR struct {
   137  	sqltype    int
   138  	sqlscale   int
   139  	sqlsubtype int
   140  	sqllen     int
   141  	null_ok    bool
   142  	fieldname  string
   143  	relname    string
   144  	ownname    string
   145  	aliasname  string
   146  }
   147  
   148  func (x *xSQLVAR) ioLength() int {
   149  	if x.sqltype == SQL_TYPE_TEXT {
   150  		return x.sqllen
   151  	}
   152  	return xsqlvarTypeLength[x.sqltype]
   153  }
   154  
   155  func (x *xSQLVAR) displayLength() int {
   156  	if x.sqltype == SQL_TYPE_TEXT || x.sqltype == SQL_TYPE_VARYING {
   157  		return x.sqllen
   158  	}
   159  	return xsqlvarTypeDisplayLength[x.sqltype]
   160  }
   161  
   162  func (x *xSQLVAR) hasPrecisionScale() bool {
   163  	return (x.sqltype == SQL_TYPE_SHORT || x.sqltype == SQL_TYPE_LONG || x.sqltype == SQL_TYPE_QUAD || x.sqltype == SQL_TYPE_INT64 || x.sqltype == SQL_TYPE_INT128 || x.sqltype == SQL_TYPE_DEC64 || x.sqltype == SQL_TYPE_DEC128 || x.sqltype == SQL_TYPE_DEC_FIXED) && x.sqlscale != 0
   164  }
   165  
   166  func (x *xSQLVAR) typename() string {
   167  	return xsqlvarTypeName[x.sqltype]
   168  }
   169  
   170  func (x *xSQLVAR) scantype() reflect.Type {
   171  	switch x.sqltype {
   172  	case SQL_TYPE_TEXT:
   173  		return reflect.TypeOf("")
   174  	case SQL_TYPE_VARYING:
   175  		return reflect.TypeOf("")
   176  	case SQL_TYPE_SHORT:
   177  		if x.sqlscale != 0 {
   178  			return reflect.TypeOf(decimal.Decimal{})
   179  		}
   180  		return reflect.TypeOf(int16(0))
   181  	case SQL_TYPE_LONG:
   182  		if x.sqlscale != 0 {
   183  			return reflect.TypeOf(decimal.Decimal{})
   184  		}
   185  		return reflect.TypeOf(int32(0))
   186  	case SQL_TYPE_INT64:
   187  		if x.sqlscale != 0 {
   188  			return reflect.TypeOf(decimal.Decimal{})
   189  		}
   190  		return reflect.TypeOf(int64(0))
   191  	case SQL_TYPE_INT128:
   192  		return reflect.TypeOf(big.Int{})
   193  	case SQL_TYPE_DATE:
   194  		return reflect.TypeOf(time.Time{})
   195  	case SQL_TYPE_TIME:
   196  		return reflect.TypeOf(time.Time{})
   197  	case SQL_TYPE_TIMESTAMP:
   198  		return reflect.TypeOf(time.Time{})
   199  	case SQL_TYPE_FLOAT:
   200  		return reflect.TypeOf(float32(0))
   201  	case SQL_TYPE_DOUBLE:
   202  		return reflect.TypeOf(float64(0))
   203  	case SQL_TYPE_BOOLEAN:
   204  		return reflect.TypeOf(false)
   205  	case SQL_TYPE_BLOB:
   206  		return reflect.TypeOf([]byte{})
   207  	case SQL_TYPE_TIMESTAMP_TZ:
   208  		return reflect.TypeOf(time.Time{})
   209  	case SQL_TYPE_TIME_TZ:
   210  		return reflect.TypeOf(time.Time{})
   211  	case SQL_TYPE_DEC64:
   212  		return reflect.TypeOf(decimal.Decimal{})
   213  	case SQL_TYPE_DEC128:
   214  		return reflect.TypeOf(decimal.Decimal{})
   215  	case SQL_TYPE_DEC_FIXED:
   216  		return reflect.TypeOf(decimal.Decimal{})
   217  	}
   218  	return reflect.TypeOf(nil)
   219  }
   220  
   221  func (x *xSQLVAR) _parseTimezone(raw_value []byte) *time.Location {
   222  	timezone := getTimezoneNameByID(int(bytes_to_buint16(raw_value)))
   223  	tz, _ := time.LoadLocation(timezone)
   224  	return tz
   225  }
   226  
   227  func (x *xSQLVAR) _parseDate(raw_value []byte) (int, int, int) {
   228  	nday := int(bytes_to_bint32(raw_value)) + 678882
   229  	century := (4*nday - 1) / 146097
   230  	nday = 4*nday - 1 - 146097*century
   231  	day := nday / 4
   232  
   233  	nday = (4*day + 3) / 1461
   234  	day = 4*day + 3 - 1461*nday
   235  	day = (day + 4) / 4
   236  
   237  	month := (5*day - 3) / 153
   238  	day = 5*day - 3 - 153*month
   239  	day = (day + 5) / 5
   240  	year := 100*century + nday
   241  	if month < 10 {
   242  		month += 3
   243  	} else {
   244  		month -= 9
   245  		year++
   246  	}
   247  	return year, month, day
   248  }
   249  
   250  func (x *xSQLVAR) _parseTime(raw_value []byte) (int, int, int, int) {
   251  	n := int(bytes_to_bint32(raw_value))
   252  	s := n / 10000
   253  	m := s / 60
   254  	h := m / 60
   255  	m = m % 60
   256  	s = s % 60
   257  	return h, m, s, (n % 10000) * 100000
   258  }
   259  
   260  func (x *xSQLVAR) parseDate(raw_value []byte, timezone string) time.Time {
   261  	tz := time.Local
   262  	if timezone != "" {
   263  		tz, _ = time.LoadLocation(timezone)
   264  	}
   265  	year, month, day := x._parseDate(raw_value)
   266  	return time.Date(year, time.Month(month), day, 0, 0, 0, 0, tz)
   267  }
   268  
   269  func (x *xSQLVAR) parseTime(raw_value []byte, timezone string) time.Time {
   270  	tz := time.Local
   271  	if timezone != "" {
   272  		tz, _ = time.LoadLocation(timezone)
   273  	}
   274  	h, m, s, n := x._parseTime(raw_value)
   275  	now := time.Now()
   276  	zone, offset := time.Date(now.Year(), now.Month(), now.Day(), h, m, s, n, tz).Zone()
   277  	return time.Date(0, time.Month(1), 1, h, m, s, n, time.FixedZone(zone, offset))
   278  }
   279  
   280  func (x *xSQLVAR) parseTimestamp(raw_value []byte, timezone string) time.Time {
   281  	tz := time.Local
   282  	if timezone != "" {
   283  		tz, _ = time.LoadLocation(timezone)
   284  	}
   285  
   286  	year, month, day := x._parseDate(raw_value[:4])
   287  	h, m, s, n := x._parseTime(raw_value[4:8])
   288  	return time.Date(year, time.Month(month), day, h, m, s, n, tz)
   289  }
   290  
   291  func (x *xSQLVAR) parseTimeTz(raw_value []byte) time.Time {
   292  	h, m, s, n := x._parseTime(raw_value[:4])
   293  	tz := x._parseTimezone(raw_value[4:6])
   294  	loc := x._parseTimezone(raw_value[6:8])
   295  	now := time.Now()
   296  	t := time.Date(now.Year(), now.Month(), now.Day(), h, m, s, n, tz).In(loc)
   297  	zone, offset := t.Zone()
   298  	return time.Date(0, time.Month(1), 1, t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), time.FixedZone(zone, offset))
   299  }
   300  
   301  func (x *xSQLVAR) parseTimestampTz(raw_value []byte) time.Time {
   302  	year, month, day := x._parseDate(raw_value[:4])
   303  	h, m, s, n := x._parseTime(raw_value[4:8])
   304  	tz := x._parseTimezone(raw_value[8:10])
   305  	offset := x._parseTimezone(raw_value[10:12])
   306  	return time.Date(year, time.Month(month), day, h, m, s, n, tz).In(offset)
   307  }
   308  
   309  func (x *xSQLVAR) parseString(raw_value []byte, charset string) interface{} {
   310  	if x.sqlsubtype == 1 { // OCTETS
   311  		return raw_value
   312  	}
   313  	switch charset {
   314  	case "OCTETS":
   315  		return raw_value
   316  	case "UNICODE_FSS", "UTF8":
   317  		return bytes.NewBuffer(raw_value).String()
   318  	case "SJIS_0208":
   319  		dec := japanese.ShiftJIS.NewDecoder()
   320  		v, _ := dec.Bytes(raw_value)
   321  		return string(v)
   322  	case "EUCJ_0208":
   323  		dec := japanese.EUCJP.NewDecoder()
   324  		v, _ := dec.Bytes(raw_value)
   325  		return string(v)
   326  	case "ISO8859_1":
   327  		dec := charmap.ISO8859_1.NewDecoder()
   328  		v, _ := dec.Bytes(raw_value)
   329  		return string(v)
   330  	case "ISO8859_2":
   331  		dec := charmap.ISO8859_2.NewDecoder()
   332  		v, _ := dec.Bytes(raw_value)
   333  		return string(v)
   334  	case "ISO8859_3":
   335  		dec := charmap.ISO8859_3.NewDecoder()
   336  		v, _ := dec.Bytes(raw_value)
   337  		return string(v)
   338  	case "ISO8859_4":
   339  		dec := charmap.ISO8859_5.NewDecoder()
   340  		v, _ := dec.Bytes(raw_value)
   341  		return string(v)
   342  	case "ISO8859_5":
   343  		dec := charmap.ISO8859_5.NewDecoder()
   344  		v, _ := dec.Bytes(raw_value)
   345  		return string(v)
   346  	case "ISO8859_6":
   347  		dec := charmap.ISO8859_6.NewDecoder()
   348  		v, _ := dec.Bytes(raw_value)
   349  		return string(v)
   350  	case "ISO8859_7":
   351  		dec := charmap.ISO8859_7.NewDecoder()
   352  		v, _ := dec.Bytes(raw_value)
   353  		return string(v)
   354  	case "ISO8859_8":
   355  		dec := charmap.ISO8859_8.NewDecoder()
   356  		v, _ := dec.Bytes(raw_value)
   357  		return string(v)
   358  	case "ISO8859_9":
   359  		dec := charmap.ISO8859_9.NewDecoder()
   360  		v, _ := dec.Bytes(raw_value)
   361  		return string(v)
   362  	case "ISO8859_13":
   363  		dec := charmap.ISO8859_13.NewDecoder()
   364  		v, _ := dec.Bytes(raw_value)
   365  		return string(v)
   366  	case "KSC_5601":
   367  		dec := korean.EUCKR.NewDecoder()
   368  		v, _ := dec.Bytes(raw_value)
   369  		return string(v)
   370  	case "WIN1250":
   371  		dec := charmap.Windows1250.NewDecoder()
   372  		v, _ := dec.Bytes(raw_value)
   373  		return string(v)
   374  	case "WIN1251":
   375  		dec := charmap.Windows1251.NewDecoder()
   376  		v, _ := dec.Bytes(raw_value)
   377  		return string(v)
   378  	case "WIN1252":
   379  		dec := charmap.Windows1252.NewDecoder()
   380  		v, _ := dec.Bytes(raw_value)
   381  		return string(v)
   382  	case "WIN1253":
   383  		dec := charmap.Windows1252.NewDecoder()
   384  		v, _ := dec.Bytes(raw_value)
   385  		return string(v)
   386  	case "WIN1254":
   387  		dec := charmap.Windows1252.NewDecoder()
   388  		v, _ := dec.Bytes(raw_value)
   389  		return string(v)
   390  	case "BIG_5":
   391  		dec := traditionalchinese.Big5.NewDecoder()
   392  		v, _ := dec.Bytes(raw_value)
   393  		return string(v)
   394  	case "GB_2312":
   395  		dec := simplifiedchinese.HZGB2312.NewDecoder()
   396  		v, _ := dec.Bytes(raw_value)
   397  		return string(v)
   398  	case "WIN1255":
   399  		dec := charmap.Windows1255.NewDecoder()
   400  		v, _ := dec.Bytes(raw_value)
   401  		return string(v)
   402  	case "WIN1256":
   403  		dec := charmap.Windows1256.NewDecoder()
   404  		v, _ := dec.Bytes(raw_value)
   405  		return string(v)
   406  	case "WIN1257":
   407  		dec := charmap.Windows1257.NewDecoder()
   408  		v, _ := dec.Bytes(raw_value)
   409  		return string(v)
   410  	case "KOI8R":
   411  		dec := charmap.KOI8R.NewDecoder()
   412  		v, _ := dec.Bytes(raw_value)
   413  		return string(v)
   414  	case "KOI8U":
   415  		dec := charmap.KOI8U.NewDecoder()
   416  		v, _ := dec.Bytes(raw_value)
   417  		return string(v)
   418  	case "WIN1258":
   419  		dec := charmap.Windows1258.NewDecoder()
   420  		v, _ := dec.Bytes(raw_value)
   421  		return string(v)
   422  	default:
   423  		return raw_value
   424  	}
   425  }
   426  
   427  func (x *xSQLVAR) value(raw_value []byte, timezone string, charset string) (v interface{}, err error) {
   428  	switch x.sqltype {
   429  	case SQL_TYPE_TEXT:
   430  		if x.sqlsubtype == 1 || charset == "None" { // OCTETS
   431  			v = raw_value
   432  		} else {
   433  			v = x.parseString(raw_value, charset)
   434  			switch v.(type) {
   435  			case string:
   436  				v = strings.TrimRight(v.(string), " ")
   437  			case []uint8:
   438  				v = strings.TrimRight(string(v.([]uint8)), " ")
   439  			}
   440  		}
   441  	case SQL_TYPE_VARYING:
   442  		if x.sqlsubtype == 1 { // OCTETS
   443  			v = raw_value
   444  		} else {
   445  			v = x.parseString(raw_value, charset)
   446  		}
   447  	case SQL_TYPE_SHORT:
   448  		i16 := int16(bytes_to_bint32(raw_value))
   449  		if x.sqlscale > 0 {
   450  			v = int64(i16) * int64(math.Pow10(x.sqlscale))
   451  		} else if x.sqlscale < 0 {
   452  			v = decimal.New(int64(i16), int32(x.sqlscale))
   453  		} else {
   454  			v = i16
   455  		}
   456  	case SQL_TYPE_LONG:
   457  		i32 := bytes_to_bint32(raw_value)
   458  		if x.sqlscale > 0 {
   459  			v = int64(i32) * int64(math.Pow10(x.sqlscale))
   460  		} else if x.sqlscale < 0 {
   461  			v = decimal.New(int64(i32), int32(x.sqlscale))
   462  		} else {
   463  			v = i32
   464  		}
   465  	case SQL_TYPE_INT64:
   466  		i64 := bytes_to_bint64(raw_value)
   467  		if x.sqlscale > 0 {
   468  			v = i64 * int64(math.Pow10(x.sqlscale))
   469  		} else if x.sqlscale < 0 {
   470  			v = decimal.New(int64(i64), int32(x.sqlscale))
   471  		} else {
   472  			v = i64
   473  		}
   474  	case SQL_TYPE_INT128:
   475  		var isNegative bool
   476  
   477  		// when raw_value[0] is > 127, then subtract 255 in every index
   478  		if raw_value[0] > 127 {
   479  			for i := range raw_value {
   480  				if raw_value[i] < 255 {
   481  					raw_value[i] = 255 - raw_value[i]
   482  				} else {
   483  					raw_value[i] -= 255
   484  				}
   485  			}
   486  			isNegative = true
   487  		}
   488  
   489  		// reverse
   490  		for i, j := 0, len(raw_value)-1; i < j; i, j = i+1, j-1 {
   491  			raw_value[i], raw_value[j] = raw_value[j], raw_value[i]
   492  		}
   493  
   494  		// variable to return
   495  		var x = new(big.Int)
   496  
   497  		for i := len(raw_value) - 1; i >= 0; i-- {
   498  			if raw_value[i] == 0 {
   499  				continue
   500  			}
   501  
   502  			// get the 2^(i*8) in big.Float
   503  			var t = new(big.Float).SetFloat64(math.Pow(2, float64(i*8)))
   504  
   505  			// convert the float to int
   506  			var xx *big.Int
   507  			xx, _ = t.Int(xx)
   508  
   509  			// mul with the value in raw_value
   510  			xx.Mul(xx, big.NewInt(int64(raw_value[i])))
   511  
   512  			// add to x
   513  			x.Add(x, xx)
   514  		}
   515  
   516  		// when negative, add 1 and mul -1
   517  		if isNegative {
   518  			x.Add(x, big.NewInt(1))
   519  			x.Mul(x, big.NewInt(-1))
   520  		}
   521  		v = x
   522  	case SQL_TYPE_DATE:
   523  		v = x.parseDate(raw_value, timezone)
   524  	case SQL_TYPE_TIME:
   525  		v = x.parseTime(raw_value, timezone)
   526  	case SQL_TYPE_TIMESTAMP:
   527  		v = x.parseTimestamp(raw_value, timezone)
   528  	case SQL_TYPE_TIME_TZ:
   529  		v = x.parseTimeTz(raw_value)
   530  	case SQL_TYPE_TIMESTAMP_TZ:
   531  		v = x.parseTimestampTz(raw_value)
   532  	case SQL_TYPE_FLOAT:
   533  		var f32 float32
   534  		b := bytes.NewReader(raw_value)
   535  		err = binary.Read(b, binary.BigEndian, &f32)
   536  		v = f32
   537  	case SQL_TYPE_DOUBLE:
   538  		b := bytes.NewReader(raw_value)
   539  		var f64 float64
   540  		err = binary.Read(b, binary.BigEndian, &f64)
   541  		v = f64
   542  	case SQL_TYPE_BOOLEAN:
   543  		v = raw_value[0] != 0
   544  	case SQL_TYPE_BLOB:
   545  		v = raw_value
   546  	case SQL_TYPE_DEC_FIXED:
   547  		v = decimalFixedToDecimal(raw_value, int32(x.sqlscale))
   548  	case SQL_TYPE_DEC64:
   549  		v = decimal64ToDecimal(raw_value)
   550  	case SQL_TYPE_DEC128:
   551  		v = decimal128ToDecimal(raw_value)
   552  	}
   553  	return
   554  }
   555  
   556  func calcBlr(xsqlda []xSQLVAR) []byte {
   557  	// Calculate  BLR from XSQLVAR array.
   558  	ln := len(xsqlda) * 2
   559  	blr := make([]byte, (ln*4)+8)
   560  	blr[0] = 5
   561  	blr[1] = 2
   562  	blr[2] = 4
   563  	blr[3] = 0
   564  	blr[4] = byte(ln & 255)
   565  	blr[5] = byte(ln >> 8)
   566  	n := 6
   567  
   568  	for _, x := range xsqlda {
   569  		sqlscale := x.sqlscale
   570  		if sqlscale < 0 {
   571  			sqlscale += 256
   572  		}
   573  		switch x.sqltype {
   574  		case SQL_TYPE_VARYING:
   575  			blr[n] = 37
   576  			blr[n+1] = byte(x.sqllen & 255)
   577  			blr[n+2] = byte(x.sqllen >> 8)
   578  			n += 3
   579  		case SQL_TYPE_TEXT:
   580  			blr[n] = 14
   581  			blr[n+1] = byte(x.sqllen & 255)
   582  			blr[n+2] = byte(x.sqllen >> 8)
   583  			n += 3
   584  		case SQL_TYPE_LONG:
   585  			blr[n] = 8
   586  			blr[n+1] = byte(sqlscale)
   587  			n += 2
   588  		case SQL_TYPE_SHORT:
   589  			blr[n] = 7
   590  			blr[n+1] = byte(sqlscale)
   591  			n += 2
   592  		case SQL_TYPE_INT64:
   593  			blr[n] = 16
   594  			blr[n+1] = byte(sqlscale)
   595  			n += 2
   596  		case SQL_TYPE_INT128:
   597  			blr[n] = 26
   598  			blr[n+1] = byte(sqlscale)
   599  			n += 2
   600  		case SQL_TYPE_QUAD:
   601  			blr[n] = 9
   602  			blr[n+1] = byte(sqlscale)
   603  			n += 2
   604  		case SQL_TYPE_DEC_FIXED: // OBSOLATED
   605  			blr[n] = 26
   606  			blr[n+1] = byte(sqlscale)
   607  			n += 2
   608  		case SQL_TYPE_DOUBLE:
   609  			blr[n] = 27
   610  			n++
   611  		case SQL_TYPE_FLOAT:
   612  			blr[n] = 10
   613  			n++
   614  		case SQL_TYPE_D_FLOAT:
   615  			blr[n] = 11
   616  			n++
   617  		case SQL_TYPE_DATE:
   618  			blr[n] = 12
   619  			n++
   620  		case SQL_TYPE_TIME:
   621  			blr[n] = 13
   622  			n++
   623  		case SQL_TYPE_TIMESTAMP:
   624  			blr[n] = 35
   625  			n++
   626  		case SQL_TYPE_BLOB:
   627  			blr[n] = 9
   628  			blr[n+1] = 0
   629  			n += 2
   630  		case SQL_TYPE_ARRAY:
   631  			blr[n] = 9
   632  			blr[n+1] = 0
   633  			n += 2
   634  		case SQL_TYPE_BOOLEAN:
   635  			blr[n] = 23
   636  			n++
   637  		case SQL_TYPE_DEC64:
   638  			blr[n] = 24
   639  			n++
   640  		case SQL_TYPE_DEC128:
   641  			blr[n] = 25
   642  			n++
   643  		case SQL_TYPE_TIME_TZ:
   644  			blr[n] = 28
   645  			n++
   646  		case SQL_TYPE_TIMESTAMP_TZ:
   647  			blr[n] = 29
   648  			n++
   649  		}
   650  		// [blr_short, 0]
   651  		blr[n] = 7
   652  		blr[n+1] = 0
   653  		n += 2
   654  	}
   655  	// [blr_end, blr_eoc]
   656  	blr[n] = 255
   657  	blr[n+1] = 76
   658  	n += 2
   659  
   660  	return blr[:n]
   661  }