• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

codenotary / immudb / 9791636125

04 Jul 2024 09:10AM UTC coverage: 89.523% (+0.1%) from 89.416%
9791636125

push

gh-ci

ostafen
Implement CHECK constraints

Signed-off-by: Stefano Scafiti <stefano.scafiti96@gmail.com>

554 of 628 new or added lines in 10 files covered. (88.22%)

14 existing lines in 7 files now uncovered.

35374 of 39514 relevant lines covered (89.52%)

160396.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.86
/embedded/sql/json_type.go
1
package sql
2

3
import (
4
        "encoding/json"
5
        "fmt"
6
        "strconv"
7
        "strings"
8
)
9

10
const (
11
        JSONTypeNumber = "NUMBER"
12
        JSONTypeBool   = "BOOL"
13
        JSONTypeString = "STRING"
14
        JSONTypeArray  = "ARRAY"
15
        JSONTypeObject = "OBJECT"
16
        JSONTypeNull   = "NULL"
17
)
18

19
type JSON struct {
20
        val interface{}
21
}
22

23
func NewJsonFromString(s string) (*JSON, error) {
5✔
24
        var val interface{}
5✔
25
        if err := json.Unmarshal([]byte(s), &val); err != nil {
5✔
NEW
26
                return nil, err
×
NEW
27
        }
×
28
        return &JSON{val: val}, nil
5✔
29
}
30

31
func NewJson(val interface{}) *JSON {
2,163✔
32
        return &JSON{val: val}
2,163✔
33
}
2,163✔
34

35
func (v *JSON) Type() SQLValueType {
1,670✔
36
        return JSONType
1,670✔
37
}
1,670✔
38

39
func (v *JSON) IsNull() bool {
2,325✔
40
        return false
2,325✔
41
}
2,325✔
42

43
func (v *JSON) inferType(cols map[string]ColDescriptor, params map[string]SQLValueType, implicitTable string) (SQLValueType, error) {
7✔
44
        return JSONType, nil
7✔
45
}
7✔
46

47
func (v *JSON) requiresType(t SQLValueType, cols map[string]ColDescriptor, params map[string]SQLValueType, implicitTable string) error {
7✔
48
        ok := t == JSONType
7✔
49
        switch t {
7✔
50
        case IntegerType, Float64Type:
3✔
51
                _, isInt := v.val.(int64)
3✔
52
                _, isFloat := v.val.(float64)
3✔
53
                ok = isInt || (isFloat && t == Float64Type)
3✔
54
        case VarcharType:
1✔
55
                _, ok = v.val.(string)
1✔
56
        case BooleanType:
1✔
57
                _, ok = v.val.(bool)
1✔
58
        case AnyType:
1✔
59
                ok = v.val == nil
1✔
60
        }
61

62
        if !ok {
8✔
63
                return fmt.Errorf("%w: %v can not be interpreted as type %v", ErrInvalidTypes, JSONType, t)
1✔
64
        }
1✔
65
        return nil
6✔
66
}
67

68
func (v *JSON) substitute(params map[string]interface{}) (ValueExp, error) {
1,101✔
69
        return v, nil
1,101✔
70
}
1,101✔
71

72
func (v *JSON) reduce(tx *SQLTx, row *Row, implicitTable string) (TypedValue, error) {
1,101✔
73
        return v, nil
1,101✔
74
}
1,101✔
75

76
func (v *JSON) reduceSelectors(row *Row, implicitTable string) ValueExp {
1✔
77
        return v
1✔
78
}
1✔
79

80
func (v *JSON) isConstant() bool {
101✔
81
        return true
101✔
82
}
101✔
83

84
func (v *JSON) selectorRanges(table *Table, asTable string, params map[string]interface{}, rangesByColID map[uint32]*typedValueRange) error {
1✔
85
        return nil
1✔
86
}
1✔
87

88
func (v *JSON) RawValue() interface{} {
1,074✔
89
        return v.val
1,074✔
90
}
1,074✔
91

92
func (v *JSON) Compare(val TypedValue) (int, error) {
2,433✔
93
        if val.IsNull() {
2,441✔
94
                return val.Compare(v)
8✔
95
        }
8✔
96

97
        tv, ok := v.castToTypedValue()
2,425✔
98
        if !ok {
2,632✔
99
                return -1, fmt.Errorf("%w: comparison not defined for JSON %s", ErrNotComparableValues, v.primitiveType())
207✔
100
        }
207✔
101

102
        if val.Type() != JSONType {
3,931✔
103
                return tv.Compare(val)
1,713✔
104
        }
1,713✔
105

106
        res, err := val.Compare(tv)
505✔
107
        return -res, err
505✔
108
}
109

