summaryrefslogtreecommitdiff
path: root/src/duckdb/Column.zig
blob: fb505bb783843eff7c3397d6795fb5720d0b35c9 (plain)
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
const std   = @import("std");
const c = @cImport({
    @cInclude("duckdb.h");
});


const DuckdbType = enum {
    BOOLEAN,
    TINYINT,
    SMALLINT,
    INTEGER,
    BIGINT,
    UTINYINT,
    USMALLINT,
    UINTEGER,
    UBIGINT,
    FLOAT,
    DOUBLE,
    TIMESTAMP,
    DATE,
    TIME,
    INTERVAL,
    HUGEINT,
    UHUGEINT,
    VARCHAR,
    BLOB,
    TIMESTAMP_S,
    TIMESTAMP_MS,
    TIMESTAMP_NS,
    UUID,
    TIME_TZ,
    TIMESTAMP_TZ,
};

pub const Column = union(DuckdbType) {
    BOOLEAN:      [*]bool,
    TINYINT:      [*]i8,
    SMALLINT:     [*]i16,
    INTEGER:      [*]i32,
    BIGINT:       [*]i64,
    UTINYINT:     [*]u8,
    USMALLINT:    [*]u16,
    UINTEGER:     [*]u32,
    UBIGINT:      [*]u64,
    FLOAT:        [*]f32,
    DOUBLE:       [*]f64,
    TIMESTAMP:    [*]c.duckdb_timestamp,
    DATE:         [*]c.duckdb_date,
    TIME:         [*]c.duckdb_time,
    INTERVAL:     [*]c.duckdb_interval,
    HUGEINT:      [*]c.duckdb_hugeint,
    UHUGEINT:     [*]c.duckdb_uhugeint,
    VARCHAR:      [*]c.duckdb_string_t,
    BLOB:         [*]c.duckdb_string_t,
    TIMESTAMP_S:  [*]c.duckdb_timestamp,
    TIMESTAMP_MS: [*]c.duckdb_timestamp,
    TIMESTAMP_NS: [*]c.duckdb_timestamp,
    UUID:         [*]c.duckdb_hugeint,
    TIME_TZ:      [*]c.duckdb_time_tz,
    TIMESTAMP_TZ: [*]c.duckdb_timestamp,

    const Self = @This();

    pub fn fromType(column_type: c.DUCKDB_TYPE, column: *anyopaque) Column {
        return switch (column_type) {
            c.DUCKDB_TYPE_BOOLEAN      => .{.BOOLEAN      = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_TINYINT      => .{.TINYINT      = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_SMALLINT     => .{.SMALLINT     = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_INTEGER      => .{.INTEGER      = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_BIGINT       => .{.BIGINT       = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_UTINYINT     => .{.UTINYINT     = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_USMALLINT    => .{.USMALLINT    = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_UINTEGER     => .{.UINTEGER     = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_UBIGINT      => .{.UBIGINT      = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_FLOAT        => .{.FLOAT        = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_DOUBLE       => .{.DOUBLE       = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_VARCHAR      => .{.VARCHAR      = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_BLOB         => .{.BLOB         = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_TIMESTAMP    => .{.TIMESTAMP    = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_DATE         => .{.DATE         = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_TIME         => .{.TIME         = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_INTERVAL     => .{.INTERVAL     = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_HUGEINT      => .{.HUGEINT      = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_UHUGEINT     => .{.UHUGEINT     = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_TIMESTAMP_S  => .{.TIMESTAMP_S  = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_TIMESTAMP_MS => .{.TIMESTAMP_MS = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_TIMESTAMP_NS => .{.TIMESTAMP_NS = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_UUID         => .{.UUID         = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_TIME_TZ      => .{.TIME_TZ      = @alignCast(@ptrCast(column))},
            c.DUCKDB_TYPE_TIMESTAMP_TZ => .{.TIMESTAMP_TZ = @alignCast(@ptrCast(column))},
            else => unreachable,
        };
    }

    pub fn getAs(self: Self, i: usize, T: anytype) !T{
        const ti : std.builtin.Type = @typeInfo(T);
        switch (self){
            .BOOLEAN
                => |ptr| switch(ti) {
                .Bool => return ptr[i],
                .Int  => return @intFromBool(ptr[i]),
                else  => return error.InvalidConversion,
            },
            .TINYINT
                => |ptr| switch(ti) {
                .Int    => return @intCast(ptr[i]),
                .Float  => return @floatFromInt(ptr[i]),
                else    => return error.InvalidConversion,
            },
            .SMALLINT
                => |ptr| switch(ti) {
                .Int    => return @intCast(ptr[i]),
                .Float  => return @floatFromInt(ptr[i]),
                else    => return error.InvalidConversion,
            },
            .INTEGER
                => |ptr| switch(ti) {
                .Int    => return @intCast(ptr[i]),
                .Float  => return @floatFromInt(ptr[i]),
                else    => return error.InvalidConversion,
            },
            .BIGINT
                => |ptr| switch(ti) {
                .Int    => return @intCast(ptr[i]),
                .Float  => return @floatFromInt(ptr[i]),
                else    => return error.InvalidConversion,
            },
            .UTINYINT
                => |ptr| switch(ti) {
                .Int    => return @intCast(ptr[i]),
                .Float  => return @floatFromInt(ptr[i]),
                else    => return error.InvalidConversion,
            },
            .USMALLINT
                => |ptr| switch(ti) {
                .Int    => return @intCast(ptr[i]),
                .Float  => return @floatFromInt(ptr[i]),
                else    => return error.InvalidConversion,
            },
            .UINTEGER
                => |ptr| switch(ti) {
                .Int    => return @intCast(ptr[i]),
                .Float  => return @floatFromInt(ptr[i]),
                else    => return error.InvalidConversion,
            },
            .UBIGINT
                => |ptr| switch(ti) {
                .Int    => return @intCast(ptr[i]),
                .Float  => return @floatFromInt(ptr[i]),
                else    => return error.InvalidConversion,
            },
            .FLOAT
                => |ptr| switch(ti) {
                .Int    => return @intFromFloat(ptr[i]),
                .Float  => return @floatCast(ptr[i]),
                else    => return error.InvalidConversion,
            },
            .DOUBLE
                => |ptr| switch(ti) {
                .Int    => return @intFromFloat(ptr[i]),
                .Float  => return @floatCast(ptr[i]),
                else    => return error.InvalidConversion,
            },
            .VARCHAR,
            .BLOB
                => |ptr| switch(ti){
                .Pointer => |p| switch (p.size) {
                    .Slice => {
                        if ( p.child == u8 ) {
                            var result: T = undefined;
                            if (c.duckdb_string_is_inlined(ptr[i])){
                                result = &ptr[i].value.inlined.inlined;
                                result.len = ptr[i].value.inlined.length;
                                return result;
                            } else {
                                result.len = ptr[i].value.pointer.length;
                                result.ptr = ptr[i].value.pointer.ptr;
                                return result;
                            }
                        } else {
                            @compileError("Invalid type for output data: "
                                ++ @typeName(T));
                        }
                    },
                    else    => return error.InvalidConversion,
                },
                else    => return error.InvalidConversion,
            },
            .TIMESTAMP,
            .DATE,
            .TIME,
            .INTERVAL,
            .HUGEINT,
            .UHUGEINT,
            .TIMESTAMP_S,
            .TIMESTAMP_MS,
            .TIMESTAMP_NS,
            .UUID,
            .TIME_TZ,
            .TIMESTAMP_TZ =>
                return error.ConversionNotImplemented,
        }
    }
};