1// Copyright (c) 2017-2021 Snowflake Computing Inc. All right reserved. 2 3package gosnowflake 4 5import ( 6 "bytes" 7 "database/sql" 8 "database/sql/driver" 9 "fmt" 10) 11 12type snowflakeType int 13 14const ( 15 fixedType snowflakeType = iota 16 realType 17 textType 18 dateType 19 variantType 20 timestampLtzType 21 timestampNtzType 22 timestampTzType 23 objectType 24 arrayType 25 binaryType 26 timeType 27 booleanType 28 // the following are not snowflake types per se but internal types 29 nullType 30 sliceType 31 changeType 32 unSupportedType 33) 34 35var snowflakeTypes = [...]string{"FIXED", "REAL", "TEXT", "DATE", "VARIANT", 36 "TIMESTAMP_LTZ", "TIMESTAMP_NTZ", "TIMESTAMP_TZ", "OBJECT", "ARRAY", 37 "BINARY", "TIME", "BOOLEAN", "NULL", "SLICE", "CHANGE_TYPE", "NOT_SUPPORTED"} 38 39func (st snowflakeType) String() string { 40 return snowflakeTypes[st] 41} 42 43func (st snowflakeType) Byte() byte { 44 return byte(st) 45} 46 47func getSnowflakeType(typ string) snowflakeType { 48 for i, sft := range snowflakeTypes { 49 if sft == typ { 50 return snowflakeType(i) 51 } else if snowflakeType(i) == nullType { 52 break 53 } 54 } 55 return nullType 56} 57 58var ( 59 // DataTypeFixed is a FIXED datatype. 60 DataTypeFixed = []byte{fixedType.Byte()} 61 // DataTypeReal is a REAL datatype. 62 DataTypeReal = []byte{realType.Byte()} 63 // DataTypeText is a TEXT datatype. 64 DataTypeText = []byte{textType.Byte()} 65 // DataTypeDate is a Date datatype. 66 DataTypeDate = []byte{dateType.Byte()} 67 // DataTypeVariant is a TEXT datatype. 68 DataTypeVariant = []byte{variantType.Byte()} 69 // DataTypeTimestampLtz is a TIMESTAMP_LTZ datatype. 70 DataTypeTimestampLtz = []byte{timestampLtzType.Byte()} 71 // DataTypeTimestampNtz is a TIMESTAMP_NTZ datatype. 72 DataTypeTimestampNtz = []byte{timestampNtzType.Byte()} 73 // DataTypeTimestampTz is a TIMESTAMP_TZ datatype. 74 DataTypeTimestampTz = []byte{timestampTzType.Byte()} 75 // DataTypeObject is a OBJECT datatype. 76 DataTypeObject = []byte{objectType.Byte()} 77 // DataTypeArray is a ARRAY datatype. 78 DataTypeArray = []byte{arrayType.Byte()} 79 // DataTypeBinary is a BINARY datatype. 80 DataTypeBinary = []byte{binaryType.Byte()} 81 // DataTypeTime is a TIME datatype. 82 DataTypeTime = []byte{timeType.Byte()} 83 // DataTypeBoolean is a BOOLEAN datatype. 84 DataTypeBoolean = []byte{booleanType.Byte()} 85) 86 87// dataTypeMode returns the subsequent data type in a string representation. 88func dataTypeMode(v driver.Value) (tsmode snowflakeType, err error) { 89 if bd, ok := v.([]byte); ok { 90 switch { 91 case bytes.Equal(bd, DataTypeDate): 92 tsmode = dateType 93 case bytes.Equal(bd, DataTypeTime): 94 tsmode = timeType 95 case bytes.Equal(bd, DataTypeTimestampLtz): 96 tsmode = timestampLtzType 97 case bytes.Equal(bd, DataTypeTimestampNtz): 98 tsmode = timestampNtzType 99 case bytes.Equal(bd, DataTypeTimestampTz): 100 tsmode = timestampTzType 101 case bytes.Equal(bd, DataTypeBinary): 102 tsmode = binaryType 103 default: 104 return nullType, fmt.Errorf(errMsgInvalidByteArray, v) 105 } 106 } else { 107 return nullType, fmt.Errorf(errMsgInvalidByteArray, v) 108 } 109 return tsmode, nil 110} 111 112// SnowflakeParameter includes the columns output from SHOW PARAMETER command. 113type SnowflakeParameter struct { 114 Key string 115 Value string 116 Default string 117 Level string 118 Description string 119 SetByUser string 120 SetInJob string 121 SetOn string 122 SetByThreadID string 123 SetByThreadName string 124 SetByClass string 125 ParameterComment string 126 Type string 127 IsExpired string 128 ExpiresAt string 129 SetByControllingParameter string 130 ActivateVersion string 131 PartialRollout string 132 Unknown string // Reserve for added parameter 133} 134 135func populateSnowflakeParameter(colname string, p *SnowflakeParameter) interface{} { 136 switch colname { 137 case "key": 138 return &p.Key 139 case "value": 140 return &p.Value 141 case "default": 142 return &p.Default 143 case "level": 144 return &p.Level 145 case "description": 146 return &p.Description 147 case "set_by_user": 148 return &p.SetByUser 149 case "set_in_job": 150 return &p.SetInJob 151 case "set_on": 152 return &p.SetOn 153 case "set_by_thread_id": 154 return &p.SetByThreadID 155 case "set_by_thread_name": 156 return &p.SetByThreadName 157 case "set_by_class": 158 return &p.SetByClass 159 case "parameter_comment": 160 return &p.ParameterComment 161 case "type": 162 return &p.Type 163 case "is_expired": 164 return &p.IsExpired 165 case "expires_at": 166 return &p.ExpiresAt 167 case "set_by_controlling_parameter": 168 return &p.SetByControllingParameter 169 case "activate_version": 170 return &p.ActivateVersion 171 case "partial_rollout": 172 return &p.PartialRollout 173 default: 174 debugPanicf("unknown type: %v", colname) 175 return &p.Unknown 176 } 177} 178 179// ScanSnowflakeParameter binds SnowflakeParameter variable with an array of column buffer. 180func ScanSnowflakeParameter(rows *sql.Rows) (*SnowflakeParameter, error) { 181 var err error 182 var columns []string 183 columns, err = rows.Columns() 184 if err != nil { 185 return nil, err 186 } 187 colNum := len(columns) 188 p := SnowflakeParameter{} 189 cols := make([]interface{}, colNum) 190 for i := 0; i < colNum; i++ { 191 cols[i] = populateSnowflakeParameter(columns[i], &p) 192 } 193 err = rows.Scan(cols...) 194 return &p, err 195} 196