Skip to content

Commit bd9aa25

Browse files
SNOW-969719: Increased max LOB size complete testing (#1047)
Added tests for increased LOB size and increased test timeout from 30m to 50m.
1 parent 400b315 commit bd9aa25

File tree

5 files changed

+268
-3
lines changed

5 files changed

+268
-3
lines changed

bindings_test.go

+169
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@ const (
3434
deleteTableSQLBulkArrayDateTimeTimestamp = "drop table if exists test_bulk_array_DateTimeTimestamp"
3535
insertSQLBulkArrayDateTimeTimestamp = "insert into test_bulk_array_DateTimeTimestamp values(?, ?, ?, ?, ?)"
3636
selectAllSQLBulkArrayDateTimeTimestamp = "select * from test_bulk_array_DateTimeTimestamp ORDER BY 1"
37+
38+
enableFeatureMaxLOBSize = "ALTER SESSION SET FEATURE_INCREASED_MAX_LOB_SIZE_IN_MEMORY='ENABLED'"
39+
unsetFeatureMaxLOBSize = "ALTER SESSION UNSET FEATURE_INCREASED_MAX_LOB_SIZE_IN_MEMORY"
40+
41+
// For max LOB size tests
42+
// maxLOBSize = 128 * 1024 * 1024 // new max LOB size
43+
maxLOBSize = 16 * 1024 * 1024 // current max LOB size
44+
largeSize = maxLOBSize / 2
45+
mediumSize = largeSize / 2
46+
originSize = 16 * 1024 * 1024
47+
smallSize = 16
48+
// range to use for generating random numbers
49+
lobRandomRange = 100000
3750
)
3851

3952
func TestBindingFloat64(t *testing.T) {
@@ -975,6 +988,11 @@ func TestVariousBindingModes(t *testing.T) {
975988
{"timestamp_ntzAndTypedNullTime", "timestamp_ntz", TypedNullTime{sql.NullTime{}, TimestampNTZType}, true},
976989
{"timestamp_ltzAndTypedNullTime", "timestamp_ltz", TypedNullTime{sql.NullTime{}, TimestampLTZType}, true},
977990
{"timestamp_tzAndTypedNullTime", "timestamp_tz", TypedNullTime{sql.NullTime{}, TimestampTZType}, true},
991+
{"LOBSmallSize", fmt.Sprintf("varchar(%v)", smallSize), randomString(smallSize), false},
992+
{"LOBOriginSize", fmt.Sprintf("varchar(%v)", originSize), randomString(originSize), false},
993+
{"LOBMediumSize", fmt.Sprintf("varchar(%v)", mediumSize), randomString(mediumSize), false},
994+
{"LOBLargeSize", fmt.Sprintf("varchar(%v)", largeSize), randomString(largeSize), false},
995+
{"LOBMaxSize", fmt.Sprintf("varchar(%v)", maxLOBSize), randomString(maxLOBSize), false},
978996
}
979997

980998
bindingModes := []struct {
@@ -1023,3 +1041,154 @@ func TestVariousBindingModes(t *testing.T) {
10231041
}
10241042
})
10251043
}
1044+
1045+
func TestLOBRetrievalWithArrow(t *testing.T) {
1046+
testLOBRetrieval(t, true)
1047+
}
1048+
1049+
func TestLOBRetrievalWithJSON(t *testing.T) {
1050+
testLOBRetrieval(t, false)
1051+
}
1052+
1053+
func testLOBRetrieval(t *testing.T, useArrowFormat bool) {
1054+
// the LOB sizes to be tested
1055+
testSizes := [5]int{smallSize, originSize, mediumSize, largeSize, maxLOBSize}
1056+
var res string
1057+
1058+
runDBTest(t, func(dbt *DBTest) {
1059+
dbt.exec(enableFeatureMaxLOBSize)
1060+
if useArrowFormat {
1061+
dbt.mustExec(forceARROW)
1062+
} else {
1063+
dbt.mustExec(forceJSON)
1064+
}
1065+
1066+
for _, testSize := range testSizes {
1067+
t.Run(fmt.Sprintf("testLOB_%v_useArrowFormat=%v", strconv.Itoa(testSize), strconv.FormatBool(useArrowFormat)), func(t *testing.T) {
1068+
rows, err := dbt.query(fmt.Sprintf("SELECT randstr(%v, 124)", testSize))
1069+
assertNilF(t, err)
1070+
defer rows.Close()
1071+
assertTrueF(t, rows.Next(), fmt.Sprintf("no rows returned for the LOB size %v", testSize))
1072+
1073+
// retrieve the result
1074+
err = rows.Scan(&res)
1075+
assertNilF(t, err)
1076+
1077+
// verify the length of the result
1078+
assertEqualF(t, len(res), testSize)
1079+
})
1080+
}
1081+
dbt.exec(unsetFeatureMaxLOBSize)
1082+
})
1083+
}
1084+
1085+
func TestInsertLobDataWithLiteralArrow(t *testing.T) {
1086+
testInsertLOBData(t, true, true)
1087+
}
1088+
1089+
func TestInsertLobDataWithLiteralJSON(t *testing.T) {
1090+
testInsertLOBData(t, false, true)
1091+
}
1092+
1093+
func TestInsertLobDataWithBindingsArrow(t *testing.T) {
1094+
testInsertLOBData(t, true, false)
1095+
}
1096+
1097+
func TestInsertLobDataWithBindingsJSON(t *testing.T) {
1098+
testInsertLOBData(t, false, false)
1099+
}
1100+
1101+
func testInsertLOBData(t *testing.T, useArrowFormat bool, isLiteral bool) {
1102+
expectedNumCols := 3
1103+
columnMeta := []struct {
1104+
columnName string
1105+
columnType reflect.Type
1106+
}{
1107+
{"C1", reflect.TypeOf("")},
1108+
{"C2", reflect.TypeOf("")},
1109+
{"C3", reflect.TypeOf(int64(0))},
1110+
}
1111+
testCases := []struct {
1112+
testDesc string
1113+
c1Size int
1114+
c2Size int
1115+
c3Size int
1116+
}{
1117+
{"testLOBInsertSmallSize", smallSize, smallSize, lobRandomRange},
1118+
{"testLOBInsertOriginSize", originSize, originSize, lobRandomRange},
1119+
{"testLOBInsertMediumSize", mediumSize, originSize, lobRandomRange},
1120+
{"testLOBInsertLargeSize", largeSize, originSize, lobRandomRange},
1121+
{"testLOBInsertMaxSize", maxLOBSize, originSize, lobRandomRange},
1122+
}
1123+
1124+
runDBTest(t, func(dbt *DBTest) {
1125+
var c1 string
1126+
var c2 string
1127+
var c3 int
1128+
1129+
dbt.exec(enableFeatureMaxLOBSize)
1130+
if useArrowFormat {
1131+
dbt.mustExec(forceARROW)
1132+
} else {
1133+
dbt.mustExec(forceJSON)
1134+
}
1135+
1136+
for _, tc := range testCases {
1137+
t.Run(tc.testDesc, func(t *testing.T) {
1138+
// initialize test data
1139+
c1Data := randomString(tc.c1Size)
1140+
c2Data := randomString(tc.c2Size)
1141+
c3Data := rand.Intn(tc.c3Size)
1142+
1143+
dbt.mustExec(fmt.Sprintf("CREATE OR REPLACE TABLE lob_test_table (c1 varchar(%v), c2 varchar(%v), c3 int)", tc.c1Size, tc.c2Size))
1144+
if isLiteral {
1145+
dbt.mustExec(fmt.Sprintf("INSERT INTO lob_test_table VALUES ('%s', '%s', %v)", c1Data, c2Data, c3Data))
1146+
} else {
1147+
dbt.mustExec("INSERT INTO lob_test_table VALUES (?, ?, ?)", c1Data, c2Data, c3Data)
1148+
}
1149+
rows, err := dbt.query("SELECT * FROM lob_test_table")
1150+
assertNilF(t, err)
1151+
defer rows.Close()
1152+
assertTrueF(t, rows.Next(), fmt.Sprintf("%s: no rows returned", tc.testDesc))
1153+
1154+
err = rows.Scan(&c1, &c2, &c3)
1155+
assertNilF(t, err)
1156+
1157+
// check the number of columns
1158+
columnTypes, err := rows.ColumnTypes()
1159+
assertNilF(t, err)
1160+
assertEqualF(t, len(columnTypes), expectedNumCols)
1161+
1162+
// verify the column metadata: name, type and length
1163+
for colIdx := 0; colIdx < expectedNumCols; colIdx++ {
1164+
colName := columnTypes[colIdx].Name()
1165+
assertEqualF(t, colName, columnMeta[colIdx].columnName)
1166+
1167+
colType := columnTypes[colIdx].ScanType()
1168+
assertEqualF(t, colType, columnMeta[colIdx].columnType)
1169+
1170+
colLength, ok := columnTypes[colIdx].Length()
1171+
1172+
switch colIdx {
1173+
case 0:
1174+
assertTrueF(t, ok)
1175+
assertEqualF(t, colLength, int64(tc.c1Size))
1176+
// verify the data
1177+
assertEqualF(t, c1, c1Data)
1178+
case 1:
1179+
assertTrueF(t, ok)
1180+
assertEqualF(t, colLength, int64(tc.c2Size))
1181+
// verify the data
1182+
assertEqualF(t, c2, c2Data)
1183+
case 2:
1184+
assertFalseF(t, ok)
1185+
// verify the data
1186+
assertEqualF(t, c3, c3Data)
1187+
}
1188+
}
1189+
})
1190+
dbt.mustExec("DROP TABLE IF EXISTS lob_test_table")
1191+
}
1192+
dbt.exec(unsetFeatureMaxLOBSize)
1193+
})
1194+
}