110
func (v *JSON) primitiveType() string {
507✔
111
        switch v.val.(type) {
507✔
112
        case int64, float64:
72✔
113
                return JSONTypeNumber
72✔
114
        case string:
36✔
115
                return JSONTypeString
36✔
116
        case bool:
51✔
117
                return JSONTypeBool
51✔
118
        case nil:
30✔
119
                return JSONTypeNull
30✔
120
        case []interface{}:
48✔
121
                return JSONTypeArray
48✔
122
        }
123
        return JSONTypeObject
270✔
124
}
125

126
func (v *JSON) castToTypedValue() (TypedValue, bool) {
2,528✔
127
        var tv TypedValue
2,528✔
128
        switch val := v.val.(type) {
2,528✔
129
        case int64:
2✔
130
                tv = NewInteger(val)
2✔
131
        case string:
1,102✔
132
                tv = NewVarchar(val)
1,102✔
133
        case float64:
1,114✔
134
                tv = NewFloat64(val)
1,114✔
135
        case bool:
103✔
136
                tv = NewBool(val)
103✔
UNCOV
137
        case nil:
×
UNCOV
138
                tv = NewNull(JSONType)
×
139
        default:
207✔
140
                return nil, false
207✔
141
        }
142
        return tv, true
2,321✔
143
}
144

145
func (v *JSON) String() string {
25✔
146
        data, _ := json.Marshal(v.val)
25✔
147
        return string(data)
25✔
148
}
25✔
149

150
func (v *JSON) lookup(fields []string) TypedValue {
2,233✔
151
        currVal := v.val
2,233✔
152
        for i, field := range fields {
7,838✔
153
                switch cv := currVal.(type) {
5,605✔
154
                case map[string]interface{}:
5,425✔
155
                        v, hasField := cv[field]
5,425✔
156
                        if !hasField || (v == nil && i < len(field)-1) {
5,425✔
157
                                return NewNull(AnyType)
×
158
                        }
×
159
                        currVal = v
5,425✔
160

5,425✔
161
                        if currVal == nil {
5,425✔
162
                                break
×
163
                        }
164
                case []interface{}:
116✔
165
                        idx, err := strconv.ParseInt(field, 10, 64)
116✔
166
                        if err != nil || idx < 0 || idx >= int64(len(cv)) {
132✔
167
                                return NewNull(AnyType)
16✔
168
                        }
16✔
169
                        currVal = cv[idx]
100✔
170
                default:
64✔
171
                        return NewNull(AnyType)
64✔
172
                }
173
        }
174
        return NewJson(currVal)
2,153✔
175
}
176

177
type JSONSelector struct {
178
        *ColSelector
179
        fields []string
180
}
181

182
func (sel *JSONSelector) substitute(params map[string]interface{}) (ValueExp, error) {
400✔
183
        return sel, nil
400✔
184
}
400✔
185

186
func (v *JSONSelector) alias() string {
1,440✔
187
        if v.ColSelector.as != "" {
2,040✔
188
                return v.ColSelector.as
600✔
189
        }
600✔
190
        return v.String()
840✔
191
}
192

193
func (v *JSONSelector) resolve(implicitTable string) (string, string, string) {
725✔
194
        aggFn, table, _ := v.ColSelector.resolve(implicitTable)
725✔
195
        return aggFn, table, v.String()
725✔
196
}
725✔
197

198
func (v *JSONSelector) String() string {
1,566✔
199
        return fmt.Sprintf("%s->'%s'", v.ColSelector.col, strings.Join(v.fields, "->"))
1,566✔
200
}
1,566✔
201

202
func (sel *JSONSelector) reduce(tx *SQLTx, row *Row, implicitTable string) (TypedValue, error) {
2,134✔
203
        val, err := sel.ColSelector.reduce(tx, row, implicitTable)
2,134✔
204
        if err != nil {
2,134✔
205
                return nil, err
×
206
        }
×
207

208
        jsonVal, ok := val.(*JSON)
2,134✔
209
        if !ok {
2,135✔
210
                return val, fmt.Errorf("-> operator cannot be applied on column of type %s", val.Type())
1✔
211
        }
1✔
212
        return jsonVal.lookup(sel.fields), nil
2,133✔
213
}
214

215
func (sel *JSONSelector) reduceSelectors(row *Row, implicitTable string) ValueExp {
100✔
216
        val := sel.ColSelector.reduceSelectors(row, implicitTable)
100✔
217

100✔
218
        jsonVal, ok := val.(*JSON)
100✔
219
        if !ok {
100✔
220
                return sel
×
221
        }
×
222
        return jsonVal.lookup(sel.fields)
100✔
223
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc