-
Notifications
You must be signed in to change notification settings - Fork 6
/
type.go
289 lines (242 loc) · 7.71 KB
/
type.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
package pqt
import "fmt"
// Type ...
type Type interface {
fmt.Stringer
// Fingerprint returns unique identifier of the type. Two different types can have same SQL representation.
Fingerprint() string
}
// BaseType ...
type BaseType struct {
name string
}
// String implements Stringer interface.
func (bt BaseType) String() string {
return bt.name
}
// Fingerprint implements Type interface.
func (bt BaseType) Fingerprint() string {
return fmt.Sprintf("base: %s", bt.name)
}
// TypeDecimal ...
func TypeDecimal(precision, scale int) BaseType {
switch {
case precision == 0:
return BaseType{name: "DECIMAL"}
case precision != 0 && scale == 0:
return BaseType{name: fmt.Sprintf("DECIMAL(%d)", precision)}
default:
return BaseType{name: fmt.Sprintf("DECIMAL(%d,%d)", precision, scale)}
}
}
// TypeReal ...
func TypeReal() BaseType {
return BaseType{name: "REAL"}
}
// TypeSerial ...
func TypeSerial() BaseType {
return BaseType{name: "SERIAL"}
}
// TypeSerialSmall ...
func TypeSerialSmall() BaseType {
return BaseType{name: "SMALLSERIAL"}
}
// TypeSerialBig ...
func TypeSerialBig() BaseType {
return BaseType{name: "BIGSERIAL"}
}
// TypeInteger is the common choice, as it offers the best balance between range, storage size, and performance.
func TypeInteger() BaseType {
return BaseType{name: "INTEGER"}
}
// TypeIntegerSmall is generally only used if disk space is at a premium.
func TypeIntegerSmall() BaseType {
return BaseType{name: "SMALLINT"}
}
// TypeIntegerBig is designed to be used when the range of the TypeInteger is insufficient.
func TypeIntegerBig() BaseType {
return BaseType{name: "BIGINT"}
}
// TypeIntegerArray ...
func TypeIntegerArray(l int) BaseType {
if l == 0 {
return BaseType{name: "INTEGER[]"}
}
return BaseType{name: fmt.Sprintf("INTEGER[%d]", l)}
}
// TypeIntegerBigArray ...
func TypeIntegerBigArray(l int) BaseType {
if l == 0 {
return BaseType{name: "BIGINT[]"}
}
return BaseType{name: fmt.Sprintf("BIGINT[%d]", l)}
}
// TypeIntegerSmallArray ...
func TypeIntegerSmallArray(l int) BaseType {
if l == 0 {
return BaseType{name: "SMALLINT[]"}
}
return BaseType{name: fmt.Sprintf("SMALLINT[%d]", l)}
}
// TypeDoubleArray ...
func TypeDoubleArray(l int) BaseType {
if l == 0 {
return BaseType{name: "DOUBLE PRECISION[]"}
}
return BaseType{name: fmt.Sprintf("DOUBLE PRECISION[%d]", l)}
}
// TypeNumeric can store numbers with a very large number of digits.
// It is especially recommended for storing monetary amounts and other quantities where exactness is required.
// Calculations with numeric values yield exact results where possible, e.g. addition, subtraction, multiplication.
// However, calculations on numeric values are very slow compared to the integer types, or to the floating-point types described in the next section.
func TypeNumeric(precision, scale int) BaseType {
switch {
case precision == 0:
return BaseType{name: "NUMERIC"}
case precision != 0 && scale == 0:
return BaseType{name: fmt.Sprintf("NUMERIC(%d)", precision)}
default:
return BaseType{name: fmt.Sprintf("NUMERIC(%d,%d)", precision, scale)}
}
}
// TypeDoublePrecision is a numeric type with 15 decimal digits precision.
func TypeDoublePrecision() BaseType {
return BaseType{name: "DOUBLE PRECISION"}
}
// TypeBool is a state of true or false.
func TypeBool() BaseType {
return BaseType{name: "BOOL"}
}
// TypeUUID stores Universally Unique Identifiers (UUID) as defined by RFC 4122, ISO/IEC 9834-8:2005, and related standards.
// (Some systems refer to this data type as a globally unique identifier, or GUID, instead.)
// This identifier is a 128-bit quantity that is generated by an algorithm chosen to make it very unlikely that the same identifier will be generated by anyone else in the known universe using the same algorithm.
// Therefore, for distributed systems, these identifiers provide a better uniqueness guarantee than sequence generators, which are only unique within a single database.
func TypeUUID() BaseType {
return BaseType{name: "UUID"}
}
// TypeCharacter is physically padded with spaces to the specified width n, and are stored and displayed that way.
func TypeCharacter(l int) BaseType {
return BaseType{name: fmt.Sprintf("CHARACTER[%d]", l)}
}
// TypeText is variable-length character string.
func TypeText() BaseType {
return BaseType{name: "TEXT"}
}
// TypeTextArray ...
func TypeTextArray(l int) BaseType {
if l == 0 {
return BaseType{name: "TEXT[]"}
}
return BaseType{name: fmt.Sprintf("TEXT[%d]", l)}
}
// TypeVarchar ...
func TypeVarchar(l int) BaseType {
if l == 0 {
return BaseType{name: "VARCHAR"}
}
return BaseType{name: fmt.Sprintf("VARCHAR(%d)", l)}
}
// TypeBytea ...
func TypeBytea() BaseType {
return BaseType{name: "BYTEA"}
}
// TypeTimestamp is a date and time (no time zone).
func TypeTimestamp() BaseType {
return BaseType{name: "TIMESTAMP"}
}
// TypeTimestampTZ is a date and time, including time zone
func TypeTimestampTZ() BaseType {
return BaseType{name: "TIMESTAMPTZ"}
}
// TypeJSON is for storing JSON (JavaScript Object Notation) data, as specified in RFC 7159.
// Such data can also be stored as text, but the JSON data types have the advantage of enforcing that each stored value is valid according to the JSON rules.
func TypeJSON() BaseType {
return BaseType{name: "JSON"}
}
// TypeJSONB in compare to TypeJSON is stored in a decomposed binary format that makes it slightly slower to input due to added conversion overhead, but significantly faster to process, since no reparsing is needed.
// JSONB also supports indexing, which can be a significant advantage.
func TypeJSONB() BaseType {
return BaseType{name: "JSONB"}
}
// CompositeType represents the structure of a row or record.
// It is essentially just a list of field names and their data types.
// PostgreSQL allows composite types to be used in many of the same ways that simple types can be used.
// For example, a column of a table can be declared to be of a composite type.
type CompositeType struct {
name string
Attributes []*Attribute
}
// String implements Stringer interface.
func (ct CompositeType) String() string {
return "" // TODO: ?
}
// Fingerprint implements Type interface.
func (ct CompositeType) Fingerprint() string {
return fmt.Sprintf("composite: %v", ct)
}
// TypeComposite allocates CompositeType with given name and attributes.
func TypeComposite(name string, attributes ...*Attribute) CompositeType {
return CompositeType{
name: name,
Attributes: attributes,
}
}
// EnumeratedType ...
type EnumeratedType struct {
name string
Enums []string
}
// String implements Stringer interface.
func (et EnumeratedType) String() string {
return et.name
}
// Fingerprint implements Type interface.
func (et EnumeratedType) Fingerprint() string {
return fmt.Sprintf("enumarated: %v", et)
}
// TypeEnumerated ...
func TypeEnumerated(name string, enums ...string) EnumeratedType {
return EnumeratedType{
name: name,
Enums: enums,
}
}
// PseudoType ...
type PseudoType struct {
name string
// input, output Function
}
// String implements Stringer interface.
func (pt PseudoType) String() string {
return pt.name
}
// Fingerprint implements Type interface.
func (pt PseudoType) Fingerprint() string {
return fmt.Sprintf("pseudo: %v", pt)
}
// TypePseudo ...
func TypePseudo(name string) PseudoType {
return PseudoType{
name: name,
}
}
// MappableType ...
type MappableType struct {
From Type
Mapping []Type
}
// String implements Stringer interface.
func (mt MappableType) String() string {
return mt.From.String()
}
// Fingerprint implements Type interface.
func (mt MappableType) Fingerprint() string {
return fmt.Sprintf("mappable: %v", mt)
}
// TypeMappable ...
func TypeMappable(from Type, mapping ...Type) MappableType {
return MappableType{
From: from,
Mapping: mapping,
}
}