Renamed fields. (#471)
Removed unused fields.
Nikita Gavrilov authored 5 years ago
Daniel Theophanes committed 5 years ago
209 | 209 | * "cloud.google.com/go/civil".Date -> date |
210 | 210 | * "cloud.google.com/go/civil".DateTime -> datetime2 |
211 | 211 | * "cloud.google.com/go/civil".Time -> time |
212 | * mssql.TVPType -> Table Value Parameter (TDS version dependent) | |
212 | * mssql.TVP -> Table Value Parameter (TDS version dependent) | |
213 | 213 | |
214 | 214 | ## Important Notes |
215 | 215 |
119 | 119 | }, |
120 | 120 | } |
121 | 121 | |
122 | tvpType := mssql.TVPType{ | |
123 | TVPTypeName: "TestTVPSchema.exampleTVP", | |
124 | TVPValue: exampleData, | |
122 | tvpType := mssql.TVP{ | |
123 | TypeName: "TestTVPSchema.exampleTVP", | |
124 | Value: exampleData, | |
125 | 125 | } |
126 | 126 | |
127 | 127 | rows, err := conn.Query(execTvp, |
111 | 111 | *v = 0 // By default the return value should be zero. |
112 | 112 | c.returnStatus = v |
113 | 113 | return driver.ErrRemoveArgument |
114 | case TVPType: | |
114 | case TVP: | |
115 | 115 | return nil |
116 | 116 | default: |
117 | 117 | var err error |
161 | 161 | case sql.Out: |
162 | 162 | res, err = s.makeParam(val.Dest) |
163 | 163 | res.Flags = fByRevValue |
164 | case TVPType: | |
164 | case TVP: | |
165 | 165 | err = val.check() |
166 | 166 | if err != nil { |
167 | 167 | return |
168 | 168 | } |
169 | schema, name, errGetName := getSchemeAndName(val.TVPTypeName) | |
169 | schema, name, errGetName := getSchemeAndName(val.TypeName) | |
170 | 170 | if errGetName != nil { |
171 | 171 | return |
172 | 172 | } |
19 | 19 | ) |
20 | 20 | |
21 | 21 | var ( |
22 | ErrorEmptyTVPTypeName = errors.New("TVPTypeName must not be empty") | |
23 | ErrorTypeSlice = errors.New("TVPType must be slice type") | |
24 | ErrorTypeSliceIsEmpty = errors.New("TVPType mustn't be null value") | |
22 | ErrorEmptyTVPTypeName = errors.New("TypeName must not be empty") | |
23 | ErrorTypeSlice = errors.New("TVP must be slice type") | |
24 | ErrorTypeSliceIsEmpty = errors.New("TVP mustn't be null value") | |
25 | 25 | ErrorSkip = errors.New("all fields mustn't skip") |
26 | 26 | ErrorObjectName = errors.New("wrong tvp name") |
27 | 27 | ) |
28 | 28 | |
29 | //TVPType is driver type, which allows supporting Table Valued Parameters (TVP) in SQL Server | |
30 | type TVPType struct { | |
31 | //TVP param name, mustn't be default value | |
32 | TVPTypeName string | |
33 | //TVP Value Param must be the slice, mustn't be nil | |
34 | TVPValue interface{} | |
35 | } | |
36 | ||
37 | func (tvp TVPType) check() error { | |
38 | if len(tvp.TVPTypeName) == 0 { | |
29 | //TVP is driver type, which allows supporting Table Valued Parameters (TVP) in SQL Server | |
30 | type TVP struct { | |
31 | //TypeName mustn't be default value | |
32 | TypeName string | |
33 | //Value must be the slice, mustn't be nil | |
34 | Value interface{} | |
35 | } | |
36 | ||
37 | func (tvp TVP) check() error { | |
38 | if len(tvp.TypeName) == 0 { | |
39 | 39 | return ErrorEmptyTVPTypeName |
40 | 40 | } |
41 | if !isProc(tvp.TVPTypeName) { | |
41 | if !isProc(tvp.TypeName) { | |
42 | 42 | return ErrorEmptyTVPTypeName |
43 | 43 | } |
44 | if sepCount := getCountSQLSeparators(tvp.TVPTypeName); sepCount > 1 { | |
44 | if sepCount := getCountSQLSeparators(tvp.TypeName); sepCount > 1 { | |
45 | 45 | return ErrorObjectName |
46 | 46 | } |
47 | valueOf := reflect.ValueOf(tvp.TVPValue) | |
47 | valueOf := reflect.ValueOf(tvp.Value) | |
48 | 48 | if valueOf.Kind() != reflect.Slice { |
49 | 49 | return ErrorTypeSlice |
50 | 50 | } |
51 | 51 | if valueOf.IsNil() { |
52 | 52 | return ErrorTypeSliceIsEmpty |
53 | 53 | } |
54 | if reflect.TypeOf(tvp.TVPValue).Elem().Kind() != reflect.Struct { | |
54 | if reflect.TypeOf(tvp.Value).Elem().Kind() != reflect.Struct { | |
55 | 55 | return ErrorTypeSlice |
56 | 56 | } |
57 | 57 | return nil |
58 | 58 | } |
59 | 59 | |
60 | func (tvp TVPType) encode(schema, name string) ([]byte, error) { | |
60 | func (tvp TVP) encode(schema, name string) ([]byte, error) { | |
61 | 61 | columnStr, tvpFieldIndexes, err := tvp.columnTypes() |
62 | 62 | if err != nil { |
63 | 63 | return nil, err |
90 | 90 | c: conn, |
91 | 91 | } |
92 | 92 | |
93 | val := reflect.ValueOf(tvp.TVPValue) | |
93 | val := reflect.ValueOf(tvp.Value) | |
94 | 94 | for i := 0; i < val.Len(); i++ { |
95 | 95 | refStr := reflect.ValueOf(val.Index(i).Interface()) |
96 | 96 | buf.WriteByte(_TVP_ROW_TOKEN) |
129 | 129 | return buf.Bytes(), nil |
130 | 130 | } |
131 | 131 | |
132 | func (tvp TVPType) columnTypes() ([]columnStruct, []int, error) { | |
133 | val := reflect.ValueOf(tvp.TVPValue) | |
132 | func (tvp TVP) columnTypes() ([]columnStruct, []int, error) { | |
133 | val := reflect.ValueOf(tvp.Value) | |
134 | 134 | var firstRow interface{} |
135 | 135 | if val.Len() != 0 { |
136 | 136 | firstRow = val.Index(0).Interface() |
137 | 137 | } else { |
138 | firstRow = reflect.New(reflect.TypeOf(tvp.TVPValue).Elem()).Elem().Interface() | |
138 | firstRow = reflect.New(reflect.TypeOf(tvp.Value).Elem()).Elem().Interface() | |
139 | 139 | } |
140 | 140 | |
141 | 141 | tvpRow := reflect.TypeOf(firstRow) |
274 | 274 | }, |
275 | 275 | } |
276 | 276 | |
277 | tvpType := TVPType{ | |
278 | TVPTypeName: "tvptable", | |
279 | TVPValue: param1, | |
280 | } | |
281 | tvpTypeEmpty := TVPType{ | |
282 | TVPTypeName: "tvptable", | |
283 | TVPValue: []TvptableRow{}, | |
277 | tvpType := TVP{ | |
278 | TypeName: "tvptable", | |
279 | Value: param1, | |
280 | } | |
281 | tvpTypeEmpty := TVP{ | |
282 | TypeName: "tvptable", | |
283 | Value: []TvptableRow{}, | |
284 | 284 | } |
285 | 285 | |
286 | 286 | rows, err := db.QueryContext(ctx, |
518 | 518 | }, |
519 | 519 | } |
520 | 520 | |
521 | tvpType := TVPType{ | |
522 | TVPTypeName: "tvptable", | |
523 | TVPValue: param1, | |
524 | } | |
525 | tvpTypeEmpty := TVPType{ | |
526 | TVPTypeName: "tvptable", | |
527 | TVPValue: []TvptableRowWithSkipTag{}, | |
521 | tvpType := TVP{ | |
522 | TypeName: "tvptable", | |
523 | Value: param1, | |
524 | } | |
525 | tvpTypeEmpty := TVP{ | |
526 | TypeName: "tvptable", | |
527 | Value: []TvptableRowWithSkipTag{}, | |
528 | 528 | } |
529 | 529 | |
530 | 530 | rows, err := db.QueryContext(ctx, |
652 | 652 | }, |
653 | 653 | } |
654 | 654 | |
655 | tvpType := TVPType{ | |
656 | TVPTypeName: "exempleTVP", | |
657 | TVPValue: exempleData, | |
655 | tvpType := TVP{ | |
656 | TypeName: "exempleTVP", | |
657 | Value: exempleData, | |
658 | 658 | } |
659 | 659 | |
660 | 660 | rows, err := conn.Query(execTvp, |
59 | 59 | }, |
60 | 60 | }, |
61 | 61 | { |
62 | name: "TVPValue has wrong field type", | |
62 | name: "Value has wrong field type", | |
63 | 63 | fields: fields{ |
64 | 64 | TVPValue: []TestFieldError{TestFieldError{}}, |
65 | 65 | }, |
66 | 66 | wantErr: true, |
67 | 67 | }, |
68 | 68 | { |
69 | name: "TVPValue has wrong type", | |
69 | name: "Value has wrong type", | |
70 | 70 | fields: fields{ |
71 | 71 | TVPValue: []TestFieldsUnsupportedTypes{}, |
72 | 72 | }, |
73 | 73 | wantErr: true, |
74 | 74 | }, |
75 | 75 | { |
76 | name: "TVPValue has wrong type", | |
76 | name: "Value has wrong type", | |
77 | 77 | fields: fields{ |
78 | 78 | TVPValue: []structType{}, |
79 | 79 | }, |
110 | 110 | } |
111 | 111 | for _, tt := range tests { |
112 | 112 | t.Run(tt.name, func(t *testing.T) { |
113 | tvp := TVPType{ | |
114 | TVPTypeName: tt.fields.TVPName, | |
115 | TVPValue: tt.fields.TVPValue, | |
113 | tvp := TVP{ | |
114 | TypeName: tt.fields.TVPName, | |
115 | Value: tt.fields.TVPValue, | |
116 | 116 | } |
117 | 117 | _, _, err := tvp.columnTypes() |
118 | 118 | if (err != nil) != tt.wantErr { |
119 | t.Errorf("TVPType.columnTypes() error = %v, wantErr %v", err, tt.wantErr) | |
119 | t.Errorf("TVP.columnTypes() error = %v, wantErr %v", err, tt.wantErr) | |
120 | 120 | return |
121 | 121 | } |
122 | 122 | }) |
137 | 137 | wantErr bool |
138 | 138 | }{ |
139 | 139 | { |
140 | name: "TVPTypeName is nil", | |
141 | wantErr: true, | |
142 | }, | |
143 | { | |
144 | name: "TVPValue is nil", | |
140 | name: "TypeName is nil", | |
141 | wantErr: true, | |
142 | }, | |
143 | { | |
144 | name: "Value is nil", | |
145 | 145 | fields: fields{ |
146 | 146 | TVPName: "Test", |
147 | 147 | TVPValue: nil, |
149 | 149 | wantErr: true, |
150 | 150 | }, |
151 | 151 | { |
152 | name: "TVPValue is nil", | |
152 | name: "Value is nil", | |
153 | 153 | fields: fields{ |
154 | 154 | TVPName: "Test", |
155 | 155 | }, |
156 | 156 | wantErr: true, |
157 | 157 | }, |
158 | 158 | { |
159 | name: "TVPValue isn't slice", | |
159 | name: "Value isn't slice", | |
160 | 160 | fields: fields{ |
161 | 161 | TVPName: "Test", |
162 | 162 | TVPValue: "", |
164 | 164 | wantErr: true, |
165 | 165 | }, |
166 | 166 | { |
167 | name: "TVPValue isn't slice", | |
167 | name: "Value isn't slice", | |
168 | 168 | fields: fields{ |
169 | 169 | TVPName: "Test", |
170 | 170 | TVPValue: 12345, |
172 | 172 | wantErr: true, |
173 | 173 | }, |
174 | 174 | { |
175 | name: "TVPValue isn't slice", | |
175 | name: "Value isn't slice", | |
176 | 176 | fields: fields{ |
177 | 177 | TVPName: "Test", |
178 | 178 | TVPValue: nullSlice, |
180 | 180 | wantErr: true, |
181 | 181 | }, |
182 | 182 | { |
183 | name: "TVPValue isn't right", | |
183 | name: "Value isn't right", | |
184 | 184 | fields: fields{ |
185 | 185 | TVPName: "Test", |
186 | 186 | TVPValue: []*fields{}, |
188 | 188 | wantErr: true, |
189 | 189 | }, |
190 | 190 | { |
191 | name: "TVPValue is right", | |
192 | fields: fields{ | |
193 | TVPName: "Test", | |
194 | TVPValue: []fields{}, | |
195 | }, | |
196 | wantErr: false, | |
197 | }, | |
198 | { | |
199 | name: "TVPValue is right", | |
200 | fields: fields{ | |
201 | TVPName: "Test", | |
202 | TVPValue: []fields{}, | |
203 | }, | |
204 | wantErr: false, | |
205 | }, | |
206 | { | |
207 | name: "TVPValue is right", | |
191 | name: "Value is right", | |
192 | fields: fields{ | |
193 | TVPName: "Test", | |
194 | TVPValue: []fields{}, | |
195 | }, | |
196 | wantErr: false, | |
197 | }, | |
198 | { | |
199 | name: "Value is right", | |
200 | fields: fields{ | |
201 | TVPName: "Test", | |
202 | TVPValue: []fields{}, | |
203 | }, | |
204 | wantErr: false, | |
205 | }, | |
206 | { | |
207 | name: "Value is right", | |
208 | 208 | fields: fields{ |
209 | 209 | TVPName: "[Test]", |
210 | 210 | TVPValue: []fields{}, |
212 | 212 | wantErr: false, |
213 | 213 | }, |
214 | 214 | { |
215 | name: "TVPValue is right", | |
215 | name: "Value is right", | |
216 | 216 | fields: fields{ |
217 | 217 | TVPName: "[123].[Test]", |
218 | 218 | TVPValue: []fields{}, |
254 | 254 | } |
255 | 255 | for _, tt := range tests { |
256 | 256 | t.Run(tt.name, func(t *testing.T) { |
257 | tvp := TVPType{ | |
258 | TVPTypeName: tt.fields.TVPName, | |
259 | TVPValue: tt.fields.TVPValue, | |
257 | tvp := TVP{ | |
258 | TypeName: tt.fields.TVPName, | |
259 | Value: tt.fields.TVPValue, | |
260 | 260 | } |
261 | 261 | if err := tvp.check(); (err != nil) != tt.wantErr { |
262 | t.Errorf("TVPType.check() error = %v, wantErr %v", err, tt.wantErr) | |
262 | t.Errorf("TVP.check() error = %v, wantErr %v", err, tt.wantErr) | |
263 | 263 | } |
264 | 264 | }) |
265 | 265 | } |
278 | 278 | wantErr bool |
279 | 279 | }{ |
280 | 280 | { |
281 | name: "TVPValue gets error unsupported type", | |
281 | name: "Value gets error unsupported type", | |
282 | 282 | fields: fields{ |
283 | 283 | TVPTypeName: "Test", |
284 | 284 | TVPValue: []TestFieldError{}, |
288 | 288 | } |
289 | 289 | for _, tt := range tests { |
290 | 290 | t.Run(tt.name, func(t *testing.T) { |
291 | tvp := TVPType{ | |
292 | TVPTypeName: tt.fields.TVPTypeName, | |
293 | TVPValue: tt.fields.TVPValue, | |
291 | tvp := TVP{ | |
292 | TypeName: tt.fields.TVPTypeName, | |
293 | Value: tt.fields.TVPValue, | |
294 | 294 | } |
295 | 295 | schema, name, err := getSchemeAndName(tt.fields.TVPTypeName) |
296 | 296 | if err != nil { |
298 | 298 | } |
299 | 299 | _, err = tvp.encode(schema, name) |
300 | 300 | if (err != nil) != tt.wantErr { |
301 | t.Errorf("TVPType.encode() error = %v, wantErr %v", err, tt.wantErr) | |
301 | t.Errorf("TVP.encode() error = %v, wantErr %v", err, tt.wantErr) | |
302 | 302 | } |
303 | 303 | }) |
304 | 304 | } |
308 | 308 | type val struct { |
309 | 309 | Value string |
310 | 310 | } |
311 | tvp := TVPType{ | |
312 | TVPTypeName: "Test", | |
313 | TVPValue: []val{}, | |
311 | tvp := TVP{ | |
312 | TypeName: "Test", | |
313 | Value: []val{}, | |
314 | 314 | } |
315 | 315 | for i := 0; i < b.N; i++ { |
316 | 316 | err := tvp.check() |
353 | 353 | boolsNull *bool |
354 | 354 | } |
355 | 355 | wal := make([]str, 100) |
356 | tvp := TVPType{ | |
357 | TVPTypeName: "Test", | |
358 | TVPValue: wal, | |
356 | tvp := TVP{ | |
357 | TypeName: "Test", | |
358 | Value: wal, | |
359 | 359 | } |
360 | 360 | for i := 0; i < b.N; i++ { |
361 | 361 | _, _, err := tvp.columnTypes() |
72 | 72 | const _PLP_NULL = 0xFFFFFFFFFFFFFFFF |
73 | 73 | const _UNKNOWN_PLP_LEN = 0xFFFFFFFFFFFFFFFE |
74 | 74 | const _PLP_TERMINATOR = 0x00000000 |
75 | const _TVP_NULL_TOKEN = 0xffff | |
76 | 75 | |
77 | 76 | // TVP COLUMN FLAGS |
78 | const _TVP_COLUMN_DEFAULT_FLAG = 0x200 | |
79 | 77 | const _TVP_END_TOKEN = 0x00 |
80 | 78 | const _TVP_ROW_TOKEN = 0x01 |
81 | const _TVP_ORDER_UNIQUE_TOKEN = 0x10 | |
82 | const _TVP_COLUMN_ORDERING_TOKEN = 0x11 | |
83 | 79 | |
84 | 80 | // TYPE_INFO rule |
85 | 81 | // http://msdn.microsoft.com/en-us/library/dd358284.aspx |