Repository: snowflakedb/gosnowflake
Pull request #1414 (2025-05-16 11:02:22)

SNOW-2091309 Fix precision lost for NUMBER(19, 0) by returning big.Int and for non-zero scale numbers, align scan types and actual types
### Description

SNOW-2091309 Before this change, when `NUMBER(19, 0)` was used as a column, there was a potential loss of precision when the value was above 9,223,372,036,854,775,807 (max int64 value). To fix this issue, `*big.Int` or string (depending on the higher precision setting) is pessimistically chosen as the return type for such a column.

Also, added higher precision support for JSON result sets.

### Checklist
- [x] Created tests which fail without the change (if possible)
- [x] Extended the README / documentation, if necessary


sfc-gh-snowflakedb-snyk-sa: ![](https://res.cloudinary.com/snyk/image/upload/r-d/scm-platform/snyk-pull-requests/pr-banner-default.svg)

### :tada: **Snyk checks have passed. No issues have been found so far.**

:white_check_mark: **security/snyk** check is complete. No issues have been found. [(View Details)](https://app.snyk.io/org/snowflakedb-sca-scanning-public-repo/pr-checks/7d577704-e735-413b-96ab-3fed08e3368b?refs=25befdfda6c184d38f92ba7667d19b958f1cef33&source=prChecksComment)

:white_check_mark: **license/snyk** check is complete. No issues have been found. [(View Details)](https://app.snyk.io/org/snowflakedb-sca-scanning-public-repo/pr-checks/7d577704-e735-413b-96ab-3fed08e3368b/license?refs=25befdfda6c184d38f92ba7667d19b958f1cef33&source=prChecksComment)




Patch:
diff --git a/converter.go b/converter.go
index ee6f4fa..440a463 100644
--- a/converter.go
+++ b/converter.go
@@ -139,17 +139,23 @@ func goTypeToSnowflake(v driver.Value, tsmode snowflakeType) snowflakeType {
 }
 
 // snowflakeTypeToGo translates Snowflake data type to Go data type.
-func snowflakeTypeToGo(ctx context.Context, dbtype snowflakeType, scale int64, fields []fieldMetadata) reflect.Type {
+func snowflakeTypeToGo(ctx context.Context, dbtype snowflakeType, precision int64, scale int64, fields []fieldMetadata) reflect.Type {
 	structuredTypesEnabled := structuredTypesEnabled(ctx)
 	switch dbtype {
 	case fixedType:
 		if higherPrecisionEnabled(ctx) {
 			if scale == 0 {
-				return reflect.TypeOf(&big.Int{})
+				if precision >= 19 {
+					return reflect.TypeOf(&big.Int{})
+				}
+				return reflect.TypeOf(int64(0))
 			}
 			return reflect.TypeOf(&big.Float{})
 		}
 		if scale == 0 {
+			if precision >= 19 {
+				return reflect.TypeOf("")
+			}
 			return reflect.TypeOf(int64(0))
 		}
 		return reflect.TypeOf(float64(0))
@@ -974,7 +980,28 @@ func stringToValue(ctx context.Context, dest *driver.Value, srcColumnMeta execRe
 		}
 		*dest = v
 		return nil
-	case "text", "fixed", "real", "variant":
+	case "text", "real", "variant":
+		*dest = *srcValue
+		return nil
+	case "fixed":
+		if higherPrecisionEnabled(ctx) {
+			if srcColumnMeta.Scale == 0 {
+				if srcColumnMeta.Precision >= 19 {
+					bigInt := big.NewInt(0)
+					bigInt.SetString(*srcValue, 10)
+					*dest = *bigInt
+					return nil
+				}
+				*dest = *srcValue
+				return nil
+			}
+			bigFloat, _, err := big.ParseFloat(*srcValue, 10, big.MaxPrec, big.AwayFromZero)
+			if err != nil {
+				return err
+			}
+			*dest = *bigFloat
+			return nil
+		}
 		*dest = *srcValue
 		return nil
 	case "date":
@@ -1533,15 +1560,15 @@ func arrowToValue(ctx context.Context, rowIdx int, srcColumnMeta fieldMetadata,
 		// e.g. NUMBER, DECIMAL/NUMERIC, INT/INTEGER
 		switch numericValue := srcValue.(type) {
 		case *array.Decimal128:
-			return arrowDecimal128ToValue(numericValue, rowIdx, higherPrecision, int(srcColumnMeta.Scale)), nil
+			return arrowDecimal128ToValue(numericValue, rowIdx, higherPrecision, srcColumnMeta), nil
 		case *array.Int64:
-			return arrowInt64ToValue(numericValue, rowIdx, higherPrecision, int(srcColumnMeta.Scale)), nil
+			return arrowInt64ToValue(numericValue, rowIdx, higherPrecision, srcColumnMeta), nil
 		case *array.Int32:
-			return arrowInt32ToValue(numericValue, rowIdx, higherPrecision, int(srcColumnMeta.Scale)), nil
+			return arrowInt32ToValue(numericValue, rowIdx, higherPrecision, srcColumnMeta), nil
 		case *array.Int16:
-			return arrowInt16ToValue(numericValue, rowIdx, higherPrecision, int(srcColumnMeta.Scale)), nil
+			return arrowInt16ToValue(numericValue, rowIdx, higherPrecision, srcColumnMeta), nil
 		case *array.Int8:
-			return arrowInt8ToValue(numericValue, rowIdx, higherPrecision, int(srcColumnMeta.Scale)), nil
+			return arrowInt8ToValue(numericValue, rowIdx, higherPrecision, srcColumnMeta), nil
 		}
 		return nil, fmt.Errorf("unsupported data type")
 	case booleanType:
@@ -1690,7 +1717,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 		case *array.Decimal128:
 			if higherPrecision && fieldMetadata.Scale == 0 {
 				return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (*big.Int, error) {
-					bigInt := arrowDecimal128ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+					bigInt := arrowDecimal128ToValue(typedValues, j, higherPrecision, fieldMetadata)
 					if bigInt == nil {
 						return nil, nil
 					}
@@ -1699,7 +1726,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 				})
 			} else if higherPrecision && fieldMetadata.Scale != 0 {
 				return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (*big.Float, error) {
-					bigFloat := arrowDecimal128ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+					bigFloat := arrowDecimal128ToValue(typedValues, j, higherPrecision, fieldMetadata)
 					if bigFloat == nil {
 						return nil, nil
 					}
@@ -1710,7 +1737,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 			} else if !higherPrecision && fieldMetadata.Scale == 0 {
 				if arrayValuesNullableEnabled(ctx) {
 					return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (sql.NullInt64, error) {
-						v := arrowDecimal128ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+						v := arrowDecimal128ToValue(typedValues, j, higherPrecision, fieldMetadata)
 						if v == nil {
 							return sql.NullInt64{Valid: false}, nil
 						}
@@ -1723,7 +1750,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 					})
 				}
 				return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (int64, error) {
-					v := arrowDecimal128ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+					v := arrowDecimal128ToValue(typedValues, j, higherPrecision, fieldMetadata)
 					if v == nil {
 						return 0, errNullValueInArray()
 					}
@@ -1732,7 +1759,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 			} else {
 				if arrayValuesNullableEnabled(ctx) {
 					return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (sql.NullFloat64, error) {
-						v := arrowDecimal128ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+						v := arrowDecimal128ToValue(typedValues, j, higherPrecision, fieldMetadata)
 						if v == nil {
 							return sql.NullFloat64{Valid: false}, nil
 						}
@@ -1745,7 +1772,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 					})
 				}
 				return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (float64, error) {
-					v := arrowDecimal128ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+					v := arrowDecimal128ToValue(typedValues, j, higherPrecision, fieldMetadata)
 					if v == nil {
 						return 0, errNullValueInArray()
 					}
@@ -1756,7 +1783,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 		case *array.Int64:
 			if arrayValuesNullableEnabled(ctx) {
 				return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (sql.NullInt64, error) {
-					resInt := arrowInt64ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+					resInt := arrowInt64ToValue(typedValues, j, higherPrecision, fieldMetadata)
 					if resInt == nil {
 						return sql.NullInt64{Valid: false}, nil
 					}
@@ -1764,7 +1791,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 				})
 			}
 			return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (int64, error) {
-				resInt := arrowInt64ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+				resInt := arrowInt64ToValue(typedValues, j, higherPrecision, fieldMetadata)
 				if resInt == nil {
 					return 0, errNullValueInArray()
 				}
@@ -1774,7 +1801,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 		case *array.Int32:
 			if arrayValuesNullableEnabled(ctx) {
 				return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (sql.NullInt32, error) {
-					resInt := arrowInt32ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+					resInt := arrowInt32ToValue(typedValues, j, higherPrecision, fieldMetadata)
 					if resInt == nil {
 						return sql.NullInt32{Valid: false}, nil
 					}
@@ -1783,7 +1810,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 				})
 			}
 			return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (int32, error) {
-				resInt := arrowInt32ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+				resInt := arrowInt32ToValue(typedValues, j, higherPrecision, fieldMetadata)
 				if resInt == nil {
 					return 0, errNullValueInArray()
 				}
@@ -1792,7 +1819,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 		case *array.Int16:
 			if arrayValuesNullableEnabled(ctx) {
 				return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (sql.NullInt16, error) {
-					resInt := arrowInt16ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+					resInt := arrowInt16ToValue(typedValues, j, higherPrecision, fieldMetadata)
 					if resInt == nil {
 						return sql.NullInt16{Valid: false}, nil
 					}
@@ -1801,7 +1828,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 				})
 			}
 			return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (int16, error) {
-				resInt := arrowInt16ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+				resInt := arrowInt16ToValue(typedValues, j, higherPrecision, fieldMetadata)
 				if resInt == nil {
 					return 0, errNullValueInArray()
 				}
@@ -1811,7 +1838,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 		case *array.Int8:
 			if arrayValuesNullableEnabled(ctx) {
 				return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (sql.NullByte, error) {
-					resInt := arrowInt8ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+					resInt := arrowInt8ToValue(typedValues, j, higherPrecision, fieldMetadata)
 					if resInt == nil {
 						return sql.NullByte{Valid: false}, nil
 					}
@@ -1819,7 +1846,7 @@ func buildListFromNativeArrow(ctx context.Context, rowIdx int, fieldMetadata fie
 				})
 			}
 			return mapStructuredArrayNativeArrowRows(offsets, rowIdx, func(j int) (int8, error) {
-				resInt := arrowInt8ToValue(typedValues, j, higherPrecision, fieldMetadata.Scale)
+				resInt := arrowInt8ToValue(typedValues, j, higherPrecision, fieldMetadata)
 				if resInt == nil {
 					return 0, errNullValueInArray()
 				}
@@ -2240,25 +2267,25 @@ func buildTimeFromNativeArrowArray[K comparable](mapNullValuesEnabled bool, offs
 }
 
 func mapStructuredMapNativeArrowFixedValue[V any](valueMetadata fieldMetadata, j int, items arrow.Array, higherPrecision bool, defaultValue V) (V, error) {
-	v, err := extractNumberFromArrow(&items, j, higherPrecision, valueMetadata.Scale)
+	v, err := extractNumberFromArrow(&items, j, higherPrecision, valueMetadata)
 	if err != nil {
 		return defaultValue, err
 	}
 	return v.(V), nil
 }
 
-func extractNumberFromArrow(values *arrow.Array, j int, higherPrecision bool, scale int) (snowflakeValue, error) {
+func extractNumberFromArrow(values *arrow.Array, j int, higherPrecision bool, srcColumnMeta fieldMetadata) (snowflakeValue, error) {
 	switch typedValues := (*values).(type) {
 	case *array.Decimal128:
-		return arrowDecimal128ToValue(typedValues, j, higherPrecision, scale), nil
+		return arrowDecimal128ToValue(typedValues, j, higherPrecision, srcColumnMeta), nil
 	case *array.Int64:
-		return arrowInt64ToValue(typedValues, j, higherPrecision, scale), nil
+		return arrowInt64ToValue(typedValues, j, higherPrecision, srcColumnMeta), nil
 	case *array.Int32:
-		return arrowInt32ToValue(typedValues, j, higherPrecision, scale), nil
+		return arrowInt32ToValue(typedValues, j, higherPrecision, srcColumnMeta), nil
 	case *array.Int16:
-		return arrowInt16ToValue(typedValues, j, higherPrecision, scale), nil
+		return arrowInt16ToValue(typedValues, j, higherPrecision, srcColumnMeta), nil
 	case *array.Int8:
-		return arrowInt8ToValue(typedValues, j, higherPrecision, scale), nil
+		return arrowInt8ToValue(typedValues, j, higherPrecision, srcColumnMeta), nil
 	}
 	return 0, fmt.Errorf("unknown number type: %T", values)
 }
@@ -2286,15 +2313,15 @@ func arrowToStructuredType(ctx context.Context, structs *array.Struct, fieldMeta
 			v = structs.Field(colIdx).ValueStr(rowIdx)
 			switch typedValues := structs.Field(colIdx).(type) {
 			case *array.Decimal128:
-				v = arrowDecimal128ToValue(typedValues, rowIdx, higherPrecision, fieldMetadata[colIdx].Scale)
+				v = arrowDecimal128ToValue(typedValues, rowIdx, higherPrecision, fieldMetadata[colIdx])
 			case *array.Int64:
-				v = arrowInt64ToValue(typedValues, rowIdx, higherPrecision, fieldMetadata[colIdx].Scale)
+				v = arrowInt64ToValue(typedValues, rowIdx, higherPrecision, fieldMetadata[colIdx])
 			case *array.Int32:
-				v = arrowInt32ToValue(typedValues, rowIdx, higherPrecision, fieldMetadata[colIdx].Scale)
+				v = arrowInt32ToValue(typedValues, rowIdx, higherPrecision, fieldMetadata[colIdx])
 			case *array.Int16:
-				v = arrowInt16ToValue(typedValues, rowIdx, higherPrecision, fieldMetadata[colIdx].Scale)
+				v = arrowInt16ToValue(typedValues, rowIdx, higherPrecision, fieldMetadata[colIdx])
 			case *array.Int8:
-				v = arrowInt8ToValue(typedValues, rowIdx, higherPrecision, fieldMetadata[colIdx].Scale)
+				v = arrowInt8ToValue(typedValues, rowIdx, higherPrecision, fieldMetadata[colIdx])
 			}
 		case booleanType:
 			v = arrowBoolToValue(structs.Field(colIdx).(*array.Boolean), rowIdx)
@@ -2350,68 +2377,71 @@ func arrowStringToValue(srcValue *array.String, rowIdx int) snowflakeValue {
 	return srcValue.Value(rowIdx)
 }
 
-func arrowDecimal128ToValue(srcValue *array.Decimal128, rowIdx int, higherPrecision bool, scale int) snowflakeValue {
+func arrowDecimal128ToValue(srcValue *array.Decimal128, rowIdx int, higherPrecision bool, srcColumnMeta fieldMetadata) snowflakeValue {
 	if !srcValue.IsNull(rowIdx) {
 		num := srcValue.Value(rowIdx)
-		if scale == 0 {
+		if srcColumnMeta.Scale == 0 {
 			if higherPrecision {
 				return num.BigInt()
 			}
 			return num.ToString(0)
 		}
-		f := decimalToBigFloat(num, int64(scale))
+		f := decimalToBigFloat(num, int64(srcColumnMeta.Scale))
 		if higherPrecision {
 			return f
 		}
-		return fmt.Sprintf("%.*f", scale, f)
+		return fmt.Sprintf("%.*f", srcColumnMeta.Scale, f)
 	}
 	return nil
 }
 
-func arrowInt64ToValue(srcValue *array.Int64, rowIdx int, higherPrecision bool, scale int) snowflakeValue {
+func arrowInt64ToValue(srcValue *array.Int64, rowIdx int, higherPrecision bool, srcColumnMeta fieldMetadata) snowflakeValue {
 	if !srcValue.IsNull(rowIdx) {
 		val := srcValue.Value(rowIdx)
-		return arrowIntToValue(scale, higherPrecision, val)
+		return arrowIntToValue(srcColumnMeta, higherPrecision, val)
 	}
 	return nil
 }
 
-func arrowInt32ToValue(srcValue *array.Int32, rowIdx int, higherPrecision bool, scale int) snowflakeValue {
+func arrowInt32ToValue(srcValue *array.Int32, rowIdx int, higherPrecision bool, srcColumnMeta fieldMetadata) snowflakeValue {
 	if !srcValue.IsNull(rowIdx) {
 		val := srcValue.Value(rowIdx)
-		return arrowIntToValue(scale, higherPrecision, int64(val))
+		return arrowIntToValue(srcColumnMeta, higherPrecision, int64(val))
 	}
 	return nil
 }
 
-func arrowInt16ToValue(srcValue *array.Int16, rowIdx int, higherPrecision bool, scale int) snowflakeValue {
+func arrowInt16ToValue(srcValue *array.Int16, rowIdx int, higherPrecision bool, srcColumnMeta fieldMetadata) snowflakeValue {
 	if !srcValue.IsNull(rowIdx) {
 		val := srcValue.Value(rowIdx)
-		return arrowIntToValue(scale, higherPrecision, int64(val))
+		return arrowIntToValue(srcColumnMeta, higherPrecision, int64(val))
 	}
 	return nil
 }
 
-func arrowInt8ToValue(srcValue *array.Int8, rowIdx int, higherPrecision bool, scale int) snowflakeValue {
+func arrowInt8ToValue(srcValue *array.Int8, rowIdx int, higherPrecision bool, srcColumnMeta fieldMetadata) snowflakeValue {
 	if !srcValue.IsNull(rowIdx) {
 		val := srcValue.Value(rowIdx)
-		return arrowIntToValue(scale, higherPrecision, int64(val))
+		return arrowIntToValue(srcColumnMeta, higherPrecision, int64(val))
 	}
 	return nil
 }
 
-func arrowIntToValue(scale int, higherPrecision bool, val int64) snowflakeValue {
-	if scale == 0 {
+func arrowIntToValue(srcColumnMeta fieldMetadata, higherPrecision bool, val int64) snowflakeValue {
+	if srcColumnMeta.Scale == 0 {
 		if higherPrecision {
-			return int64(val)
+			if srcColumnMeta.Precision >= 19 {
+				return big.NewInt(val)
+			}
+			return val
 		}
 		return fmt.Sprintf("%d", val)
 	}
 	if higherPrecision {
-		f := intToBigFloat(int64(val), int64(scale))
+		f := intToBigFloat(val, int64(srcColumnMeta.Scale))
 		return f
 	}
-	return fmt.Sprintf("%.*f", scale, float64(val)/math.Pow10(int(scale)))
+	return fmt.Sprintf("%.*f", srcColumnMeta.Scale, float64(val)/math.Pow10(srcColumnMeta.Scale))
 }
 
 func arrowRealToValue(srcValue *array.Float64, rowIdx int) snowflakeValue {
diff --git a/rows.go b/rows.go
index 1f4df3a..a714fb8 100644
--- a/rows.go
+++ b/rows.go
@@ -148,7 +148,7 @@ func (rows *snowflakeRows) ColumnTypeScanType(index int) reflect.Type {
 	if err := rows.waitForAsyncQueryStatus(); err != nil {
 		return nil
 	}
-	return snowflakeTypeToGo(rows.ctx, getSnowflakeType(rows.ChunkDownloader.getRowType()[index].Type), rows.ChunkDownloader.getRowType()[index].Scale, rows.ChunkDownloader.getRowType()[index].Fields)
+	return snowflakeTypeToGo(rows.ctx, getSnowflakeType(rows.ChunkDownloader.getRowType()[index].Type), rows.ChunkDownloader.getRowType()[index].Precision, rows.ChunkDownloader.getRowType()[index].Scale, rows.ChunkDownloader.getRowType()[index].Fields)
 }
 
 func (rows *snowflakeRows) GetQueryID() string {


Test patch:
diff --git a/arrow_test.go b/arrow_test.go
index 1c8b150..0576d6e 100644
--- a/arrow_test.go
+++ b/arrow_test.go
@@ -494,26 +494,29 @@ func TestArrowVariousTypes(t *testing.T) {
 			dbt.Errorf("column types: %v", ct)
 		}
 		var v1 *big.Float
-		var v2 int
+		var v2, v2a int
 		var v3 string
 		var v4 float64
 		var v5 []byte
 		var v6 bool
-		if err = rows.Scan(&v1, &v2, &v3, &v4, &v5, &v6); err != nil {
+		if err = rows.Scan(&v1, &v2, &v2a, &v3, &v4, &v5, &v6); err != nil {
 			dbt.Errorf("failed to scan: %#v", err)
 		}
 		if v1.Cmp(big.NewFloat(1.0)) != 0 {
 			dbt.Errorf("failed to scan. %#v", *v1)
 		}
-		if ct[0].Name() != "C1" || ct[1].Name() != "C2" || ct[2].Name() != "C3" || ct[3].Name() != "C4" || ct[4].Name() != "C5" || ct[5].Name() != "C6" {
+		if ct[0].Name() != "C1" || ct[1].Name() != "C2" || ct[2].Name() != "C2A" || ct[3].Name() != "C3" || ct[4].Name() != "C4" || ct[5].Name() != "C5" || ct[6].Name() != "C6" {
 			dbt.Errorf("failed to get column names: %#v", ct)
 		}
 		if ct[0].ScanType() != reflect.TypeOf(&big.Float{}) {
 			dbt.Errorf("failed to get scan type. expected: %v, got: %v", reflect.TypeOf(float64(0)), ct[0].ScanType())
 		}
-		if ct[1].ScanType() != reflect.TypeOf(&big.Int{}) {
+		if ct[1].ScanType() != reflect.TypeOf(int64(0)) {
 			dbt.Errorf("failed to get scan type. expected: %v, got: %v", reflect.TypeOf(int64(0)), ct[1].ScanType())
 		}
+		if ct[2].ScanType() != reflect.TypeOf(&big.Int{}) {
+			dbt.Errorf("failed to get scan type. expected: %v, got: %v", reflect.TypeOf(&big.Int{}), ct[2].ScanType())
+		}
 		var pr, sc int64
 		var cLen int64
 		pr, sc = dbt.mustDecimalSize(ct[0])
@@ -531,50 +534,53 @@ func TestArrowVariousTypes(t *testing.T) {
 			dbt.Errorf("failed to scan. %#v", v2)
 		}
 		pr, sc = dbt.mustDecimalSize(ct[1])
-		if pr != 38 || sc != 0 {
+		if pr != 18 || sc != 0 {
 			dbt.Errorf("failed to get precision and scale. %#v", ct[1])
 		}
 		dbt.mustFailLength(ct[1])
 		if canNull := dbt.mustNullable(ct[1]); canNull {
 			dbt.Errorf("failed to get nullable. %#v", ct[1])
 		}
-		if v3 != "t3" {
-			dbt.Errorf("failed to scan. %#v", v3)
-		}
-		dbt.mustFailDecimalSize(ct[2])
-		if cLen = dbt.mustLength(ct[2]); cLen != 2 {
-			dbt.Errorf("failed to get length. %#v", ct[2])
+		if v2a != 22 {
+			dbt.Errorf("failed to scan. %#v", v2a)
 		}
+		dbt.mustFailLength(ct[2])
 		if canNull := dbt.mustNullable(ct[2]); canNull {
 			dbt.Errorf("failed to get nullable. %#v", ct[2])
 		}
-		if v4 != 4.2 {
-			dbt.Errorf("failed to scan. %#v", v4)
+		if v3 != "t3" {
+			dbt.Errorf("failed to scan. %#v", v3)
 		}
 		dbt.mustFailDecimalSize(ct[3])
-		dbt.mustFailLength(ct[3])
+		if cLen = dbt.mustLength(ct[3]); cLen != 2 {
+			dbt.Errorf("failed to get length. %#v", ct[3])
+		}
 		if canNull := dbt.mustNullable(ct[3]); canNull {
 			dbt.Errorf("failed to get nullable. %#v", ct[3])
 		}
-		if !bytes.Equal(v5, []byte{0xab, 0xcd}) {
-			dbt.Errorf("failed to scan. %#v", v5)
+		if v4 != 4.2 {
+			dbt.Errorf("failed to scan. %#v", v4)
 		}
 		dbt.mustFailDecimalSize(ct[4])
-		if cLen = dbt.mustLength(ct[4]); cLen != 8388608 { // BINARY
-			dbt.Errorf("failed to get length. %#v", ct[4])
-		}
+		dbt.mustFailLength(ct[4])
 		if canNull := dbt.mustNullable(ct[4]); canNull {
 			dbt.Errorf("failed to get nullable. %#v", ct[4])
 		}
-		if !v6 {
-			dbt.Errorf("failed to scan. %#v", v6)
+		if !bytes.Equal(v5, []byte{0xab, 0xcd}) {
+			dbt.Errorf("failed to scan. %#v", v5)
 		}
 		dbt.mustFailDecimalSize(ct[5])
-		dbt.mustFailLength(ct[5])
-		/*canNull = dbt.mustNullable(ct[5])
-		if canNull {
+		if cLen = dbt.mustLength(ct[5]); cLen != 8388608 { // BINARY
+			dbt.Errorf("failed to get length. %#v", ct[5])
+		}
+		if canNull := dbt.mustNullable(ct[5]); canNull {
 			dbt.Errorf("failed to get nullable. %#v", ct[5])
-		}*/
+		}
+		if !v6 {
+			dbt.Errorf("failed to scan. %#v", v6)
+		}
+		dbt.mustFailDecimalSize(ct[6])
+		dbt.mustFailLength(ct[6])
 	})
 }
 
diff --git a/bindings_test.go b/bindings_test.go
index 20957de..59cb8b7 100644
--- a/bindings_test.go
+++ b/bindings_test.go
@@ -334,8 +334,8 @@ func TestBindingInterface(t *testing.T) {
 		if !rows.Next() {
 			dbt.Error("failed to query")
 		}
-		var v1, v2, v3, v4, v5, v6 any
-		if err := rows.Scan(&v1, &v2, &v3, &v4, &v5, &v6); err != nil {
+		var v1, v2, v2a, v3, v4, v5, v6 any
+		if err := rows.Scan(&v1, &v2, &v2a, &v3, &v4, &v5, &v6); err != nil {
 			dbt.Errorf("failed to scan: %#v", err)
 		}
 		if s1, ok := v1.(*big.Float); !ok || s1.Cmp(big.NewFloat(1.0)) != 0 {
@@ -344,6 +344,9 @@ func TestBindingInterface(t *testing.T) {
 		if s2, ok := v2.(int64); !ok || s2 != 2 {
 			dbt.Fatalf("failed to fetch. ok: %v, value: %v", ok, v2)
 		}
+		if s2a, ok := v2a.(*big.Int); !ok || big.NewInt(22).Cmp(s2a) != 0 {
+			dbt.Fatalf("failed to fetch. ok: %v, value: %v", ok, v2a)
+		}
 		if s3, ok := v3.(string); !ok || s3 != "t3" {
 			dbt.Fatalf("failed to fetch. ok: %v, value: %v", ok, v3)
 		}
@@ -362,8 +365,8 @@ func TestBindingInterfaceString(t *testing.T) {
 		if !rows.Next() {
 			dbt.Error("failed to query")
 		}
-		var v1, v2, v3, v4, v5, v6 any
-		if err := rows.Scan(&v1, &v2, &v3, &v4, &v5, &v6); err != nil {
+		var v1, v2, v2a, v3, v4, v5, v6 any
+		if err := rows.Scan(&v1, &v2, &v2a, &v3, &v4, &v5, &v6); err != nil {
 			dbt.Errorf("failed to scan: %#v", err)
 		}
 		if s, ok := v1.(string); !ok {
@@ -376,6 +379,9 @@ func TestBindingInterfaceString(t *testing.T) {
 		if s, ok := v2.(string); !ok || s != "2" {
 			dbt.Fatalf("failed to fetch. ok: %v, value: %v", ok, v2)
 		}
+		if s, ok := v2a.(string); !ok || s != "22" {
+			dbt.Fatalf("failed to fetch. ok: %v, value: %v", ok, v2a)
+		}
 		if s, ok := v3.(string); !ok || s != "t3" {
 			dbt.Fatalf("failed to fetch. ok: %v, value: %v", ok, v3)
 		}
@@ -1457,7 +1463,7 @@ func testInsertLOBData(t *testing.T, useArrowFormat bool, isLiteral bool) {
 	}{
 		{"C1", reflect.TypeOf("")},
 		{"C2", reflect.TypeOf("")},
-		{"C3", reflect.TypeOf(int64(0))},
+		{"C3", reflect.TypeOf("")},
 	}
 	testCases := []struct {
 		testDesc string
diff --git a/converter_test.go b/converter_test.go
index d1c1c20..ca3eef0 100644
--- a/converter_test.go
+++ b/converter_test.go
@@ -138,15 +138,22 @@ func TestGoTypeToSnowflake(t *testing.T) {
 
 func TestSnowflakeTypeToGo(t *testing.T) {
 	testcases := []struct {
-		in     snowflakeType
-		scale  int64
-		fields []fieldMetadata
-		out    reflect.Type
-		ctx    context.Context
+		in        snowflakeType
+		precision int64
+		scale     int64
+		fields    []fieldMetadata
+		out       reflect.Type
+		ctx       context.Context
 	}{
-		{in: fixedType, scale: 0, out: reflect.TypeOf(int64(0)), ctx: context.Background()},
+		{in: fixedType, precision: 1, scale: 0, out: reflect.TypeOf(int64(0)), ctx: context.Background()},
+		{in: fixedType, precision: 18, scale: 0, out: reflect.TypeOf(int64(0)), ctx: context.Background()},
+		{in: fixedType, precision: 19, scale: 0, out: reflect.TypeOf(""), ctx: context.Background()},
+		{in: fixedType, precision: 38, scale: 0, out: reflect.TypeOf(""), ctx: context.Background()},
 		{in: fixedType, scale: 2, out: reflect.TypeOf(float64(0)), ctx: context.Background()},
-		{in: fixedType, scale: 0, out: reflect.TypeOf(&big.Int{}), ctx: WithHigherPrecision(context.Background())},
+		{in: fixedType, precision: 1, scale: 0, out: reflect.TypeOf(int64(0)), ctx: WithHigherPrecision(context.Background())},
+		{in: fixedType, precision: 18, scale: 0, out: reflect.TypeOf(int64(0)), ctx: WithHigherPrecision(context.Background())},
+		{in: fixedType, precision: 19, scale: 0, out: reflect.TypeOf(&big.Int{}), ctx: WithHigherPrecision(context.Background())},
+		{in: fixedType, precision: 38, scale: 0, out: reflect.TypeOf(&big.Int{}), ctx: WithHigherPrecision(context.Background())},
 		{in: fixedType, scale: 2, out: reflect.TypeOf(&big.Float{}), ctx: WithHigherPrecision(context.Background())},
 		{in: realType, scale: 0, out: reflect.TypeOf(float64(0)), ctx: context.Background()},
 		{in: textType, scale: 0, out: reflect.TypeOf(""), ctx: context.Background()},
@@ -186,7 +193,7 @@ func TestSnowflakeTypeToGo(t *testing.T) {
 	}
 	for _, test := range testcases {
 		t.Run(fmt.Sprintf("%v_%v", test.in, test.out), func(t *testing.T) {
-			a := snowflakeTypeToGo(test.ctx, test.in, test.scale, test.fields)
+			a := snowflakeTypeToGo(test.ctx, test.in, test.precision, test.scale, test.fields)
 			if a != test.out {
 				t.Errorf("failed. in: %v, scale: %v, expected: %v, got: %v",
 					test.in, test.scale, test.out, a)
@@ -2495,3 +2502,139 @@ func TestSqlNull(t *testing.T) {
 		assertEqualE(t, nullStr, sql.Null[string]{Valid: true, V: "test"})
 	})
 }
+
+func TestNumbersScanType(t *testing.T) {
+	for _, forceFormat := range []string{forceJSON, forceARROW} {
+		t.Run(forceFormat, func(t *testing.T) {
+			runDBTest(t, func(dbt *DBTest) {
+				dbt.mustExecT(t, forceFormat)
+
+				t.Run("scale == 0", func(t *testing.T) {
+					t.Run("without higher precision", func(t *testing.T) {
+						rows := dbt.mustQueryContext(context.Background(), "SELECT 1, 300::NUMBER(15, 0), 600::NUMBER(18, 0), 700::NUMBER(19, 0), 900::NUMBER(38, 0), 123456789012345678901234567890")
+						defer rows.Close()
+						rows.mustNext()
+						var i1, i2, i3 int64
+						var i4, i5, i6 string
+						rows.mustScan(&i1, &i2, &i3, &i4, &i5, &i6)
+						assertEqualE(t, i1, int64(1))
+						assertEqualE(t, i2, int64(300))
+						assertEqualE(t, i3, int64(600))
+						assertEqualE(t, i4, "700")
+						assertEqualE(t, i5, "900")
+						assertEqualE(t, i6, "123456789012345678901234567890") // pragma: allowlist secret
+
+						types, err := rows.ColumnTypes()
+						assertNilF(t, err)
+						assertEqualE(t, types[0].ScanType(), reflect.TypeOf(int64(1)))
+						assertEqualE(t, types[1].ScanType(), reflect.TypeOf(int64(1)))
+						assertEqualE(t, types[2].ScanType(), reflect.TypeOf(int64(1)))
+						assertEqualE(t, types[3].ScanType(), reflect.TypeOf(""))
+						assertEqualE(t, types[4].ScanType(), reflect.TypeOf(""))
+						assertEqualE(t, types[5].ScanType(), reflect.TypeOf(""))
+					})
+
+					t.Run("without higher precision - regardless of scan type, int parsing should still work", func(t *testing.T) {
+						rows := dbt.mustQueryContext(context.Background(), "SELECT 1, 300::NUMBER(15, 0), 600::NUMBER(18, 0), 700::NUMBER(19, 0), 900::NUMBER(38, 0), 123456789012345678901234567890")
+						defer rows.Close()
+						rows.mustNext()
+						var i1, i2, i3, i4, i5 int64
+						var i6 string
+						rows.mustScan(&i1, &i2, &i3, &i4, &i5, &i6)
+						assertEqualE(t, i1, int64(1))
+						assertEqualE(t, i2, int64(300))
+						assertEqualE(t, i3, int64(600))
+						assertEqualE(t, i4, int64(700))
+						assertEqualE(t, i5, int64(900))
+						assertEqualE(t, i6, "123456789012345678901234567890") // pragma: allowlist secret
+
+						types, err := rows.ColumnTypes()
+						assertNilF(t, err)
+						assertEqualE(t, types[0].ScanType(), reflect.TypeOf(int64(1)))
+						assertEqualE(t, types[1].ScanType(), reflect.TypeOf(int64(1)))
+						assertEqualE(t, types[2].ScanType(), reflect.TypeOf(int64(1)))
+						assertEqualE(t, types[3].ScanType(), reflect.TypeOf(""))
+						assertEqualE(t, types[4].ScanType(), reflect.TypeOf(""))
+						assertEqualE(t, types[5].ScanType(), reflect.TypeOf(""))
+					})
+
+					t.Run("with higher precision", func(t *testing.T) {
+						rows := dbt.mustQueryContext(WithHigherPrecision(context.Background()), "SELECT 1::NUMBER(1, 0), 300::NUMBER(15, 0), 600::NUMBER(19, 0), 700::NUMBER(20, 0), 900::NUMBER(38, 0), 123456789012345678901234567890")
+						defer rows.Close()
+						rows.mustNext()
+						var i1, i2 int64
+						var i3, i4, i5, i6 *big.Int
+						rows.mustScan(&i1, &i2, &i3, &i4, &i5, &i6)
+						assertEqualE(t, i1, int64(1))
+						assertEqualE(t, i2, int64(300))
+						assertEqualE(t, i3.Cmp(big.NewInt(600)), 0)
+						assertEqualE(t, i4.Cmp(big.NewInt(700)), 0)
+						assertEqualE(t, i5.Cmp(big.NewInt(900)), 0)
+						bigInt123456789012345678901234567890 := &big.Int{}
+						bigInt123456789012345678901234567890.SetString("123456789012345678901234567890", 10) // pragma: allowlist secret
+						assertEqualE(t, i6.Cmp(bigInt123456789012345678901234567890), 0)
+
+						types, err := rows.ColumnTypes()
+						assertNilF(t, err)
+						assertEqualE(t, types[0].ScanType(), reflect.TypeOf(int64(1)))
+						assertEqualE(t, types[1].ScanType(), reflect.TypeOf(int64(1)))
+						assertEqualE(t, types[2].ScanType(), reflect.TypeOf(&big.Int{}))
+						assertEqualE(t, types[3].ScanType(), reflect.TypeOf(&big.Int{}))
+						assertEqualE(t, types[4].ScanType(), reflect.TypeOf(&big.Int{}))
+						assertEqualE(t, types[5].ScanType(), reflect.TypeOf(&big.Int{}))
+					})
+				})
+
+				t.Run("scale != 0", func(t *testing.T) {
+					t.Run("without higher precision", func(t *testing.T) {
+						rows := dbt.mustQueryContext(context.Background(), "SELECT 1.5, 300.5::NUMBER(15, 1), 600.5::NUMBER(18, 1), 700.5::NUMBER(19, 1), 900.5::NUMBER(38, 1), 123456789012345678901234567890.5")
+						defer rows.Close()
+						rows.mustNext()
+						var i1, i2, i3, i4, i5, i6 float64
+						rows.mustScan(&i1, &i2, &i3, &i4, &i5, &i6)
+						assertEqualE(t, i1, 1.5)
+						assertEqualE(t, i2, 300.5)
+						assertEqualE(t, i3, 600.5)
+						assertEqualE(t, i4, 700.5)
+						assertEqualE(t, i5, 900.5)
+						assertEqualE(t, i6, 123456789012345678901234567890.5)
+
+						types, err := rows.ColumnTypes()
+						assertNilF(t, err)
+						assertEqualE(t, types[0].ScanType(), reflect.TypeOf(1.5))
+						assertEqualE(t, types[1].ScanType(), reflect.TypeOf(1.5))
+						assertEqualE(t, types[2].ScanType(), reflect.TypeOf(1.5))
+						assertEqualE(t, types[3].ScanType(), reflect.TypeOf(1.5))
+						assertEqualE(t, types[4].ScanType(), reflect.TypeOf(1.5))
+						assertEqualE(t, types[5].ScanType(), reflect.TypeOf(1.5))
+					})
+
+					t.Run("with higher precision", func(t *testing.T) {
+						rows := dbt.mustQueryContext(WithHigherPrecision(context.Background()), "SELECT 1.5, 300.5::NUMBER(15, 1), 600.5::NUMBER(18, 1), 700.5::NUMBER(19, 1), 900.5::NUMBER(38, 1), 123456789012345678901234567890.5")
+						defer rows.Close()
+						rows.mustNext()
+						var i1, i2, i3, i4, i5, i6 *big.Float
+						rows.mustScan(&i1, &i2, &i3, &i4, &i5, &i6)
+						assertEqualE(t, i1.Cmp(big.NewFloat(1.5)), 0)
+						assertEqualE(t, i2.Cmp(big.NewFloat(300.5)), 0)
+						assertEqualE(t, i3.Cmp(big.NewFloat(600.5)), 0)
+						assertEqualE(t, i4.Cmp(big.NewFloat(700.5)), 0)
+						assertEqualE(t, i5.Cmp(big.NewFloat(900.5)), 0)
+						bigInt123456789012345678901234567890, _, err := big.ParseFloat("123456789012345678901234567890.5", 10, big.MaxPrec, big.AwayFromZero)
+						assertNilF(t, err)
+						assertEqualE(t, i6.Cmp(bigInt123456789012345678901234567890), 0)
+
+						types, err := rows.ColumnTypes()
+						assertNilF(t, err)
+						assertEqualE(t, types[0].ScanType(), reflect.TypeOf(&big.Float{}))
+						assertEqualE(t, types[1].ScanType(), reflect.TypeOf(&big.Float{}))
+						assertEqualE(t, types[2].ScanType(), reflect.TypeOf(&big.Float{}))
+						assertEqualE(t, types[3].ScanType(), reflect.TypeOf(&big.Float{}))
+						assertEqualE(t, types[4].ScanType(), reflect.TypeOf(&big.Float{}))
+						assertEqualE(t, types[5].ScanType(), reflect.TypeOf(&big.Float{}))
+					})
+				})
+			})
+		})
+	}
+}
diff --git a/driver_test.go b/driver_test.go
index 3979295..ddfb1eb 100644
--- a/driver_test.go
+++ b/driver_test.go
@@ -39,7 +39,7 @@ var (
 
 const (
 	selectNumberSQL       = "SELECT %s::NUMBER(%v, %v) AS C"
-	selectVariousTypes    = "SELECT 1.0::NUMBER(30,2) as C1, 2::NUMBER(38,0) AS C2, 't3' AS C3, 4.2::DOUBLE AS C4, 'abcd'::BINARY(8388608) AS C5, true AS C6"
+	selectVariousTypes    = "SELECT 1.0::NUMBER(30,2) as C1, 2::NUMBER(18,0) AS C2, 22::NUMBER(38, 0) AS C2A, 't3' AS C3, 4.2::DOUBLE AS C4, 'abcd'::BINARY(8388608) AS C5, true AS C6"
 	selectRandomGenerator = "SELECT SEQ8(), RANDSTR(1000, RANDOM()) FROM TABLE(GENERATOR(ROWCOUNT=>%v))"
 	PSTLocation           = "America/Los_Angeles"
 )
@@ -243,6 +243,7 @@ func (dbt *DBTest) mustQueryContextT(ctx context.Context, t *testing.T, query st
 	return &RowsExtended{
 		rows:      rs,
 		closeChan: &c0,
+		t:         t,
 	}
 }
 
diff --git a/old_driver_test.go b/old_driver_test.go
index 3b997ba..78ab879 100644
--- a/old_driver_test.go
+++ b/old_driver_test.go
@@ -40,19 +40,19 @@ func TestJSONVariousTypes(t *testing.T) {
 			dbt.Errorf("column types: %v", ct)
 		}
 		var v1 float32
-		var v2 int
+		var v2, v2a int
 		var v3 string
 		var v4 float64
 		var v5 []byte
 		var v6 bool
-		err = rows.Scan(&v1, &v2, &v3, &v4, &v5, &v6)
+		err = rows.Scan(&v1, &v2, &v2a, &v3, &v4, &v5, &v6)
 		if err != nil {
 			dbt.Errorf("failed to scan: %#v", err)
 		}
 		if v1 != 1.0 {
 			dbt.Errorf("failed to scan. %#v", v1)
 		}
-		if ct[0].Name() != "C1" || ct[1].Name() != "C2" || ct[2].Name() != "C3" || ct[3].Name() != "C4" || ct[4].Name() != "C5" || ct[5].Name() != "C6" {
+		if ct[0].Name() != "C1" || ct[1].Name() != "C2" || ct[2].Name() != "C2A" || ct[3].Name() != "C3" || ct[4].Name() != "C4" || ct[5].Name() != "C5" || ct[6].Name() != "C6" {
 			dbt.Errorf("failed to get column names: %#v", ct)
 		}
 		if ct[0].ScanType() != reflect.TypeOf(float64(0)) {
@@ -61,6 +61,7 @@ func TestJSONVariousTypes(t *testing.T) {
 		if ct[1].ScanType() != reflect.TypeOf(int64(0)) {
 			dbt.Errorf("failed to get scan type. expected: %v, got: %v", reflect.TypeOf(int64(0)), ct[1].ScanType())
 		}
+		assertEqualE(t, ct[2].ScanType(), reflect.TypeOf(""))
 		var pr, sc int64
 		var cLen int64
 		var canNull bool
@@ -80,7 +81,7 @@ func TestJSONVariousTypes(t *testing.T) {
 			dbt.Errorf("failed to scan. %#v", v2)
 		}
 		pr, sc = dbt.mustDecimalSize(ct[1])
-		if pr != 38 || sc != 0 {
+		if pr != 18 || sc != 0 {
 			dbt.Errorf("failed to get precision and scale. %#v", ct[1])
 		}
 		dbt.mustFailLength(ct[1])
@@ -88,49 +89,51 @@ func TestJSONVariousTypes(t *testing.T) {
 		if canNull {
 			dbt.Errorf("failed to get nullable. %#v", ct[1])
 		}
+		if v2a != 22 {
+			dbt.Errorf("failed to scan. %#v", v2a)
+		}
+		pr, sc = dbt.mustDecimalSize(ct[2])
+		if pr != 38 || sc != 0 {
+			dbt.Errorf("failed to get precision and scale. %#v", ct[2])
+		}
 		if v3 != "t3" {
 			dbt.Errorf("failed to scan. %#v", v3)
 		}
-		dbt.mustFailDecimalSize(ct[2])
-		cLen = dbt.mustLength(ct[2])
+		dbt.mustFailDecimalSize(ct[3])
+		cLen = dbt.mustLength(ct[3])
 		if cLen != 2 {
-			dbt.Errorf("failed to get length. %#v", ct[2])
+			dbt.Errorf("failed to get length. %#v", ct[3])
 		}
-		canNull = dbt.mustNullable(ct[2])
+		canNull = dbt.mustNullable(ct[3])
 		if canNull {
-			dbt.Errorf("failed to get nullable. %#v", ct[2])
+			dbt.Errorf("failed to get nullable. %#v", ct[3])
 		}
 		if v4 != 4.2 {
 			dbt.Errorf("failed to scan. %#v", v4)
 		}
-		dbt.mustFailDecimalSize(ct[3])
-		dbt.mustFailLength(ct[3])
-		canNull = dbt.mustNullable(ct[3])
+		dbt.mustFailDecimalSize(ct[4])
+		dbt.mustFailLength(ct[4])
+		canNull = dbt.mustNullable(ct[4])
 		if canNull {
-			dbt.Errorf("failed to get nullable. %#v", ct[3])
+			dbt.Errorf("failed to get nullable. %#v", ct[4])
 		}
 		if !bytes.Equal(v5, []byte{0xab, 0xcd}) {
 			dbt.Errorf("failed to scan. %#v", v5)
 		}
-		dbt.mustFailDecimalSize(ct[4])
-		cLen = dbt.mustLength(ct[4]) // BINARY
+		dbt.mustFailDecimalSize(ct[5])
+		cLen = dbt.mustLength(ct[5]) // BINARY
 		if cLen != 8388608 {
-			dbt.Errorf("failed to get length. %#v", ct[4])
+			dbt.Errorf("failed to get length. %#v", ct[5])
 		}
-		canNull = dbt.mustNullable(ct[4])
+		canNull = dbt.mustNullable(ct[5])
 		if canNull {
-			dbt.Errorf("failed to get nullable. %#v", ct[4])
+			dbt.Errorf("failed to get nullable. %#v", ct[5])
 		}
 		if !v6 {
 			dbt.Errorf("failed to scan. %#v", v6)
 		}
-		dbt.mustFailDecimalSize(ct[5])
-		dbt.mustFailLength(ct[5])
-		/*canNull = dbt.mustNullable(ct[5])
-		if canNull {
-			dbt.Errorf("failed to get nullable. %#v", ct[5])
-		}*/
-
+		dbt.mustFailDecimalSize(ct[6])
+		dbt.mustFailLength(ct[6])
 	})
 }
 
@@ -184,8 +187,8 @@ func TestBindingJSONInterface(t *testing.T) {
 		if !rows.Next() {
 			dbt.Error("failed to query")
 		}
-		var v1, v2, v3, v4, v5, v6 interface{}
-		if err := rows.Scan(&v1, &v2, &v3, &v4, &v5, &v6); err != nil {
+		var v1, v2, v2a, v3, v4, v5, v6 interface{}
+		if err := rows.Scan(&v1, &v2, &v2a, &v3, &v4, &v5, &v6); err != nil {
 			dbt.Errorf("failed to scan: %#v", err)
 		}
 		if s, ok := v1.(string); !ok || s != "1.00" {
diff --git a/rows_test.go b/rows_test.go
index 351b7e0..7f478be 100644
--- a/rows_test.go
+++ b/rows_test.go
@@ -15,6 +15,7 @@ import (
 type RowsExtended struct {
 	rows      *sql.Rows
 	closeChan *chan bool
+	t *testing.T
 }
 
 func (rs *RowsExtended) Close() error {
@@ -39,6 +40,10 @@ func (rs *RowsExtended) Next() bool {
 	return rs.rows.Next()
 }
 
+func (rs *RowsExtended) mustNext() {
+	assertTrueF(rs.t, rs.rows.Next())
+}
+
 func (rs *RowsExtended) NextResultSet() bool {
 	return rs.rows.NextResultSet()
 }
@@ -47,6 +52,11 @@ func (rs *RowsExtended) Scan(dest ...interface{}) error {
 	return rs.rows.Scan(dest...)
 }
 
+func (rs *RowsExtended) mustScan(dest ...interface{}) {
+	err := rs.rows.Scan(dest...)
+	assertNilF(rs.t, err)
+}
+
 // test variables
 var (
 	rowsInChunk = 123