Repository: snowflakedb/gosnowflake
Pull request #554 (2022-02-22 19:43:08)

SNOW-546088 Export UUID
### Description
Fixes https://github.com/snowflakedb/gosnowflake/issues/552

### Checklist
- [x] Code compiles correctly
- [x] Run ``make fmt`` to fix inconsistent formats
- [x] Run ``make lint`` to get lint errors and fix all of them
- [x] Created tests which fail without the change (if possible)
- [x] All tests passing
- [x] Extended the README / documentation, if necessary



Patch:
diff --git a/auth.go b/auth.go
index 1ca6614..0c3317c 100644
--- a/auth.go
+++ b/auth.go
@@ -198,7 +198,7 @@ func postAuth(
 	timeout time.Duration) (
 	data *authResponse, err error) {
 	params.Add(requestIDKey, getOrGenerateRequestIDFromContext(ctx).String())
-	params.Add(requestGUIDKey, newUUID().String())
+	params.Add(requestGUIDKey, NewUUID().String())
 
 	fullURL := sr.getFullURL(loginRequestPath, params)
 	logger.Infof("full URL: %v", fullURL)
diff --git a/bind_uploader.go b/bind_uploader.go
index e348907..905f9c2 100644
--- a/bind_uploader.go
+++ b/bind_uploader.go
@@ -171,7 +171,7 @@ func (sc *snowflakeConn) processBindings(
 	ctx context.Context,
 	bindings []driver.NamedValue,
 	describeOnly bool,
-	requestID uuid,
+	requestID UUID,
 	req *execRequest) error {
 	arrayBindThreshold := sc.getArrayBindStageThreshold()
 	numBinds := arrayBindValueCount(bindings)
diff --git a/converter.go b/converter.go
index a1fc2f3..c77c8b0 100644
--- a/converter.go
+++ b/converter.go
@@ -289,32 +289,6 @@ func decimalToBigFloat(num decimal128.Num, scale int64) *big.Float {
 	return new(big.Float).Quo(f, s)
 }
 
-func stringIntToDecimal(src string) (decimal128.Num, bool) {
-	b, ok := new(big.Int).SetString(src, 10)
-	if !ok {
-		return decimal128.Num{}, ok
-	}
-	var high, low big.Int
-	high.QuoRem(b, decimalShift, &low)
-	return decimal128.New(high.Int64(), low.Uint64()), ok
-}
-
-func stringFloatToDecimal(src string, scale int64) (decimal128.Num, bool) {
-	b, ok := new(big.Float).SetString(src)
-	if !ok {
-		return decimal128.Num{}, ok
-	}
-	s := new(big.Float).SetInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(scale), nil))
-	n := new(big.Float).Mul(b, s)
-	if !n.IsInt() {
-		return decimal128.Num{}, false
-	}
-	var high, low, z big.Int
-	n.Int(&z)
-	high.QuoRem(&z, decimalShift, &low)
-	return decimal128.New(high.Int64(), low.Uint64()), ok
-}
-
 // Arrow Interface (Column) converter. This is called when Arrow chunks are
 // downloaded to convert to the corresponding row type.
 func arrowToValue(
diff --git a/doc.go b/doc.go
index 88791a2..cfc9fc5 100644
--- a/doc.go
+++ b/doc.go
@@ -160,7 +160,7 @@ Query request ID
 A specific query request ID can be set in the context and will be passed through
 in place of the default randomized request ID. For example:
 
-	requestID := uuid.MustParse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
+	requestID := ParseUUID("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
 	ctxWithID := WithRequestID(ctx, requestID)
 	rows, err := db.QueryContext(ctxWithID, query)
 
diff --git a/heartbeat.go b/heartbeat.go
index e475a4f..28e01be 100644
--- a/heartbeat.go
+++ b/heartbeat.go
@@ -54,8 +54,8 @@ func (hc *heartbeat) stop() {
 func (hc *heartbeat) heartbeatMain() error {
 	logger.Info("Heartbeating!")
 	params := &url.Values{}
-	params.Add(requestIDKey, newUUID().String())
-	params.Add(requestGUIDKey, newUUID().String())
+	params.Add(requestIDKey, NewUUID().String())
+	params.Add(requestGUIDKey, NewUUID().String())
 	headers := getHeaders()
 	token, _, _ := hc.restful.TokenAccessor.GetTokens()
 	headers[headerAuthorizationKey] = fmt.Sprintf(headerSnowflakeToken, token)
diff --git a/monitoring.go b/monitoring.go
index fdf07d3..68d123b 100644
--- a/monitoring.go
+++ b/monitoring.go
@@ -133,7 +133,7 @@ func (sc *snowflakeConn) checkQueryStatus(
 	*retStatus, error) {
 	headers := make(map[string]string)
 	param := make(url.Values)
-	param.Add(requestGUIDKey, newUUID().String())
+	param.Add(requestGUIDKey, NewUUID().String())
 	if tok, _, _ := sc.rest.TokenAccessor.GetTokens(); tok != "" {
 		headers[headerAuthorizationKey] = fmt.Sprintf(headerSnowflakeToken, tok)
 	}
@@ -206,7 +206,7 @@ func (sc *snowflakeConn) getQueryResultResp(
 	param := make(url.Values)
 	param.Add(requestIDKey, getOrGenerateRequestIDFromContext(ctx).String())
 	param.Add("clientStartTime", strconv.FormatInt(time.Now().Unix(), 10))
-	param.Add(requestGUIDKey, newUUID().String())
+	param.Add(requestGUIDKey, NewUUID().String())
 	token, _, _ := sc.rest.TokenAccessor.GetTokens()
 	if token != "" {
 		headers[headerAuthorizationKey] = fmt.Sprintf(headerSnowflakeToken, token)
diff --git a/ocsp.go b/ocsp.go
index 5bd3420..0fbe455 100644
--- a/ocsp.go
+++ b/ocsp.go
@@ -287,13 +287,6 @@ func deleteOCSPCache(encodedCertID *certIDKey) {
 	ocspResponseCacheLock.Unlock()
 }
 
-// deleteOCSPCacheAll deletes all entries in the OCSP response cache on memory
-func deleteOCSPCacheAll() {
-	ocspResponseCacheLock.Lock()
-	defer ocspResponseCacheLock.Unlock()
-	ocspResponseCache = make(map[certIDKey][]interface{})
-}
-
 func validateOCSP(ocspRes *ocsp.Response) *ocspStatus {
 	curTime := time.Now()
 
@@ -931,11 +924,6 @@ func createOCSPCacheDir() {
 	logger.Infof("reset OCSP cache file. %v", cacheFileName)
 }
 
-// deleteOCSPCacheFile deletes the OCSP response cache file
-func deleteOCSPCacheFile() {
-	os.Remove(cacheFileName)
-}
-
 func init() {
 	readCACerts()
 	createOCSPCacheDir()
diff --git a/restful.go b/restful.go
index 478d232..fd17440 100644
--- a/restful.go
+++ b/restful.go
@@ -59,14 +59,14 @@ type snowflakeRestful struct {
 
 	Connection *snowflakeConn
 
-	FuncPostQuery       func(context.Context, *snowflakeRestful, *url.Values, map[string]string, []byte, time.Duration, uuid, *Config) (*execResponse, error)
-	FuncPostQueryHelper func(context.Context, *snowflakeRestful, *url.Values, map[string]string, []byte, time.Duration, uuid, *Config) (*execResponse, error)
+	FuncPostQuery       func(context.Context, *snowflakeRestful, *url.Values, map[string]string, []byte, time.Duration, UUID, *Config) (*execResponse, error)
+	FuncPostQueryHelper func(context.Context, *snowflakeRestful, *url.Values, map[string]string, []byte, time.Duration, UUID, *Config) (*execResponse, error)
 	FuncPost            funcPostType
 	FuncGet             funcGetType
 	FuncRenewSession    func(context.Context, *snowflakeRestful, time.Duration) error
 	FuncPostAuth        func(context.Context, *snowflakeRestful, *url.Values, map[string]string, []byte, time.Duration) (*authResponse, error)
 	FuncCloseSession    func(context.Context, *snowflakeRestful, time.Duration) error
-	FuncCancelQuery     func(context.Context, *snowflakeRestful, uuid, time.Duration) error
+	FuncCancelQuery     func(context.Context, *snowflakeRestful, UUID, time.Duration) error
 
 	FuncPostAuthSAML func(context.Context, *snowflakeRestful, map[string]string, []byte, time.Duration) (*authResponse, error)
 	FuncPostAuthOKTA func(context.Context, *snowflakeRestful, map[string]string, []byte, string, time.Duration) (*authOKTAResponse, error)
@@ -168,7 +168,7 @@ func postRestfulQuery(
 	headers map[string]string,
 	body []byte,
 	timeout time.Duration,
-	requestID uuid,
+	requestID UUID,
 	cfg *Config) (
 	data *execResponse, err error) {
 
@@ -192,13 +192,13 @@ func postRestfulQueryHelper(
 	headers map[string]string,
 	body []byte,
 	timeout time.Duration,
-	requestID uuid,
+	requestID UUID,
 	cfg *Config) (
 	data *execResponse, err error) {
 	logger.Infof("params: %v", params)
 	params.Add(requestIDKey, requestID.String())
 	params.Add("clientStartTime", strconv.FormatInt(time.Now().Unix(), 10))
-	params.Add(requestGUIDKey, newUUID().String())
+	params.Add(requestGUIDKey, NewUUID().String())
 	token, _, _ := sr.TokenAccessor.GetTokens()
 	if token != "" {
 		headers[headerAuthorizationKey] = fmt.Sprintf(headerSnowflakeToken, token)
@@ -291,7 +291,7 @@ func closeSession(ctx context.Context, sr *snowflakeRestful, timeout time.Durati
 	params := &url.Values{}
 	params.Add("delete", "true")
 	params.Add(requestIDKey, getOrGenerateRequestIDFromContext(ctx).String())
-	params.Add(requestGUIDKey, newUUID().String())
+	params.Add(requestGUIDKey, NewUUID().String())
 	fullURL := sr.getFullURL(sessionRequestPath, params)
 
 	headers := getHeaders()
@@ -340,7 +340,7 @@ func renewRestfulSession(ctx context.Context, sr *snowflakeRestful, timeout time
 	logger.WithContext(ctx).Info("start renew session")
 	params := &url.Values{}
 	params.Add(requestIDKey, getOrGenerateRequestIDFromContext(ctx).String())
-	params.Add(requestGUIDKey, newUUID().String())
+	params.Add(requestGUIDKey, NewUUID().String())
 	fullURL := sr.getFullURL(tokenRequestPath, params)
 
 	token, masterToken, _ := sr.TokenAccessor.GetTokens()
@@ -409,11 +409,11 @@ func getCancelRetry(ctx context.Context) int {
 	return cnt
 }
 
-func cancelQuery(ctx context.Context, sr *snowflakeRestful, requestID uuid, timeout time.Duration) error {
+func cancelQuery(ctx context.Context, sr *snowflakeRestful, requestID UUID, timeout time.Duration) error {
 	logger.WithContext(ctx).Info("cancel query")
 	params := &url.Values{}
 	params.Add(requestIDKey, getOrGenerateRequestIDFromContext(ctx).String())
-	params.Add(requestGUIDKey, newUUID().String())
+	params.Add(requestGUIDKey, NewUUID().String())
 
 	fullURL := sr.getFullURL(abortRequestPath, params)
 
diff --git a/retry.go b/retry.go
index 9d2b7a4..efc0318 100644
--- a/retry.go
+++ b/retry.go
@@ -75,11 +75,11 @@ type requestGUIDReplace struct {
 
 /**
 This function would replace they value of the requestGUIDKey in a url with a newly
-generated uuid
+generated UUID
 */
 func (replacer *requestGUIDReplace) replace() *url.URL {
 	replacer.urlValues.Del(requestGUIDKey)
-	replacer.urlValues.Add(requestGUIDKey, newUUID().String())
+	replacer.urlValues.Add(requestGUIDKey, NewUUID().String())
 	replacer.urlPtr.RawQuery = replacer.urlValues.Encode()
 	return replacer.urlPtr
 }
diff --git a/util.go b/util.go
index cdcf79b..df54d7c 100644
--- a/util.go
+++ b/util.go
@@ -6,7 +6,6 @@ import (
 	"context"
 	"database/sql/driver"
 	"io"
-	"math/rand"
 	"strings"
 	"sync"
 	"time"
@@ -48,7 +47,7 @@ func WithQueryIDChan(ctx context.Context, c chan<- string) context.Context {
 }
 
 // WithRequestID returns a new context with the specified snowflake request id
-func WithRequestID(ctx context.Context, requestID uuid) context.Context {
+func WithRequestID(ctx context.Context, requestID UUID) context.Context {
 	return context.WithValue(ctx, snowflakeRequestIDKey, requestID)
 }
 
@@ -91,12 +90,12 @@ func WithArrowBatches(ctx context.Context) context.Context {
 }
 
 // Get the request ID from the context if specified, otherwise generate one
-func getOrGenerateRequestIDFromContext(ctx context.Context) uuid {
-	requestID, ok := ctx.Value(snowflakeRequestIDKey).(uuid)
+func getOrGenerateRequestIDFromContext(ctx context.Context) UUID {
+	requestID, ok := ctx.Value(snowflakeRequestIDKey).(UUID)
 	if ok && requestID != nilUUID {
 		return requestID
 	}
-	return newUUID()
+	return NewUUID()
 }
 
 // integer min
@@ -213,13 +212,3 @@ func escapeForCSV(value string) string {
 	}
 	return value
 }
-
-func randomString(n int) string {
-	rand.Seed(time.Now().UnixNano())
-	alpha := []rune("abcdefghijklmnopqrstuvwxyz")
-	b := make([]rune, n)
-	for i := range b {
-		b[i] = alpha[rand.Intn(len(alpha))]
-	}
-	return string(b)
-}
diff --git a/uuid.go b/uuid.go
index 601175e..1f55cc1 100644
--- a/uuid.go
+++ b/uuid.go
@@ -5,16 +5,19 @@ package gosnowflake
 import (
 	"crypto/rand"
 	"fmt"
+	"strconv"
 )
 
 const rfc4122 = 0x40
 
-type uuid [16]byte
+// UUID is a RFC4122 compliant uuid type
+type UUID [16]byte
 
-var nilUUID uuid
+var nilUUID UUID
 
-func newUUID() uuid {
-	var u uuid
+// NewUUID creates a new snowflake UUID
+func NewUUID() UUID {
+	var u UUID
 	rand.Read(u[:])
 	u[8] = (u[8] | rfc4122) & 0x7F
 
@@ -23,6 +26,22 @@ func newUUID() uuid {
 	return u
 }
 
-func (u uuid) String() string {
+func getChar(str string) byte {
+	i, _ := strconv.ParseUint(str, 16, 8)
+	return byte(i)
+}
+
+// ParseUUID parses a string of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx into its UUID form
+func ParseUUID(str string) UUID {
+	return UUID{
+		getChar(str[0:2]), getChar(str[2:4]), getChar(str[4:6]), getChar(str[6:8]),
+		getChar(str[9:11]), getChar(str[11:13]),
+		getChar(str[14:16]), getChar(str[16:18]),
+		getChar(str[19:21]), getChar(str[21:23]),
+		getChar(str[24:26]), getChar(str[26:28]), getChar(str[28:30]), getChar(str[30:32]), getChar(str[32:34]), getChar(str[34:36]),
+	}
+}
+
+func (u UUID) String() string {
 	return fmt.Sprintf("%x-%x-%x-%x-%x", u[0:4], u[4:6], u[6:8], u[8:10], u[10:])
 }


Test patch:
diff --git a/connection_test.go b/connection_test.go
index 404642b..5891ba4 100644
--- a/connection_test.go
+++ b/connection_test.go
@@ -46,7 +46,7 @@ func TestInvalidConnection(t *testing.T) {
 // to generate a response with the SERVICE_NAME field appending a character at
 // the end of the header. This way it could test both the send and receive logic
 func postQueryMock(_ context.Context, _ *snowflakeRestful, _ *url.Values,
-	headers map[string]string, _ []byte, _ time.Duration, _ uuid,
+	headers map[string]string, _ []byte, _ time.Duration, _ UUID,
 	_ *Config) (*execResponse, error) {
 	var serviceName string
 	if serviceHeader, ok := headers[httpHeaderServiceName]; ok {
@@ -70,7 +70,7 @@ func TestExecWithEmptyRequestID(t *testing.T) {
 	ctx := WithRequestID(context.Background(), nilUUID)
 	postQueryMock := func(_ context.Context, _ *snowflakeRestful,
 		_ *url.Values, _ map[string]string, _ []byte, _ time.Duration,
-		requestID uuid, _ *Config) (*execResponse, error) {
+		requestID UUID, _ *Config) (*execResponse, error) {
 		// ensure the same requestID from context is used
 		if len(requestID) == 0 {
 			t.Fatal("requestID is empty")
@@ -137,11 +137,11 @@ func TestGetQueryResultUsesTokenFromTokenAccessor(t *testing.T) {
 }
 
 func TestExecWithSpecificRequestID(t *testing.T) {
-	origRequestID := newUUID()
+	origRequestID := NewUUID()
 	ctx := WithRequestID(context.Background(), origRequestID)
 	postQueryMock := func(_ context.Context, _ *snowflakeRestful,
 		_ *url.Values, _ map[string]string, _ []byte, _ time.Duration,
-		requestID uuid, _ *Config) (*execResponse, error) {
+		requestID UUID, _ *Config) (*execResponse, error) {
 		// ensure the same requestID from context is used
 		if requestID != origRequestID {
 			t.Fatal("requestID doesn't match")
@@ -441,7 +441,7 @@ func TestGetInvalidQueryStatus(t *testing.T) {
 func TestExecWithServerSideError(t *testing.T) {
 	postQueryMock := func(_ context.Context, _ *snowflakeRestful,
 		_ *url.Values, _ map[string]string, _ []byte, _ time.Duration,
-		requestID uuid, _ *Config) (*execResponse, error) {
+		requestID UUID, _ *Config) (*execResponse, error) {
 		dd := &execResponseData{}
 		return &execResponse{
 			Data:    *dd,
diff --git a/converter_test.go b/converter_test.go
index 89981db..f481018 100644
--- a/converter_test.go
+++ b/converter_test.go
@@ -13,9 +13,36 @@ import (
 
 	"github.com/apache/arrow/go/arrow"
 	"github.com/apache/arrow/go/arrow/array"
+	"github.com/apache/arrow/go/arrow/decimal128"
 	"github.com/apache/arrow/go/arrow/memory"
 )
 
+func stringIntToDecimal(src string) (decimal128.Num, bool) {
+	b, ok := new(big.Int).SetString(src, 10)
+	if !ok {
+		return decimal128.Num{}, ok
+	}
+	var high, low big.Int
+	high.QuoRem(b, decimalShift, &low)
+	return decimal128.New(high.Int64(), low.Uint64()), ok
+}
+
+func stringFloatToDecimal(src string, scale int64) (decimal128.Num, bool) {
+	b, ok := new(big.Float).SetString(src)
+	if !ok {
+		return decimal128.Num{}, ok
+	}
+	s := new(big.Float).SetInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(scale), nil))
+	n := new(big.Float).Mul(b, s)
+	if !n.IsInt() {
+		return decimal128.Num{}, false
+	}
+	var high, low, z big.Int
+	n.Int(&z)
+	high.QuoRem(&z, decimalShift, &low)
+	return decimal128.New(high.Int64(), low.Uint64()), ok
+}
+
 type tcGoTypeToSnowflake struct {
 	in    interface{}
 	tmode snowflakeType
diff --git a/driver_ocsp_test.go b/driver_ocsp_test.go
index b266cb8..46a5953 100644
--- a/driver_ocsp_test.go
+++ b/driver_ocsp_test.go
@@ -26,6 +26,18 @@ func unsetenv(k string) {
 	}
 }
 
+// deleteOCSPCacheFile deletes the OCSP response cache file
+func deleteOCSPCacheFile() {
+	os.Remove(cacheFileName)
+}
+
+// deleteOCSPCacheAll deletes all entries in the OCSP response cache on memory
+func deleteOCSPCacheAll() {
+	ocspResponseCacheLock.Lock()
+	defer ocspResponseCacheLock.Unlock()
+	ocspResponseCache = make(map[certIDKey][]interface{})
+}
+
 func cleanup() {
 	deleteOCSPCacheFile()
 	deleteOCSPCacheAll()
diff --git a/driver_test.go b/driver_test.go
index cade0e4..a52e41e 100644
--- a/driver_test.go
+++ b/driver_test.go
@@ -443,7 +443,7 @@ func TestEmptyQuery(t *testing.T) {
 func TestEmptyQueryWithRequestID(t *testing.T) {
 	runTests(t, dsn, func(dbt *DBTest) {
 		query := "select 1"
-		ctx := WithRequestID(context.Background(), newUUID())
+		ctx := WithRequestID(context.Background(), NewUUID())
 		rows := dbt.db.QueryRowContext(ctx, query)
 		var v1 interface{}
 		if err := rows.Scan(&v1); err != nil {
diff --git a/put_get_test.go b/put_get_test.go
index 778983a..28db4c2 100644
--- a/put_get_test.go
+++ b/put_get_test.go
@@ -9,16 +9,28 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
+	"math/rand"
 	"os"
 	"os/user"
 	"path/filepath"
 	"strconv"
 	"strings"
 	"testing"
+	"time"
 )
 
 const createStageStmt = "CREATE OR REPLACE STAGE %v URL = '%v' CREDENTIALS = (%v)"
 
+func randomString(n int) string {
+	rand.Seed(time.Now().UnixNano())
+	alpha := []rune("abcdefghijklmnopqrstuvwxyz")
+	b := make([]rune, n)
+	for i := range b {
+		b[i] = alpha[rand.Intn(len(alpha))]
+	}
+	return string(b)
+}
+
 func TestPutError(t *testing.T) {
 	if isWindows {
 		t.Skip("permission model is different")
diff --git a/restful_test.go b/restful_test.go
index 2eedfc0..01b2adb 100644
--- a/restful_test.go
+++ b/restful_test.go
@@ -109,7 +109,7 @@ func postTestAfterRenew(_ context.Context, _ *snowflakeRestful, _ *url.URL, _ ma
 	}, nil
 }
 
-func cancelTestRetry(ctx context.Context, sr *snowflakeRestful, requestID uuid, timeout time.Duration) error {
+func cancelTestRetry(ctx context.Context, sr *snowflakeRestful, requestID UUID, timeout time.Duration) error {
 	ctxRetry := getCancelRetry(ctx)
 	u := url.URL{}
 	reqByte, err := json.Marshal(make(map[string]string))
@@ -142,19 +142,19 @@ func TestUnitPostQueryHelperError(t *testing.T) {
 		TokenAccessor: getSimpleTokenAccessor(),
 	}
 	var err error
-	requestID := newUUID()
+	requestID := NewUUID()
 	_, err = postRestfulQueryHelper(context.Background(), sr, &url.Values{}, make(map[string]string), []byte{0x12, 0x34}, 0, requestID, &Config{})
 	if err == nil {
 		t.Fatalf("should have failed to post")
 	}
 	sr.FuncPost = postTestAppBadGatewayError
-	requestID = newUUID()
+	requestID = NewUUID()
 	_, err = postRestfulQueryHelper(context.Background(), sr, &url.Values{}, make(map[string]string), []byte{0x12, 0x34}, 0, requestID, &Config{})
 	if err == nil {
 		t.Fatalf("should have failed to post")
 	}
 	sr.FuncPost = postTestSuccessButInvalidJSON
-	requestID = newUUID()
+	requestID = NewUUID()
 	_, err = postRestfulQueryHelper(context.Background(), sr, &url.Values{}, make(map[string]string), []byte{0x12, 0x34}, 0, requestID, &Config{})
 	if err == nil {
 		t.Fatalf("should have failed to post")
@@ -359,7 +359,7 @@ func TestUnitPostQueryHelperUsesToken(t *testing.T) {
 	accessor.SetTokens(token, "", 0)
 
 	var err error
-	postQueryTest := func(_ context.Context, _ *snowflakeRestful, _ *url.Values, headers map[string]string, _ []byte, _ time.Duration, _ uuid, _ *Config) (*execResponse, error) {
+	postQueryTest := func(_ context.Context, _ *snowflakeRestful, _ *url.Values, headers map[string]string, _ []byte, _ time.Duration, _ UUID, _ *Config) (*execResponse, error) {
 		if headers[headerAuthorizationKey] != fmt.Sprintf(headerSnowflakeToken, token) {
 			t.Fatalf("authorization key doesn't match, %v vs %v", headers[headerAuthorizationKey], fmt.Sprintf(headerSnowflakeToken, token))
 		}
@@ -377,7 +377,7 @@ func TestUnitPostQueryHelperUsesToken(t *testing.T) {
 		FuncRenewSession: renewSessionTest,
 		TokenAccessor:    accessor,
 	}
-	_, err = postRestfulQueryHelper(context.Background(), sr, &url.Values{}, make(map[string]string), []byte{0x12, 0x34}, 0, newUUID(), &Config{})
+	_, err = postRestfulQueryHelper(context.Background(), sr, &url.Values{}, make(map[string]string), []byte{0x12, 0x34}, 0, NewUUID(), &Config{})
 	if err != nil {
 		t.Fatalf("err: %v", err)
 	}
@@ -385,8 +385,8 @@ func TestUnitPostQueryHelperUsesToken(t *testing.T) {
 
 func TestUnitPostQueryHelperRenewSession(t *testing.T) {
 	var err error
-	origRequestID := newUUID()
-	postQueryTest := func(_ context.Context, _ *snowflakeRestful, _ *url.Values, _ map[string]string, _ []byte, _ time.Duration, requestID uuid, _ *Config) (*execResponse, error) {
+	origRequestID := NewUUID()
+	postQueryTest := func(_ context.Context, _ *snowflakeRestful, _ *url.Values, _ map[string]string, _ []byte, _ time.Duration, requestID UUID, _ *Config) (*execResponse, error) {
 		// ensure the same requestID is used after the session token is renewed.
 		if requestID != origRequestID {
 			t.Fatal("requestID doesn't match")
diff --git a/util_test.go b/util_test.go
index 15153ca..b0a5f3c 100644
--- a/util_test.go
+++ b/util_test.go
@@ -74,7 +74,7 @@ func TestSimpleTokenAccessorGetTokensSynchronization(t *testing.T) {
 }
 
 func TestGetRequestIDFromContext(t *testing.T) {
-	expectedRequestID := newUUID()
+	expectedRequestID := NewUUID()
 	ctx := WithRequestID(context.Background(), expectedRequestID)
 	requestID := getOrGenerateRequestIDFromContext(ctx)
 	if requestID != expectedRequestID {