1// Copyright (c) 2017-2021 Snowflake Computing Inc. All right reserved.
2
3package gosnowflake
4
5import (
6	"fmt"
7)
8
9// SnowflakeError is a error type including various Snowflake specific information.
10type SnowflakeError struct {
11	Number         int
12	SQLState       string
13	QueryID        string
14	Message        string
15	MessageArgs    []interface{}
16	IncludeQueryID bool // TODO: populate this in connection
17}
18
19func (se *SnowflakeError) Error() string {
20	message := se.Message
21	if len(se.MessageArgs) > 0 {
22		message = fmt.Sprintf(se.Message, se.MessageArgs...)
23	}
24	if se.SQLState != "" {
25		if se.IncludeQueryID {
26			return fmt.Sprintf("%06d (%s): %s: %s", se.Number, se.SQLState, se.QueryID, message)
27		}
28		return fmt.Sprintf("%06d (%s): %s", se.Number, se.SQLState, message)
29	}
30	if se.IncludeQueryID {
31		return fmt.Sprintf("%06d: %s: %s", se.Number, se.QueryID, message)
32	}
33	return fmt.Sprintf("%06d: %s", se.Number, message)
34}
35
36const (
37	/* connection */
38
39	// ErrCodeEmptyAccountCode is an error code for the case where a DNS doesn't include account parameter
40	ErrCodeEmptyAccountCode = 260000
41	// ErrCodeEmptyUsernameCode is an error code for the case where a DNS doesn't include user parameter
42	ErrCodeEmptyUsernameCode = 260001
43	// ErrCodeEmptyPasswordCode is an error code for the case where a DNS doesn't include password parameter
44	ErrCodeEmptyPasswordCode = 260002
45	// ErrCodeFailedToParseHost is an error code for the case where a DNS includes an invalid host name
46	ErrCodeFailedToParseHost = 260003
47	// ErrCodeFailedToParsePort is an error code for the case where a DNS includes an invalid port number
48	ErrCodeFailedToParsePort = 260004
49	// ErrCodeIdpConnectionError is an error code for the case where a IDP connection failed
50	ErrCodeIdpConnectionError = 260005
51	// ErrCodeSSOURLNotMatch is an error code for the case where a SSO URL doesn't match
52	ErrCodeSSOURLNotMatch = 260006
53	// ErrCodeServiceUnavailable is an error code for the case where service is unavailable.
54	ErrCodeServiceUnavailable = 260007
55	// ErrCodeFailedToConnect is an error code for the case where a DB connection failed due to wrong account name
56	ErrCodeFailedToConnect = 260008
57	// ErrCodeRegionOverlap is an error code for the case where a region is specified despite an account region present
58	ErrCodeRegionOverlap = 260009
59	// ErrCodePrivateKeyParseError is an error code for the case where the private key is not parsed correctly
60	ErrCodePrivateKeyParseError = 260010
61	// ErrCodeFailedToParseAuthenticator is an error code for the case where a DNS includes an invalid authenticator
62	ErrCodeFailedToParseAuthenticator = 260011
63
64	/* network */
65
66	// ErrFailedToPostQuery is an error code for the case where HTTP POST failed.
67	ErrFailedToPostQuery = 261000
68	// ErrFailedToRenewSession is an error code for the case where session renewal failed.
69	ErrFailedToRenewSession = 261001
70	// ErrFailedToCancelQuery is an error code for the case where cancel query failed.
71	ErrFailedToCancelQuery = 261002
72	// ErrFailedToCloseSession is an error code for the case where close session failed.
73	ErrFailedToCloseSession = 261003
74	// ErrFailedToAuth is an error code for the case where authentication failed for unknown reason.
75	ErrFailedToAuth = 261004
76	// ErrFailedToAuthSAML is an error code for the case where authentication via SAML failed for unknown reason.
77	ErrFailedToAuthSAML = 261005
78	// ErrFailedToAuthOKTA is an error code for the case where authentication via OKTA failed for unknown reason.
79	ErrFailedToAuthOKTA = 261006
80	// ErrFailedToGetSSO is an error code for the case where authentication via OKTA failed for unknown reason.
81	ErrFailedToGetSSO = 261007
82	// ErrFailedToParseResponse is an error code for when we cannot parse an external browser response from Snowflake.
83	ErrFailedToParseResponse = 261008
84	// ErrFailedToGetExternalBrowserResponse is an error code for when there's an error reading from the open socket.
85	ErrFailedToGetExternalBrowserResponse = 261009
86	// ErrFailedToHeartbeat is an error code when a heartbeat fails.
87	ErrFailedToHeartbeat = 261010
88
89	/* rows */
90
91	// ErrFailedToGetChunk is an error code for the case where it failed to get chunk of result set
92	ErrFailedToGetChunk = 262000
93
94	/* transaction*/
95
96	// ErrNoReadOnlyTransaction is an error code for the case where readonly mode is specified.
97	ErrNoReadOnlyTransaction = 263000
98	// ErrNoDefaultTransactionIsolationLevel is an error code for the case where non default isolation level is specified.
99	ErrNoDefaultTransactionIsolationLevel = 263001
100
101	/* file transfer */
102
103	// ErrInvalidStageFs is an error code denoting an invalid stage in the file system
104	ErrInvalidStageFs = 264001
105	// ErrFailedToDownloadFromStage is an error code denoting the failure to download a file from the stage
106	ErrFailedToDownloadFromStage = 264002
107	// ErrFailedToUploadToStage is an error code denoting the failure to upload a file to the stage
108	ErrFailedToUploadToStage = 264003
109	// ErrInvalidStageLocation is an error code denoting an invalid stage location
110	ErrInvalidStageLocation = 264004
111	// ErrLocalPathNotDirectory is an error code denoting a local path that is not a directory
112	ErrLocalPathNotDirectory = 264005
113	// ErrFileNotExists is an error code denoting the file to be transferred does not exist
114	ErrFileNotExists = 264006
115	// ErrCompressionNotSupported is an error code denoting the user specified compression type is not supported
116	ErrCompressionNotSupported = 264007
117	// ErrInternalNotMatchEncryptMaterial is an error code denoting the encryption material specified does not match
118	ErrInternalNotMatchEncryptMaterial = 264008
119
120	/* binding */
121
122	// ErrBindSerialization is an error code for a failed serialization of bind variables
123	ErrBindSerialization = 265001
124	// ErrBindUpload is an error code for the uploading process of bind elements to the stage
125	ErrBindUpload = 265002
126
127	/* converter */
128
129	// ErrInvalidTimestampTz is an error code for the case where a returned TIMESTAMP_TZ internal value is invalid
130	ErrInvalidTimestampTz = 268000
131	// ErrInvalidOffsetStr is an error code for the case where a offset string is invalid. The input string must
132	// consist of sHHMI where one sign character '+'/'-' followed by zero filled hours and minutes
133	ErrInvalidOffsetStr = 268001
134	// ErrInvalidBinaryHexForm is an error code for the case where a binary data in hex form is invalid.
135	ErrInvalidBinaryHexForm = 268002
136
137	/* OCSP */
138
139	// ErrOCSPStatusRevoked is an error code for the case where the certificate is revoked.
140	ErrOCSPStatusRevoked = 269001
141	// ErrOCSPStatusUnknown is an error code for the case where the certificate revocation status is unknown.
142	ErrOCSPStatusUnknown = 269002
143	// ErrOCSPInvalidValidity is an error code for the case where the OCSP response validity is invalid.
144	ErrOCSPInvalidValidity = 269003
145	// ErrOCSPNoOCSPResponderURL is an error code for the case where the OCSP responder URL is not attached.
146	ErrOCSPNoOCSPResponderURL = 269004
147
148	/* Query Status*/
149
150	// ErrQueryStatus when check the status of a query, receive error or no status
151	ErrQueryStatus = 279001
152	// ErrQueryIDFormat the query ID given to fetch its result is not valid
153	ErrQueryIDFormat = 279101
154	// ErrQueryReportedError server side reports the query failed with error
155	ErrQueryReportedError = 279201
156	// ErrQueryIsRunning the query is still running
157	ErrQueryIsRunning = 279301
158
159	/* GS error code */
160
161	// ErrSessionGone is an GS error code for the case that session is already closed
162	ErrSessionGone = 390111
163	// ErrRoleNotExist is a GS error code for the case that the role specified does not exist
164	ErrRoleNotExist = 390189
165	// ErrObjectNotExistOrAuthorized is a GS error code for the case that the server-side object specified does not exist
166	ErrObjectNotExistOrAuthorized = 390201
167)
168
169const (
170	errMsgFailedToParseHost                  = "failed to parse a host name. host: %v"
171	errMsgFailedToParsePort                  = "failed to parse a port number. port: %v"
172	errMsgFailedToParseAuthenticator         = "failed to parse an authenticator: %v"
173	errMsgInvalidOffsetStr                   = "offset must be a string consist of sHHMI where one sign character '+'/'-' followed by zero filled hours and minutes: %v"
174	errMsgInvalidByteArray                   = "invalid byte array: %v"
175	errMsgIdpConnectionError                 = "failed to verify URLs. authenticator: %v, token URL:%v, SSO URL:%v"
176	errMsgSSOURLNotMatch                     = "SSO URL didn't match. expected: %v, got: %v"
177	errMsgFailedToGetChunk                   = "failed to get a chunk of result sets. idx: %v"
178	errMsgFailedToPostQuery                  = "failed to POST. HTTP: %v, URL: %v"
179	errMsgFailedToRenew                      = "failed to renew session. HTTP: %v, URL: %v"
180	errMsgFailedToCancelQuery                = "failed to cancel query. HTTP: %v, URL: %v"
181	errMsgFailedToCloseSession               = "failed to close session. HTTP: %v, URL: %v"
182	errMsgFailedToAuth                       = "failed to auth for unknown reason. HTTP: %v, URL: %v"
183	errMsgFailedToAuthSAML                   = "failed to auth via SAML for unknown reason. HTTP: %v, URL: %v"
184	errMsgFailedToAuthOKTA                   = "failed to auth via OKTA for unknown reason. HTTP: %v, URL: %v"
185	errMsgFailedToGetSSO                     = "failed to auth via OKTA for unknown reason. HTTP: %v, URL: %v"
186	errMsgFailedToParseResponse              = "failed to parse a response from Snowflake. Response: %v"
187	errMsgFailedToGetExternalBrowserResponse = "failed to get an external browser response from Snowflake, err: %s"
188	errMsgNoReadOnlyTransaction              = "no readonly mode is supported"
189	errMsgNoDefaultTransactionIsolationLevel = "no default isolation transaction level is supported"
190	errMsgServiceUnavailable                 = "service is unavailable. check your connectivity. you may need a proxy server. HTTP: %v, URL: %v"
191	errMsgFailedToConnect                    = "failed to connect to db. verify account name is correct. HTTP: %v, URL: %v"
192	errMsgOCSPStatusRevoked                  = "OCSP revoked: reason:%v, at:%v"
193	errMsgOCSPStatusUnknown                  = "OCSP unknown"
194	errMsgOCSPInvalidValidity                = "invalid validity: producedAt: %v, thisUpdate: %v, nextUpdate: %v"
195	errMsgOCSPNoOCSPResponderURL             = "no OCSP server is attached to the certificate. %v"
196	errMsgBindColumnMismatch                 = "column %v has a different number of binds (%v) than column 1 (%v)"
197)
198
199var (
200	// ErrEmptyAccount is returned if a DNS doesn't include account parameter.
201	ErrEmptyAccount = &SnowflakeError{
202		Number:  ErrCodeEmptyAccountCode,
203		Message: "account is empty",
204	}
205	// ErrEmptyUsername is returned if a DNS doesn't include user parameter.
206	ErrEmptyUsername = &SnowflakeError{
207		Number:  ErrCodeEmptyUsernameCode,
208		Message: "user is empty",
209	}
210	// ErrEmptyPassword is returned if a DNS doesn't include password parameter.
211	ErrEmptyPassword = &SnowflakeError{
212		Number:  ErrCodeEmptyPasswordCode,
213		Message: "password is empty"}
214
215	// ErrInvalidRegion is returned if a DSN's implicit region from account parameter and explicit region parameter conflict.
216	ErrInvalidRegion = &SnowflakeError{
217		Number:  ErrCodeRegionOverlap,
218		Message: "two regions specified"}
219)
220