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
|
#include "stdafx.h"
#include "Type.h"
#include "Exception.h"
#include "StrUtils.h"
namespace sql {
QueryType::QueryType() : type(0), typeSize(0) {}
QueryType::QueryType(Nat typeId) : type(typeId), typeSize(0) {}
QueryType::QueryType(Nat typeId, Nat size) : type(typeId), typeSize(size) {}
Bool QueryType::compatible(const QueryType &o) const {
if (!sameType(o))
return false;
if (typeSize == 0)
return true;
if (o.typeSize == 0)
return true;
return typeSize <= o.typeSize;
}
static bool isAlpha(wchar ch) {
return (ch >= 'a' && ch <= 'z')
|| (ch >= 'A' && ch <= 'Z');
}
QueryType QueryType::parse(Str *from) {
const wchar *nameBegin = from->c_str();
while (*nameBegin == ' ')
nameBegin++;
const wchar *nameEnd = nameBegin;
while (isAlpha(*nameEnd))
nameEnd++;
QueryType result;
if (compareNoCase(nameBegin, nameEnd, S("tinyint"))) {
return QueryType::integer().sized(1);
} else if (compareNoCase(nameBegin, nameEnd, S("smallint"))) {
return QueryType::integer().sized(2);
} else if (compareNoCase(nameBegin, nameEnd, S("mediumint"))) {
return QueryType::integer().sized(3);
} else if (compareNoCase(nameBegin, nameEnd, S("int"))) {
return QueryType::integer().sized(4);
} else if (compareNoCase(nameBegin, nameEnd, S("integer"))) {
return QueryType::integer().sized(4);
} else if (compareNoCase(nameBegin, nameEnd, S("bigint"))) {
return QueryType::integer().sized(8);
} else if (compareNoCase(nameBegin, nameEnd, S("real"))) {
return QueryType::real().sized(4);
} else if (compareNoCase(nameBegin, nameEnd, S("double"))) {
return QueryType::real().sized(8);
} else if (compareNoCase(nameBegin, nameEnd, S("text"))) {
result = QueryType::text();
} else if (compareNoCase(nameBegin, nameEnd, S("varchar"))) {
result = QueryType::text();
} else {
// We don't know the type. Just return the empty result.
return result;
// StrBuf *msg = new (from) StrBuf();
// *msg << S("Unknown type: ");
// *msg << new (from) Str(nameBegin, nameEnd);
// throw new (from) SQLError(msg->toS());
}
// Find the size if it exists.
const wchar *paren = nameEnd;
while (*paren == ' ')
paren++;
if (*paren == '(') {
paren++;
Nat size = 0;
while (*paren != ')') {
if (*paren == ' ') {
paren++;
continue;
}
if (*paren < '0' || *paren > '9')
throw new (from) SQLError(TO_S(from, S("Invalid size in SQL type: ") << from));
size = size*10 + (*paren - '0');
paren++;
}
// Consume end )
paren++;
// Consume any whitespace.
while (*paren == ' ')
paren++;
result.typeSize = size + 1;
}
if (*paren != '\0') {
throw new (from) SQLError(TO_S(from, S("Improperly formatted SQL type: ") << from));
}
return result;
}
void QueryType::toS(StrBuf *to) const {
if (sameType(QueryType())) {
*to << S("VOID");
} else if (sameType(QueryType::text())) {
*to << S("TEXT");
} else if (sameType(QueryType::integer())) {
*to << S("INTEGER");
} else if (sameType(QueryType::real())) {
*to << S("REAL");
} else {
*to << S("<invalid type>");
}
Maybe<Nat> size = this->size();
if (size.any())
*to << S("(") << size.value() << S(")");
}
}
|