ci/scripts/test_component.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ if [[ -n "$GITHUB_WORKFLOW" ]]; then
1212
fi
1313
env | grep SNOWFLAKE | grep -v PASS | sort
1414
cd $TOPDIR
15-
go test -timeout 30m -race -coverprofile=coverage.txt -covermode=atomic -v .
15+
go test -timeout 50m -race -coverprofile=coverage.txt -covermode=atomic -v .

ci/test.bat

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,4 @@ echo [INFO] Database: %SNOWFLAKE_TEST_DATABASE%
4242
echo [INFO] Warehouse: %SNOWFLAKE_TEST_WAREHOUSE%
4343
echo [INFO] Role: %SNOWFLAKE_TEST_ROLE%
4444

45-
go test --timeout 30m --tags=sfdebug -race -coverprofile=coverage.txt -covermode=atomic -v .
45+
go test --timeout 50m --tags=sfdebug -race -coverprofile=coverage.txt -covermode=atomic -v .

old_driver_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import (
99
)
1010

1111
const (
12-
forceJSON = "ALTER SESSION SET GO_QUERY_RESULT_FORMAT = JSON"
12+
forceARROW = "ALTER SESSION SET GO_QUERY_RESULT_FORMAT = ARROW"
13+
forceJSON = "ALTER SESSION SET GO_QUERY_RESULT_FORMAT = JSON"
1314
)
1415

