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
|
#pragma once
#include "Core/GcArray.h"
#include "Core/GcType.h"
#include "Core/Variant.h"
namespace sql {
/**
* Representation of a single row as a result from a database query.
*
* Behaves similarly to a read-only array, but that may contain different types. The accessor
* functions that mention specific types throw if the type is incorrect. Type inspection is
* possible through the generic `at` function that creates a `Variant` (note: the at function is
* a free function for technical reasons).
*
* Note: The class automatically casts between `Int` and `Long`, as well as `Float` and `Double`
* as required.
*/
class Row {
STORM_VALUE;
public:
// For ability to use in a Maybe<T> in C++.
Row();
// Deep copy to maintain thread safety.
void STORM_FN deepCopy(CloneEnv *env);
// Get number of columns.
Nat STORM_FN count() const { return Nat(data->count); }
// Get a column as a string.
Str *STORM_FN getStr(Nat index) const;
// Get a column as a boolean.
Bool STORM_FN getBool(Nat index) const;
// Get a column as an integer.
Int STORM_FN getInt(Nat index) const;
// Get a column as a long.
Long STORM_FN getLong(Nat index) const;
// Get a column as a float.
Float STORM_FN getFloat(Nat index) const;
// Get a column as a double.
Double STORM_FN getDouble(Nat index) const;
// Check if a column is null.
Bool STORM_FN isNull(Nat index) const;
// Output.
void STORM_FN toS(StrBuf *to) const;
private:
// Primitive types. Stored in the object value as pointers.
enum ColType {
COL_NULL = 0, // null pointer for empty
COL_LONG, // long
COL_DOUBLE, // double
COL_LAST, // last one, for quick check that the type is an object.
};
struct Element {
// Pointer to an object. Also used to indicate the type of primitives.
// Note: We sometimes store small integers here. Inspecting the MPS code
// reveals that this should be safe, since the MPS only examines pointers
// that refer to memory managed by the MPS. The page from 0 to approx 4k
// are never managed by the MPS, so this is safe to do.
void *object;
// Data for primitive objects.
union {
Long l;
Double d;
};
};
// Type for the elements.
static const GcType elemType;
// Data storage. Read-only, so assumed to be immutable.
GcArray<Element> *data;
// Check if index is valid.
const Element &checkIndex(Nat index) const;
// Throw type error.
void throwTypeError(const wchar *expected, const Element &elem) const;
// At function.
friend Variant at(EnginePtr e, const Row &row, Nat index);
public:
/**
* Builder class for a row.
*/
class Builder {
STORM_VALUE;
public:
// Create.
Builder(GcArray<Element> *elems);
// Add columns.
void STORM_FN push(Str *v);
void STORM_FN push(Long l);
void STORM_FN push(Double d);
void STORM_FN pushNull();
private:
// Data being populated.
GcArray<Element> *data;
// Check so that we are not full.
Element &next();
friend class Row;
};
// Create from a builder.
STORM_CTOR Row(Builder b);
// Create a builder.
static Builder STORM_FN builder(EnginePtr e, Nat columns);
};
// Get a column. Creates a Variant, so is slower than using typed accessors.
Variant STORM_FN at(EnginePtr e, const Row &row, Nat index);
}
|