template<> NValue NValue::callUnary<FUNC_VOLT_ASTEXT_GEOGRAPHY>() const { assert(getValueType() == VALUE_TYPE_GEOGRAPHY); if (isNull()) { return NValue::getNullValue(VALUE_TYPE_VARCHAR); } const std::string polygonAsText = getGeographyValue().toWKT(); return getTempStringValue(polygonAsText.c_str(), polygonAsText.length()); }
template<> NValue NValue::callUnary<FUNC_VOLT_POLYGON_CENTROID>() const { if (isNull()) { return NValue::getNullValue(VALUE_TYPE_POINT); } Polygon polygon; polygon.initFromGeography(getGeographyValue()); const GeographyPointValue point(polygon.GetCentroid()); NValue retVal(VALUE_TYPE_POINT); retVal.getGeographyPointValue() = point; return retVal; }
template<> NValue NValue::callUnary<FUNC_VOLT_POLYGON_NUM_INTERIOR_RINGS>() const { if (isNull()) { return NValue::getNullValue(VALUE_TYPE_INTEGER); } Polygon poly; poly.initFromGeography(getGeographyValue()); NValue retVal(VALUE_TYPE_INTEGER); // exclude exterior ring retVal.getInteger() = poly.num_loops() - 1; return retVal; }
template<> NValue NValue::callUnary<FUNC_VOLT_POLYGON_AREA>() const { if (isNull()) { return NValue::getNullValue(VALUE_TYPE_DOUBLE); } Polygon polygon; polygon.initFromGeography(getGeographyValue()); NValue retVal(VALUE_TYPE_DOUBLE); // area is in steradians which is a solid angle. Earth in the calculation is treated as sphere // and area of sphere can be calculated as steradians * radius^2 retVal.getDouble() = polygon.GetArea() * RADIUS_SQ_M; return retVal; }
template<> NValue NValue::callUnary<FUNC_VOLT_VALIDATE_POLYGON>() const { assert(getValueType() == VALUE_TYPE_GEOGRAPHY); if (isNull()) { return NValue::getNullValue(VALUE_TYPE_BOOLEAN); } // Be optimistic. bool returnval = true; // Extract the polygon and check its validity. Polygon poly; poly.initFromGeography(getGeographyValue()); if (!poly.IsValid() || isMultiPolygon(poly)) { returnval = false; } return ValueFactory::getBooleanValue(returnval); }
template<> NValue NValue::callUnary<FUNC_VOLT_POLYGON_NUM_POINTS>() const { if (isNull()) { return NValue::getNullValue(VALUE_TYPE_INTEGER); } Polygon poly; poly.initFromGeography(getGeographyValue()); // the OGC spec suggests that the number of vertices should // include the repeated closing vertex which is implicit in S2's // representation. So add an extra vertex for each loop. int32_t numPoints = poly.num_vertices() + poly.num_loops(); NValue retVal(VALUE_TYPE_INTEGER); retVal.getInteger() = numPoints; return retVal; }
template<> NValue NValue::callUnary<FUNC_VOLT_POLYGON_INVALID_REASON>() const { assert(getValueType() == VALUE_TYPE_GEOGRAPHY); if (isNull()) { return NValue::getNullValue(VALUE_TYPE_VARCHAR); } // Extract the polygon and check its validity. std::stringstream msg; Polygon poly; poly.initFromGeography(getGeographyValue()); if (poly.IsValid(&msg)) { isMultiPolygon(poly, &msg); } std::string res (msg.str()); if (res.size() == 0) { res = std::string("Valid Polygon"); } return getTempStringValue(res.c_str(),res.length()); }
/* * Produce a debugging string describing an NValue. */ std::string NValue::debug() const { const ValueType type = getValueType(); if (isNull()) { return "<NULL>"; } std::ostringstream buffer; std::string out_val; const char* ptr; int64_t addr; buffer << getTypeName(type) << "::"; switch (type) { case VALUE_TYPE_BOOLEAN: buffer << (getBoolean() ? "true" : "false"); break; case VALUE_TYPE_TINYINT: buffer << static_cast<int32_t>(getTinyInt()); break; case VALUE_TYPE_SMALLINT: buffer << getSmallInt(); break; case VALUE_TYPE_INTEGER: buffer << getInteger(); break; case VALUE_TYPE_BIGINT: buffer << getBigInt(); break; case VALUE_TYPE_DOUBLE: buffer << getDouble(); break; case VALUE_TYPE_VARCHAR: { int32_t length; ptr = getObject_withoutNull(&length); addr = reinterpret_cast<int64_t>(ptr); out_val = std::string(ptr, length); buffer << "[" << length << "]"; buffer << "\"" << out_val << "\"[@" << addr << "]"; break; } case VALUE_TYPE_VARBINARY: { int32_t length; ptr = getObject_withoutNull(&length); addr = reinterpret_cast<int64_t>(ptr); out_val = std::string(ptr, length); buffer << "[" << length << "]"; buffer << "-bin[@" << addr << "]"; break; } case VALUE_TYPE_DECIMAL: buffer << createStringFromDecimal(); break; case VALUE_TYPE_TIMESTAMP: { try { std::stringstream ss; streamTimestamp(ss); buffer << ss.str(); } catch (const SQLException &) { buffer << "<out of range timestamp:" << getBigInt() << ">"; } catch (...) { buffer << "<exception when converting timestamp:" << getBigInt() << ">"; } break; } case VALUE_TYPE_POINT: buffer << getGeographyPointValue().toString(); break; case VALUE_TYPE_GEOGRAPHY: buffer << getGeographyValue().toString(); break; default: buffer << "(no details)"; break; } std::string ret(buffer.str()); return (ret); }