1516
func TestJSONInt(t *testing.T) {

put_get_test.go

+95
Original file line numberDiff line numberDiff line change
@@ -650,3 +650,98 @@ func TestPutLargeFile(t *testing.T) {
650650

651651
})
652652
}
653+
654+
func TestPutGetMaxLOBSize(t *testing.T) {
655+
// the LOB sizes to be tested
656+
testCases := [5]int{smallSize, originSize, mediumSize, largeSize, maxLOBSize}
657+
658+
runDBTest(t, func(dbt *DBTest) {
659+
for _, tc := range testCases {
660+
// create the data file
661+
tmpDir := t.TempDir()
662+
fname := filepath.Join(tmpDir, "test_put_get.txt.gz")
663+
tableName := randomString(5)
664+
originalContents := fmt.Sprintf("%v,%s,%v\n", randomString(tc), randomString(tc), rand.Intn(100000))
665+
666+
var b bytes.Buffer
667+
gzw := gzip.NewWriter(&b)
668+
gzw.Write([]byte(originalContents))
669+
gzw.Close()
670+
err := os.WriteFile(fname, b.Bytes(), readWriteFileMode)
671+
assertNilF(t, err, "could not write to gzip file")
672+
673+
dbt.mustExec(fmt.Sprintf("create or replace table %s (c1 varchar, c2 varchar(%v), c3 int)", tableName, tc))
674+
defer dbt.mustExec("drop table " + tableName)
675+
fileStream, err := os.Open(fname)
676+
assertNilF(t, err)
677+
defer fileStream.Close()
678+
679+
// test PUT command
680+
var sqlText string
681+
var rows *RowsExtended
682+
sql := "put 'file://%v' @%%%v auto_compress=true parallel=30"
683+
sqlText = fmt.Sprintf(
684+
sql, strings.ReplaceAll(fname, "\\", "\\\\"), tableName)
685+
rows = dbt.mustQuery(sqlText)
686+
defer rows.Close()
687+
688+
var s0, s1, s2, s3, s4, s5, s6, s7 string
689+
assertTrueF(t, rows.Next(), "expected new rows")
690+
err = rows.Scan(&s0, &s1, &s2, &s3, &s4, &s5, &s6, &s7)
691+
assertNilF(t, err)
692+
assertEqualF(t, s6, uploaded.String(), fmt.Sprintf("expected %v, got: %v", uploaded, s6))
693+
assertNilF(t, err)
694+
695+
// check file is PUT
696+
dbt.mustQueryAssertCount("ls @%"+tableName, 1)
697+
698+
dbt.mustExec("copy into " + tableName)
699+
dbt.mustExec("rm @%" + tableName)
700+
dbt.mustQueryAssertCount("ls @%"+tableName, 0)
701+
702+
dbt.mustExec(fmt.Sprintf(`copy into @%%%v from %v file_format=(type=csv
703+
compression='gzip')`, tableName, tableName))
704+
705+
// test GET command
706+
sql = fmt.Sprintf("get @%%%v 'file://%v'", tableName, tmpDir)
707+
sqlText = strings.ReplaceAll(sql, "\\", "\\\\")
708+
rows2 := dbt.mustQuery(sqlText)
709+
defer rows2.Close()
710+
for rows2.Next() {
711+
err = rows2.Scan(&s0, &s1, &s2, &s3)
712+
assertNilE(t, err)
713+
assertTrueF(t, strings.HasPrefix(s0, "data_"), "a file was not downloaded by GET")
714+
assertEqualE(t, s2, "DOWNLOADED", "did not return DOWNLOADED status")
715+
assertEqualE(t, s3, "", fmt.Sprintf("returned %v", s3))
716+
}
717+
718+
// verify the content in the file
719+
files, err := filepath.Glob(filepath.Join(tmpDir, "data_*"))
720+
assertNilF(t, err)
721+
722+
fileName := files[0]
723+
f, err := os.Open(fileName)
724+
assertNilE(t, err)
725+
726+
defer f.Close()
727+
gz, err := gzip.NewReader(f)
728+
assertNilE(t, err)
729+
730+
defer gz.Close()
731+
var contents string
732+
for {
733+
c := make([]byte, defaultChunkBufferSize)
734+
if n, err := gz.Read(c); err != nil {
735+
if err == io.EOF {
736+
contents = contents + string(c[:n])
737+
break
738+
}
739+
t.Error(err)
740+
} else {
741+
contents = contents + string(c[:n])
742+
}
743+
}
744+
assertEqualE(t, contents, originalContents, "output is different from the original file")
745+
}
746+
})
747+
}

0 commit comments

Comments
 (0)