diff --git a/contrib/babelfishpg_tsql/src/tsqlIface.cpp b/contrib/babelfishpg_tsql/src/tsqlIface.cpp index 3c2c82b452..af601fec08 100644 --- a/contrib/babelfishpg_tsql/src/tsqlIface.cpp +++ b/contrib/babelfishpg_tsql/src/tsqlIface.cpp @@ -881,10 +881,394 @@ class tsqlCommonMutator : public TSqlParserBaseListener rewritten_query_fragment.emplace(std::make_pair(ctx->id().back()->start->getStartIndex(), std::make_pair(::getFullText(ctx->id().back()), delimit_identifier(ctx->id().back())))); } + void exitFunction_call(TSqlParser::Function_callContext *ctx) override + { + if (ctx->func_proc_name_server_database_schema() && ctx->func_proc_name_server_database_schema()->procedure) + { + std::string proc_name = stripQuoteFromId(ctx->func_proc_name_server_database_schema()->procedure); + + /* This if-elseIf clause rewrites the query in case of Geospatial function Call */ + if (strcmp(proc_name.c_str(), "STDistance") == 0 && ctx->func_proc_name_server_database_schema()->schema && ctx->function_arg_list()) + { + std::string func_ctx = ::getFullText(ctx); + std::string arg_ctx = ::getFullText(ctx->function_arg_list()); + int index = (int) ctx->func_proc_name_server_database_schema()->stop->getStopIndex() - ctx->func_proc_name_server_database_schema()->start->getStartIndex() + 1; + int length = (int) ctx->function_arg_list()->start->getStartIndex() - ctx->func_proc_name_server_database_schema()->stop->getStopIndex() - 1; + + /* Shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->function_arg_list()->start->getStartIndex() && entry.first <= ctx->function_arg_list()->stop->getStopIndex()) + { + size_t pos = entry.first; + size_t offset = ctx->func_proc_name_server_database_schema()->procedure->start->getStartIndex() - ctx->func_proc_name_server_database_schema()->start->getStartIndex(); + pos -= offset; + local_id_positions.emplace(std::make_pair(pos, entry.second)); + local_id_positions.erase(entry.first); + } + } + + /* + * Rewriting the query as: table.col.STDistance(arg) -> STDistance(arg, table.col) + */ + arg_ctx += ","; + if (ctx->func_proc_name_server_database_schema()->database) arg_ctx += stripQuoteFromId(ctx->func_proc_name_server_database_schema()->database) + "."; + arg_ctx += stripQuoteFromId(ctx->func_proc_name_server_database_schema()->schema); + std::string rewritten_func = proc_name + func_ctx.substr(index, length) + arg_ctx + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->func_proc_name_server_database_schema()->start->getStartIndex(), std::make_pair(::getFullText(ctx), rewritten_func.c_str()))); + } + else if ((strcmp(proc_name.c_str(), "STAsText") == 0 || strcmp(proc_name.c_str(), "STAsBinary") == 0) && ctx->func_proc_name_server_database_schema()->schema && !ctx->function_arg_list()) + { + std::string func_ctx = ::getFullText(ctx); + /* Space is provided to distinguish it from ALL | DISTINCT keywords */ + std::string arg_ctx = " "; + int index = (int) ctx->func_proc_name_server_database_schema()->stop->getStopIndex() - ctx->func_proc_name_server_database_schema()->start->getStartIndex() + 1; + int length = (int) ctx->stop->getStopIndex() - ctx->func_proc_name_server_database_schema()->stop->getStopIndex() - 1; + /* + * Rewriting the query as: table.col.STAsText() -> STAsText(table.col) + */ + if (ctx->func_proc_name_server_database_schema()->database) arg_ctx += stripQuoteFromId(ctx->func_proc_name_server_database_schema()->database) + "."; + arg_ctx += stripQuoteFromId(ctx->func_proc_name_server_database_schema()->schema); + std::string rewritten_func = proc_name + func_ctx.substr(index, length) + arg_ctx + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->func_proc_name_server_database_schema()->start->getStartIndex(), std::make_pair(::getFullText(ctx), rewritten_func.c_str()))); + } + } + } + + void exitFunc_call_expr(TSqlParser::Func_call_exprContext *ctx) override + { + if(ctx != NULL && ctx->function_call() != NULL && !ctx->DOT().empty()) + { + std::vector method_calls = ctx->method_call(); + for (size_t i=0; i function_call.method_call */ + if(method->spatial_methods()) + { + std::string proc_name = stripQuoteFromId(method->spatial_methods()->method); + if((strcmp(proc_name.c_str(), "STX") == 0 || strcmp(proc_name.c_str(), "STY") == 0 || strcmp(proc_name.c_str(), "LAT") == 0 || strcmp(proc_name.c_str(), "LONG") == 0 || + strcmp(proc_name.c_str(), "[STX]") == 0 || strcmp(proc_name.c_str(), "[STY]") == 0 || strcmp(proc_name.c_str(), "[LAT]") == 0 || strcmp(proc_name.c_str(), "[LONG]") == 0) && !method->spatial_methods()->LR_BRACKET() ) + { + std::string ctx_str = ::getFullText(ctx); + int func_call_len = (int)ctx->function_call()->stop->getStopIndex() - ctx->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->function_call()->stop->getStopIndex()) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->function_call()->start->getStartIndex() && entry.first <= ctx->function_call()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + 1, entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = "(" + expr.substr(0, func_call_len+offset1+1) + ")." + expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2 + 1); + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + if((strcmp(proc_name.c_str(), "STAsText") == 0 || strcmp(proc_name.c_str(), "STAsBinary") == 0) && !method->spatial_methods()->expression_list() ) + { + std::string ctx_str = ::getFullText(ctx); + int func_call_len = (int)ctx->function_call()->stop->getStopIndex() - ctx->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->function_call()->stop->getStopIndex()) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->function_call()->start->getStartIndex() && entry.first <= ctx->function_call()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + proc_name.size() + 1, entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2) + expr.substr(0, func_call_len+offset1+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + if(strcmp(proc_name.c_str(), "STDistance") == 0 && method->spatial_methods()->expression_list() ) + { + std::string ctx_str = ::getFullText(ctx); + int func_call_len = (int)ctx->function_call()->stop->getStopIndex() - ctx->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->function_call()->stop->getStopIndex()) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->function_call()->start->getStartIndex() && entry.first <= ctx->function_call()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + method->spatial_methods()->expression_list()->stop->getStopIndex() - method->spatial_methods()->method->start->getStartIndex() + 2, entry.second)); + local_id_positions.erase(entry.first); + } + else if(entry.first >= method->spatial_methods()->expression_list()->start->getStartIndex() && entry.first <= method->spatial_methods()->expression_list()->stop->getStopIndex()) + { + size_t pos = entry.first; + size_t offset = ctx->function_call()->stop->getStopIndex() - ctx->function_call()->start->getStartIndex() + 2; + pos -= offset; + local_id_positions.emplace(std::make_pair(pos, entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2) + "," + expr.substr(0, func_call_len+offset1+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + } + } + } + } + + void exitBracket_expr(TSqlParser::Bracket_exprContext *ctx) override + { + if(!ctx->DOT().empty()) + { + std::vector method_calls = ctx->method_call(); + for (size_t i=0; i LR_BRACKET expression RR_BRACKET.method_call */ + if(method->spatial_methods()) + { + std::string proc_name = stripQuoteFromId(method->spatial_methods()->method); + if((strcmp(proc_name.c_str(), "STAsText") == 0 || strcmp(proc_name.c_str(), "STAsBinary") == 0) && !method->spatial_methods()->expression_list() ) + { + std::string ctx_str = ::getFullText(ctx); + int expr_len = (int)ctx->expression()->stop->getStopIndex() - ctx->expression()->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->expression()->stop->getStopIndex() + 1) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->expression()->start->getStartIndex() && entry.first <= ctx->expression()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + proc_name.size(), entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2) + expr.substr((int)ctx->expression()->start->getStartIndex() - ctx->start->getStartIndex(), expr_len+offset1+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + if(strcmp(proc_name.c_str(), "STDistance") == 0 && method->spatial_methods()->expression_list() ) + { + std::string ctx_str = ::getFullText(ctx); + int expr_len = (int)ctx->expression()->stop->getStopIndex() - ctx->expression()->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->expression()->stop->getStopIndex()+1) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->expression()->start->getStartIndex() && entry.first <= ctx->expression()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + method->spatial_methods()->expression_list()->stop->getStopIndex() - method->spatial_methods()->method->start->getStartIndex() + 1, entry.second)); + local_id_positions.erase(entry.first); + } + else if(entry.first >= method->spatial_methods()->expression_list()->start->getStartIndex() && entry.first <= method->spatial_methods()->expression_list()->stop->getStopIndex()) + { + size_t pos = entry.first; + size_t offset = ctx->expression()->stop->getStopIndex() - ctx->expression()->start->getStartIndex() + 4; + pos -= offset; + local_id_positions.emplace(std::make_pair(pos, entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2) + "," + expr.substr((int)ctx->expression()->start->getStartIndex() - ctx->start->getStartIndex(), expr_len+offset1+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + } + } + } + } + + void exitSubquery_expr(TSqlParser::Subquery_exprContext *ctx) override + { + if(!ctx->DOT().empty()) + { + std::vector method_calls = ctx->method_call(); + for (size_t i=0; i subquery.method_call */ + if(method->spatial_methods()) + { + std::string proc_name = stripQuoteFromId(method->spatial_methods()->method); + if((strcmp(proc_name.c_str(), "STAsText") == 0 || strcmp(proc_name.c_str(), "STAsBinary") == 0) && !method->spatial_methods()->expression_list() ) + { + std::string ctx_str = ::getFullText(ctx); + int subquery_len = (int)ctx->subquery()->stop->getStopIndex() - ctx->subquery()->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->subquery()->stop->getStopIndex() + 1) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->subquery()->start->getStartIndex() && entry.first <= ctx->subquery()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + proc_name.size() + 1, entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2) + expr.substr(0, subquery_len+offset1+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + if(strcmp(proc_name.c_str(), "STDistance") == 0 && method->spatial_methods()->expression_list() ) + { + std::string ctx_str = ::getFullText(ctx); + int subquery_len = (int)ctx->subquery()->stop->getStopIndex() - ctx->subquery()->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->subquery()->stop->getStopIndex()+1) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->subquery()->start->getStartIndex() && entry.first <= ctx->subquery()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + method->spatial_methods()->expression_list()->stop->getStopIndex() - method->spatial_methods()->method->start->getStartIndex() + 2, entry.second)); + local_id_positions.erase(entry.first); + } + else if(entry.first >= method->spatial_methods()->expression_list()->start->getStartIndex() && entry.first <= method->spatial_methods()->expression_list()->stop->getStopIndex()) + { + size_t pos = entry.first; + size_t offset = ctx->subquery()->stop->getStopIndex() - ctx->subquery()->start->getStartIndex() + 2; + pos -= offset; + local_id_positions.emplace(std::make_pair(pos, entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2) + "," + expr.substr(0, subquery_len+offset1+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + } + } + } + } + void exitFull_column_name(TSqlParser::Full_column_nameContext *ctx) override { GetCtxFunc getSchema = [](TSqlParser::Full_column_nameContext *o) { return o->schema; }; GetCtxFunc getTablename = [](TSqlParser::Full_column_nameContext *o) { return o->tablename; }; + + /* This if clause rewrites the query in case of Geospatial function Call */ + std::string func_name = stripQuoteFromId(ctx->column_name); + if ((strcmp(func_name.c_str(), "STX") == 0 || strcmp(func_name.c_str(), "STY") == 0 || strcmp(func_name.c_str(), "LAT") == 0 || strcmp(func_name.c_str(), "LONG") == 0 || + strcmp(func_name.c_str(), "[STX]") == 0 || strcmp(func_name.c_str(), "[STY]") == 0 || strcmp(func_name.c_str(), "[LAT]") == 0 || strcmp(func_name.c_str(), "[LONG]") == 0) && ctx->tablename) + { + /* Throwing error similar to TSQL as we do not allow 4-Part name for geospatial function call */ + if(ctx->server) throw PGErrorWrapperException(ERROR, ERRCODE_SYNTAX_ERROR, format_errmsg("The multi-part identifier \"%s\" could not be bound.", ::getFullText(ctx).c_str()), getLineAndPos(ctx)); + /* + * Rewriting the query as: table.col.STX -> (table.col).STX + */ + std::string rewritten_func_name = "("; + if(ctx->schema) rewritten_func_name += stripQuoteFromId(ctx->schema) + "."; + rewritten_func_name += stripQuoteFromId(ctx->tablename) + ")." + func_name; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(::getFullText(ctx), rewritten_func_name.c_str()))); + } std::string rewritten_name = rewrite_column_name_with_omitted_schema_name(ctx, getSchema, getTablename); std::string rewritten_schema_name = rewrite_information_schema_to_information_schema_tsql(ctx, getSchema); if (!rewritten_name.empty()) @@ -1045,26 +1429,6 @@ class tsqlCommonMutator : public TSqlParserBaseListener { rewritten_query_fragment.emplace(std::make_pair(ctx->schema->start->getStartIndex(), std::make_pair(::getFullText(ctx->schema), rewritten_schema_name))); } - - #ifdef ENABLE_SPATIAL_TYPES - if(!ctx->id().empty() && ctx->id()[0]->id().size() == 2) - { - TSqlParser::IdContext *idctx = ctx->id()[0]; - if(idctx->id()[0] && idctx->colon_colon() && idctx->id()[1]) - { - std::string idText = ::getFullText(idctx->id()[0]); - transform(idText.begin(), idText.end(), idText.begin(), ::tolower); - size_t start = idText.find_first_not_of(" \n\r\t\f\v"); - idText = (start == std::string::npos) ? "" : idText.substr(start); - size_t end = idText.find_last_not_of(" \n\r\t\f\v"); - idText = (end == std::string::npos) ? "" : idText.substr(0, end + 1); - if(idText == "geography" || idText == "geometry"){ - rewritten_query_fragment.emplace(std::make_pair(idctx->start->getStartIndex(), std::make_pair(::getFullText(idctx->id()[0]), idText))); - rewritten_query_fragment.emplace(std::make_pair(idctx->colon_colon()->start->getStartIndex(), std::make_pair(::getFullText(idctx->colon_colon()), "__"))); - } - } - } - #endif // don't need to call does_object_name_need_delimiter() because problematic keywords are already allowed as function name } @@ -2260,6 +2624,403 @@ class tsqlBuilder : public tsqlCommonMutator } } + void exitFull_column_name(TSqlParser::Full_column_nameContext *ctx) override + { + /* This if clause rewrites the query in case of Geospatial function Call */ + std::string func_name = stripQuoteFromId(ctx->column_name); + if ((strcmp(func_name.c_str(), "STX") == 0 || strcmp(func_name.c_str(), "STY") == 0 || strcmp(func_name.c_str(), "LAT") == 0 || strcmp(func_name.c_str(), "LONG") == 0 || + strcmp(func_name.c_str(), "[STX]") == 0 || strcmp(func_name.c_str(), "[STY]") == 0 || strcmp(func_name.c_str(), "[LAT]") == 0 || strcmp(func_name.c_str(), "[LONG]") == 0) && ctx->tablename) + { + /* Throwing error similar to TSQL as we do not allow 4-Part name for geospatial function call */ + if(ctx->server) throw PGErrorWrapperException(ERROR, ERRCODE_SYNTAX_ERROR, format_errmsg("The multi-part identifier \"%s\" could not be bound.", ::getFullText(ctx).c_str()), getLineAndPos(ctx)); + /* + * rewriting the query as: table.col.STX -> (table.col).STX + */ + std::string rewritten_func_name = "("; + if(ctx->schema) rewritten_func_name += stripQuoteFromId(ctx->schema) + "."; + rewritten_func_name += stripQuoteFromId(ctx->tablename) + ")." + func_name; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(::getFullText(ctx), rewritten_func_name.c_str()))); + } + } + + void exitFunc_call_expr(TSqlParser::Func_call_exprContext *ctx) override + { + if(ctx != NULL && ctx->function_call() != NULL && !ctx->DOT().empty()) + { + std::vector method_calls = ctx->method_call(); + for (size_t i=0; i function_call.method_call */ + if(method->spatial_methods()) + { + std::string proc_name = stripQuoteFromId(method->spatial_methods()->method); + if((strcmp(proc_name.c_str(), "STX") == 0 || strcmp(proc_name.c_str(), "STY") == 0 || strcmp(proc_name.c_str(), "LAT") == 0 || strcmp(proc_name.c_str(), "LONG") == 0 || + strcmp(proc_name.c_str(), "[STX]") == 0 || strcmp(proc_name.c_str(), "[STY]") == 0 || strcmp(proc_name.c_str(), "[LAT]") == 0 || strcmp(proc_name.c_str(), "[LONG]") == 0) && !method->spatial_methods()->LR_BRACKET() ) + { + std::string ctx_str = ::getFullText(ctx); + int func_call_len = (int)ctx->function_call()->stop->getStopIndex() - ctx->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->function_call()->stop->getStopIndex()) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->function_call()->start->getStartIndex() && entry.first <= ctx->function_call()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + 1, entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = "(" + expr.substr(0, func_call_len+offset1+1) + ")." + expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2 + 1); + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + if((strcmp(proc_name.c_str(), "STAsText") == 0 || strcmp(proc_name.c_str(), "STAsBinary") == 0) && !method->spatial_methods()->expression_list() ) + { + std::string ctx_str = ::getFullText(ctx); + int func_call_len = (int)ctx->function_call()->stop->getStopIndex() - ctx->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->function_call()->stop->getStopIndex()) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->function_call()->start->getStartIndex() && entry.first <= ctx->function_call()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + proc_name.size() + 1, entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2) + expr.substr(0, func_call_len+offset1+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + if(strcmp(proc_name.c_str(), "STDistance") == 0 && method->spatial_methods()->expression_list() ) + { + std::string ctx_str = ::getFullText(ctx); + int func_call_len = (int)ctx->function_call()->stop->getStopIndex() - ctx->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->function_call()->stop->getStopIndex()) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->function_call()->start->getStartIndex() && entry.first <= ctx->function_call()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + method->spatial_methods()->expression_list()->stop->getStopIndex() - method->spatial_methods()->method->start->getStartIndex() + 2, entry.second)); + local_id_positions.erase(entry.first); + } + else if(entry.first >= method->spatial_methods()->expression_list()->start->getStartIndex() && entry.first <= method->spatial_methods()->expression_list()->stop->getStopIndex()) + { + size_t pos = entry.first; + size_t offset = ctx->function_call()->stop->getStopIndex() - ctx->function_call()->start->getStartIndex() + 2; + pos -= offset; + local_id_positions.emplace(std::make_pair(pos, entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2) + "," + expr.substr(0, func_call_len+offset1+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + } + } + } + } + + void exitLocal_id_expr(TSqlParser::Local_id_exprContext *ctx) override + { + if(ctx != NULL && ctx->local_id() != NULL && !ctx->DOT().empty()) + { + std::vector method_calls = ctx->method_call(); + for (size_t i=0; i select @STX.STX.STAsText() + { + TSqlParser::Method_callContext *method = method_calls[i]; + /* rewriting the query in case of Geospatial function Call -> local_id.method_call */ + if(method->spatial_methods()) + { + std::string proc_name = stripQuoteFromId(method->spatial_methods()->method); + if((strcmp(proc_name.c_str(), "STX") == 0 || strcmp(proc_name.c_str(), "STY") == 0 || strcmp(proc_name.c_str(), "LAT") == 0 || strcmp(proc_name.c_str(), "LONG") == 0 || + strcmp(proc_name.c_str(), "[STX]") == 0 || strcmp(proc_name.c_str(), "[STY]") == 0 || strcmp(proc_name.c_str(), "[LAT]") == 0 || strcmp(proc_name.c_str(), "[LONG]") == 0) && !method->spatial_methods()->LR_BRACKET() ) + { + std::string expr = ::getFullText(ctx); + int local_id_len = (int)ctx->local_id()->stop->getStopIndex() - ctx->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + local_id_positions.erase(ctx->local_id()->start->getStartIndex()); + local_id_positions.emplace(std::make_pair(ctx->local_id()->start->getStartIndex() + 1, ::getFullText(ctx->local_id()))); + std::string rewritten_exp = "(" + expr.substr(0, local_id_len+1) + ")." + expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex(),method_len+1); + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(expr.c_str(), rewritten_exp.c_str()))); + } + else if((strcmp(proc_name.c_str(), "STAsText") == 0 || strcmp(proc_name.c_str(), "STAsBinary") == 0) && !method->spatial_methods()->expression_list() ) + { + std::string expr = ::getFullText(ctx); + int local_id_len = (int)ctx->local_id()->stop->getStopIndex() - ctx->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + local_id_positions.erase(ctx->local_id()->start->getStartIndex()); + local_id_positions.emplace(std::make_pair(ctx->local_id()->start->getStartIndex() + proc_name.size() + 1, ::getFullText(ctx->local_id()))); + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex(),method_len) + expr.substr(0, local_id_len+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(expr.c_str(), rewritten_exp.c_str()))); + } + else if(strcmp(proc_name.c_str(), "STDistance") == 0 && method->spatial_methods()->expression_list() ) + { + std::string expr = ::getFullText(ctx); + int local_id_len = (int)ctx->local_id()->stop->getStopIndex() - ctx->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + local_id_positions.erase(ctx->local_id()->start->getStartIndex()); + local_id_positions.emplace(std::make_pair(ctx->local_id()->start->getStartIndex() + method->spatial_methods()->expression_list()->stop->getStopIndex() - method->spatial_methods()->method->start->getStartIndex() + 2, ::getFullText(ctx->local_id()))); + + for (auto &entry : local_id_positions) + { + if(entry.first >= method->spatial_methods()->expression_list()->start->getStartIndex() && entry.first <= method->spatial_methods()->expression_list()->stop->getStopIndex()) + { + size_t pos = entry.first; + size_t offset = ctx->local_id()->stop->getStopIndex() - ctx->local_id()->start->getStartIndex() + 2; + pos -= offset; + local_id_positions.emplace(std::make_pair(pos, entry.second)); + local_id_positions.erase(entry.first); + } + } + + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex(),method_len) + "," + expr.substr(0, local_id_len+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(expr.c_str(), rewritten_exp.c_str()))); + } + } + } + } + } + + void exitBracket_expr(TSqlParser::Bracket_exprContext *ctx) override + { + if(!ctx->DOT().empty()) + { + std::vector method_calls = ctx->method_call(); + for (size_t i=0; i LR_BRACKET expression RR_BRACKET.method_call */ + if(method->spatial_methods()) + { + std::string proc_name = stripQuoteFromId(method->spatial_methods()->method); + if((strcmp(proc_name.c_str(), "STAsText") == 0 || strcmp(proc_name.c_str(), "STAsBinary") == 0) && !method->spatial_methods()->expression_list() ) + { + std::string ctx_str = ::getFullText(ctx); + int expr_len = (int)ctx->expression()->stop->getStopIndex() - ctx->expression()->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->expression()->stop->getStopIndex() + 1) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->expression()->start->getStartIndex() && entry.first <= ctx->expression()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + proc_name.size(), entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2) + expr.substr((int)ctx->expression()->start->getStartIndex() - ctx->start->getStartIndex(), expr_len+offset1+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + if(strcmp(proc_name.c_str(), "STDistance") == 0 && method->spatial_methods()->expression_list() ) + { + std::string ctx_str = ::getFullText(ctx); + int expr_len = (int)ctx->expression()->stop->getStopIndex() - ctx->expression()->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->expression()->stop->getStopIndex()+1) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->expression()->start->getStartIndex() && entry.first <= ctx->expression()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + method->spatial_methods()->expression_list()->stop->getStopIndex() - method->spatial_methods()->method->start->getStartIndex() + 1, entry.second)); + local_id_positions.erase(entry.first); + } + else if(entry.first >= method->spatial_methods()->expression_list()->start->getStartIndex() && entry.first <= method->spatial_methods()->expression_list()->stop->getStopIndex()) + { + size_t pos = entry.first; + size_t offset = ctx->expression()->stop->getStopIndex() - ctx->expression()->start->getStartIndex() + 4; + pos -= offset; + local_id_positions.emplace(std::make_pair(pos, entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2) + "," + expr.substr((int)ctx->expression()->start->getStartIndex() - ctx->start->getStartIndex(), expr_len+offset1+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + } + } + } + } + + void exitSubquery_expr(TSqlParser::Subquery_exprContext *ctx) override + { + if(!ctx->DOT().empty()) + { + std::vector method_calls = ctx->method_call(); + for (size_t i=0; i subquery.method_call */ + if(method->spatial_methods()) + { + std::string proc_name = stripQuoteFromId(method->spatial_methods()->method); + if((strcmp(proc_name.c_str(), "STAsText") == 0 || strcmp(proc_name.c_str(), "STAsBinary") == 0) && !method->spatial_methods()->expression_list() ) + { + std::string ctx_str = ::getFullText(ctx); + int subquery_len = (int)ctx->subquery()->stop->getStopIndex() - ctx->subquery()->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->subquery()->stop->getStopIndex() + 1) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->subquery()->start->getStartIndex() && entry.first <= ctx->subquery()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + proc_name.size() + 1, entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2) + expr.substr(0, subquery_len+offset1+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + if(strcmp(proc_name.c_str(), "STDistance") == 0 && method->spatial_methods()->expression_list() ) + { + std::string ctx_str = ::getFullText(ctx); + int subquery_len = (int)ctx->subquery()->stop->getStopIndex() - ctx->subquery()->start->getStartIndex(); + int method_len = (int)method->stop->getStopIndex() - method->start->getStartIndex(); + std::string expr = ""; + int index = 0; + int offset1 = 0; + int offset2 = 0; + /* writting the previously rewritten Geospatial context */ + for (auto &entry : rewritten_query_fragment) + { + if(entry.first >= ctx->start->getStartIndex() && entry.first <= ctx->stop->getStopIndex()) + { + expr+= ctx_str.substr(index, (int)entry.first - ctx->start->getStartIndex() - index) + entry.second.second; + index = (int)entry.first - ctx->start->getStartIndex() + entry.second.first.size(); + rewritten_query_fragment.erase(entry.first); + if(entry.first <= ctx->subquery()->stop->getStopIndex()+1) offset1+= (int)entry.second.second.size() - entry.second.first.size(); + else offset2+= (int)entry.second.second.size() - entry.second.first.size(); + } + } + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->subquery()->start->getStartIndex() && entry.first <= ctx->subquery()->stop->getStopIndex()) + { + local_id_positions.emplace(std::make_pair(entry.first + method->spatial_methods()->expression_list()->stop->getStopIndex() - method->spatial_methods()->method->start->getStartIndex() + 2, entry.second)); + local_id_positions.erase(entry.first); + } + else if(entry.first >= method->spatial_methods()->expression_list()->start->getStartIndex() && entry.first <= method->spatial_methods()->expression_list()->stop->getStopIndex()) + { + size_t pos = entry.first; + size_t offset = ctx->subquery()->stop->getStopIndex() - ctx->subquery()->start->getStartIndex() + 2; + pos -= offset; + local_id_positions.emplace(std::make_pair(pos, entry.second)); + local_id_positions.erase(entry.first); + } + } + expr+=ctx_str.substr(index); + std::string rewritten_exp = expr.substr((int)method->start->getStartIndex() - ctx->start->getStartIndex() + offset1, method_len + offset2) + "," + expr.substr(0, subquery_len+offset1+1) + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->start->getStartIndex(), std::make_pair(ctx_str.c_str(), rewritten_exp.c_str()))); + } + } + } + } + } + ////////////////////////////////////////////////////////////////////////////// // function/procedure call analysis ////////////////////////////////////////////////////////////////////////////// @@ -2382,6 +3143,52 @@ class tsqlBuilder : public tsqlCommonMutator throw PGErrorWrapperException(ERROR, ERRCODE_FEATURE_NOT_SUPPORTED, format_errmsg("function %s does not exist", proc_name.c_str()), getLineAndPos(ctx)); } + + /* This if-elseIf clause rewrites the query in case of Geospatial function Call */ + if (strcmp(proc_name.c_str(), "STDistance") == 0 && ctx->func_proc_name_server_database_schema()->schema && ctx->function_arg_list()) + { + std::string func_ctx = ::getFullText(ctx); + std::string arg_ctx = ::getFullText(ctx->function_arg_list()); + int index = (int) ctx->func_proc_name_server_database_schema()->stop->getStopIndex() - ctx->func_proc_name_server_database_schema()->start->getStartIndex() + 1; + int length = (int) ctx->function_arg_list()->start->getStartIndex() - ctx->func_proc_name_server_database_schema()->stop->getStopIndex() - 1; + + /* shifting the local id positions to new positions after rewriting the query since they will be quoted later */ + for (auto &entry : local_id_positions) + { + if(entry.first >= ctx->function_arg_list()->start->getStartIndex() && entry.first <= ctx->function_arg_list()->stop->getStopIndex()) + { + size_t pos = entry.first; + size_t offset = ctx->func_proc_name_server_database_schema()->procedure->start->getStartIndex() - ctx->func_proc_name_server_database_schema()->start->getStartIndex(); + pos -= offset; + local_id_positions.emplace(std::make_pair(pos, entry.second)); + local_id_positions.erase(entry.first); + } + } + + /* + * rewriting the query as: table.col.STDistance(arg) -> STDistance(arg, table.col) + */ + arg_ctx += ","; + if (ctx->func_proc_name_server_database_schema()->database) arg_ctx += stripQuoteFromId(ctx->func_proc_name_server_database_schema()->database) + "."; + arg_ctx += stripQuoteFromId(ctx->func_proc_name_server_database_schema()->schema); + std::string rewritten_func = proc_name + func_ctx.substr(index, length) + arg_ctx + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->func_proc_name_server_database_schema()->start->getStartIndex(), std::make_pair(::getFullText(ctx), rewritten_func.c_str()))); + } + else if ((strcmp(proc_name.c_str(), "STAsText") == 0 || strcmp(proc_name.c_str(), "STAsBinary") == 0) && ctx->func_proc_name_server_database_schema()->schema && !ctx->function_arg_list()) + { + std::string func_ctx = ::getFullText(ctx); + /* Space is provided to distinguish it from ALL | DISTINCT keywords */ + std::string arg_ctx = " "; + int index = (int) ctx->func_proc_name_server_database_schema()->stop->getStopIndex() - ctx->func_proc_name_server_database_schema()->start->getStartIndex() + 1; + int length = (int) ctx->stop->getStopIndex() - ctx->func_proc_name_server_database_schema()->stop->getStopIndex() - 1; + /* + * rewriting the query as: table.col.STAsText() -> STAsText(table.col) + */ + if (ctx->func_proc_name_server_database_schema()->database) arg_ctx += stripQuoteFromId(ctx->func_proc_name_server_database_schema()->database) + "."; + arg_ctx += stripQuoteFromId(ctx->func_proc_name_server_database_schema()->schema); + std::string rewritten_func = proc_name + func_ctx.substr(index, length) + arg_ctx + ")"; + rewritten_query_fragment.emplace(std::make_pair(ctx->func_proc_name_server_database_schema()->start->getStartIndex(), std::make_pair(::getFullText(ctx), rewritten_func.c_str()))); + } } } } diff --git a/test/JDBC/expected/TestSpatialPoint-vu-cleanup.out b/test/JDBC/expected/TestSpatialPoint-vu-cleanup.out index fbf811a041..97bad2cc34 100644 --- a/test/JDBC/expected/TestSpatialPoint-vu-cleanup.out +++ b/test/JDBC/expected/TestSpatialPoint-vu-cleanup.out @@ -64,4 +64,34 @@ DROP TABLE IF EXISTS TypeToGeog DROP TABLE IF EXISTS SPATIALPOINT_dt +DROP PROCEDURE IF EXISTS GetPointsByXCoordinate + +DROP PROCEDURE IF EXISTS GetPointsByXCoordinate1 + +DROP FUNCTION IF EXISTS dbo.GetXCoordinate + +DROP FUNCTION IF EXISTS GetGeometry + +DROP TRIGGER IF EXISTS trg_LogXCoordinateChange + +DROP TABLE IF EXISTS XCoordinateChangeLog + +DROP TRIGGER IF EXISTS trg_LogDistanceChange + +DROP TABLE IF EXISTS DistanceChangeLog + +DROP TABLE IF EXISTS YourTable + +DROP TABLE IF EXISTS YourTable1 + +DROP TABLE IF EXISTS TableA + +DROP TABLE IF EXISTS TableB + +DROP PROCEDURE IF EXISTS GetPointsWithinDistance + +DROP FUNCTION IF EXISTS dbo.CalculateDistance + +DROP TABLE IF EXISTS YourTable2 + Drop Table IF EXISTS babelfish_migration_mode_table diff --git a/test/JDBC/expected/TestSpatialPoint-vu-prepare.out b/test/JDBC/expected/TestSpatialPoint-vu-prepare.out index 645e3e57b6..ae53ecd598 100644 --- a/test/JDBC/expected/TestSpatialPoint-vu-prepare.out +++ b/test/JDBC/expected/TestSpatialPoint-vu-prepare.out @@ -76,6 +76,51 @@ INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::Point(47.65100, -2 ~~ROW COUNT: 1~~ +CREATE TABLE YourTable ( ID INT PRIMARY KEY, PointColumn geometry ); + +INSERT INTO YourTable (ID, PointColumn) VALUES (1, geometry::Point(3.0, 4.0, 4326)), (2, geometry::Point(5.0, 6.0, 4326)); +~~ROW COUNT: 2~~ + + +CREATE FUNCTION dbo.GetXCoordinate(@point geometry) RETURNS float AS BEGIN RETURN @point.STX; END; + +CREATE TABLE TableA (ID INT PRIMARY KEY, PointA geometry); +CREATE TABLE TableB (ID INT PRIMARY KEY, PointB geometry); +INSERT INTO TableA (ID, PointA) VALUES (1, geometry::Point(1.0, 2.0, 4326)); +~~ROW COUNT: 1~~ + +INSERT INTO TableB (ID, PointB) VALUES (1, geometry::Point(3.0, 4.0, 4326)); +~~ROW COUNT: 1~~ + + +CREATE PROCEDURE GetPointsByXCoordinate @XCoordinate FLOAT AS BEGIN SELECT * FROM YourTable WHERE PointColumn.STX = @XCoordinate; END; + +CREATE PROCEDURE GetPointsByXCoordinate1 @XCoordinate FLOAT AS BEGIN DECLARE @Sql NVARCHAR(MAX); SET @Sql = N'SELECT ID, PointColumn.STX AS XCoordinate FROM YourTable WHERE PointColumn.STX = @ParamXCoordinate'; EXEC sp_executesql @Sql,N'@ParamXCoordinate FLOAT',@XCoordinate; END; + +CREATE TABLE YourTable1 ( ID INT PRIMARY KEY, STX geometry ); +INSERT INTO YourTable1 (ID, STX) VALUES (1, geometry::Point(3.0, 4.0, 4326)), (2, geometry::Point(5.0, 6.0, 4326)); +~~ROW COUNT: 2~~ + + +CREATE FUNCTION GetGeometry() RETURNS geometry AS BEGIN RETURN geometry::Point(1.0, 2.0, 4326); END; + +CREATE TABLE XCoordinateChangeLog (PointID INT,OldXCoordinate FLOAT,NewXCoordinate FLOAT,ChangeDate DATETIME); + +CREATE TRIGGER trg_LogXCoordinateChange ON YourTable AFTER UPDATE AS BEGIN INSERT INTO XCoordinateChangeLog (PointID, OldXCoordinate, NewXCoordinate, ChangeDate) SELECT i.ID, d.PointColumn.STX, i.PointColumn.STX, GETDATE() FROM inserted i JOIN deleted d ON i.ID = d.ID WHERE i.PointColumn.STX <> d.PointColumn.STX; END; + +CREATE TABLE YourTable2 ( ID INT PRIMARY KEY, PointColumn1 geometry, PointColumn2 geometry ); +INSERT INTO YourTable2 (ID, PointColumn1, PointColumn2) VALUES (1, geometry::Point(3.0, 4.0, 4326), geometry::Point(4.0, 5.0, 4326)); +~~ROW COUNT: 1~~ + + +CREATE FUNCTION dbo.CalculateDistance(@point1 geometry,@point2 geometry) RETURNS float AS BEGIN RETURN @point1.STDistance(@point2); END; + +CREATE PROCEDURE GetPointsWithinDistance @referencePoint geometry, @maxDistance float AS BEGIN SELECT * FROM YourTable WHERE PointColumn.STDistance(@referencePoint) <= @maxDistance; END; + +CREATE TABLE DistanceChangeLog (PointID INT,OldDistance FLOAT,NewDistance FLOAT,ChangeDate DATETIME); + +CREATE TRIGGER trg_LogDistanceChange ON YourTable AFTER UPDATE AS BEGIN DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); INSERT INTO DistanceChangeLog (PointID, OldDistance, NewDistance, ChangeDate) SELECT i.ID, d.PointColumn.STDistance(@referencePoint), i.PointColumn.STDistance(@referencePoint), GETDATE() FROM inserted i JOIN deleted d ON i.ID = d.ID WHERE i.PointColumn.STDistance(@referencePoint) <> d.PointColumn.STDistance(@referencePoint); END; + #Tests for Geometry type Prepared Statements prepst#!#INSERT INTO SPATIALPOINTGEOM_dt(location) values(?) #!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):4326 ~~ROW COUNT: 1~~ @@ -346,7 +391,7 @@ CREATE VIEW TextFromGeog AS SELECT STAsText(location) AS TextRepresentation FROM CREATE VIEW BinaryFromGeog AS SELECT STAsBinary(location) AS BinaryRepresentation FROM SPATIALPOINTGEOG_dt; -CREATE VIEW CoordsFromGeog AS SELECT long(location), lat(location) AS Coordinates FROM SPATIALPOINTGEOG_dt; +CREATE VIEW CoordsFromGeog AS SELECT LONG(location), LAT(location) AS Coordinates FROM SPATIALPOINTGEOG_dt; CREATE VIEW GeogView AS SELECT location.LONG, location.LAT AS Coordinates FROM SPATIALPOINTGEOG_dt; diff --git a/test/JDBC/expected/TestSpatialPoint-vu-verify.out b/test/JDBC/expected/TestSpatialPoint-vu-verify.out index e232110f92..fbc3cf15dc 100644 --- a/test/JDBC/expected/TestSpatialPoint-vu-verify.out +++ b/test/JDBC/expected/TestSpatialPoint-vu-verify.out @@ -30,12 +30,32 @@ POINT(22.349 -47.651) ~~END~~ +DECLARE @point geometry; +SET @point = geometry::Point(1.0, 2.0, 4326); +SELECT @point.STX AS XCoordinate; +GO +~~START~~ +float +1.0 +~~END~~ + + +DECLARE @point1 geometry = geometry::Point(1.0, 2.0, 4326); +DECLARE @point2 geometry = geometry::Point(3.0, 4.0, 4326); +SELECT @point1.STDistance(@point2) AS Distance; +GO +~~START~~ +float +2.8284271247461903 +~~END~~ + + DECLARE @point geometry; SET @point = geometry::STGeomFromText('POINT(-122.34900 47.65100)', 4326); -SELECT stx(@point); -SELECT sty(@point); -SELECT @point.stx; -SELECT @point.sty; +SELECT STX(@point); +SELECT STY(@point); +SELECT @point.STX; +SELECT @point.STY; Go ~~START~~ float @@ -60,10 +80,10 @@ float DECLARE @point geometry; SET @point = geometry::POINT(22.34900, -47.65100, 4326); -SELECT stx(@point); -SELECT sty(@point); -SELECT @point.stx; -SELECT @point.sty; +SELECT STX(@point); +SELECT STY(@point); +SELECT @point.STX; +SELECT @point.STY; Go ~~START~~ float @@ -110,26 +130,24 @@ go ~~ROW COUNT: 1~~ --- Currently it is not supported --- TODO: Need to support it and make it similar to TSQL DECLARE @STX geometry; SET @STX = geometry::STGeomFromText('POINT(-122.34900 47.65100)', 4326); select geometry::Point(@STX.STX, @STX.STY, 4326).STX, geometry::Point(@STX.STX, @STX.STY, 4326).STY; go -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: syntax error at or near ".")~~ +~~START~~ +float#!#float +-122.349#!#47.651 +~~END~~ --- Currently it is not supported --- TODO: Need to support it and make it similar to TSQL DECLARE @STX geometry; SET @STX = geometry::STGeomFromText('POINT(-122.34900 47.65100)', 4326); select geometry::Point(@STX.STX, @STX.STY, 4326).STAsText(), geometry::Point(@STX.STX, @STX.STY, 4326).STAsBinary(), geometry::Point(@STX.STX, @STX.STY, 4326).STDistance(geometry::Point(@STX.STX, @STX.STY, 4326)); go -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: syntax error at or near ".")~~ +~~START~~ +text#!#varbinary#!#float +POINT(-122.349 47.651)#!#01010000007593180456965EC017D9CEF753D34740#!#0.0 +~~END~~ -- Null test for Geospatial functions @@ -196,7 +214,7 @@ SELECT location.LAT from SPATIALPOINTGEOM_dt; GO ~~ERROR (Code: 33557097)~~ -~~ERROR (Message: function sys.lat(geometry) does not exist)~~ +~~ERROR (Message: column notation .lat applied to type geometry, which is not a composite type)~~ SELECT * FROM GeomView; @@ -436,7 +454,7 @@ float 131.52562336670374 ~~ERROR (Code: 33557097)~~ -~~ERROR (Message: ST_Distance: Operation on mixed SRID geometries (Point, 0) != (Point, 4326))~~ +~~ERROR (Message: ST_Distance: Operation on mixed SRID geometries (Point, 4326) != (Point, 0))~~ SELECT [SPATIALPOINTGEOM_dt].[location].[STX] from [SPATIALPOINTGEOM_dt]; @@ -493,6 +511,786 @@ E6100000010C7593180456965EC017D9CEF753D34740 ~~END~~ +SELECT PointColumn.STX AS XCoordinate FROM YourTable; +GO +~~START~~ +float +3.0 +5.0 +~~END~~ + + +SELECT * FROM YourTable WHERE PointColumn.STX > 3.0; +GO +~~START~~ +int#!#geometry +2#!#E6100000010C00000000000014400000000000001840 +~~END~~ + + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT * FROM YourTable WHERE PointColumn.STX > @point.STX; +GO +~~START~~ +int#!#geometry +1#!#E6100000010C00000000000008400000000000001040 +2#!#E6100000010C00000000000014400000000000001840 +~~END~~ + + +SELECT ID, PointColumn.STX AS XCoordinate FROM YourTable; +GO +~~START~~ +int#!#float +1#!#3.0 +2#!#5.0 +~~END~~ + + +SELECT ID, dbo.GetXCoordinate(PointColumn) AS XCoordinate FROM YourTable; +GO +~~START~~ +int#!#float +1#!#3.0 +2#!#5.0 +~~END~~ + + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT dbo.GetXCoordinate(@point); +GO +~~START~~ +float +1.0 +~~END~~ + + +SELECT * FROM TableA JOIN TableB ON TableA.PointA.STX = TableB.PointB.STX; +GO +~~START~~ +int#!#geometry#!#int#!#geometry +~~END~~ + + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT * FROM TableA JOIN TableB ON TableA.PointA.STX > @point.STX; +GO +~~START~~ +int#!#geometry#!#int#!#geometry +~~END~~ + + +SELECT * FROM YourTable ORDER BY PointColumn.STX; +GO +~~START~~ +int#!#geometry +1#!#E6100000010C00000000000008400000000000001040 +2#!#E6100000010C00000000000014400000000000001840 +~~END~~ + + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT * FROM YourTable ORDER BY @point.STX; +GO +~~START~~ +int#!#geometry +1#!#E6100000010C00000000000008400000000000001040 +2#!#E6100000010C00000000000014400000000000001840 +~~END~~ + + +SELECT ID, PointColumn.STX AS XCoordinate, +CASE WHEN PointColumn.STX > 3.0 THEN 'High X' +ELSE 'Low X' +END AS XCoordinateCategory FROM YourTable; +GO +~~START~~ +int#!#float#!#text +1#!#3.0#!#Low X +2#!#5.0#!#High X +~~END~~ + + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT ID, PointColumn.STX AS XCoordinate, +CASE WHEN @point.STX > 3.0 THEN 'High X' +ELSE 'Low X' +END AS XCoordinateCategory FROM YourTable; +GO +~~START~~ +int#!#float#!#text +1#!#3.0#!#Low X +2#!#5.0#!#Low X +~~END~~ + + +WITH PointData AS ( SELECT ID, PointColumn.STX AS XCoordinate FROM YourTable ) +SELECT * FROM PointData WHERE XCoordinate > 3.0; +GO +~~START~~ +int#!#float +2#!#5.0 +~~END~~ + + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +WITH PointData AS ( SELECT ID, @point.STX AS XCoordinate FROM YourTable ) +SELECT * FROM PointData WHERE XCoordinate > 3.0; +GO +~~START~~ +int#!#float +~~END~~ + + +SELECT PointColumn.STX AS XCoordinate, COUNT(*) AS PointCount +FROM YourTable GROUP BY PointColumn.STX; +GO +~~START~~ +float#!#int +3.0#!#1 +5.0#!#1 +~~END~~ + + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT @point.STX AS XCoordinate, COUNT(*) AS PointCount +FROM YourTable GROUP BY PointColumn.STX; +GO +~~START~~ +float#!#int +1.0#!#1 +1.0#!#1 +~~END~~ + + +SELECT ID, PointColumn.STX AS XCoordinate, +PointColumn.STX - LAG(PointColumn.STX) OVER (ORDER BY ID) AS XCoordinateDifference +FROM YourTable; +GO +~~START~~ +int#!#float#!#float +1#!#3.0#!# +2#!#5.0#!#2.0 +~~END~~ + + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT ID, @point.STX AS XCoordinate, +@point.STX - LAG(@point.STX) OVER (ORDER BY ID) AS XCoordinateDifference +FROM YourTable; +GO +~~START~~ +int#!#float#!#float +1#!#1.0#!# +2#!#1.0#!#0.0 +~~END~~ + + +DECLARE @XCoordinate FLOAT = 3.0; +DECLARE @DynamicQuery NVARCHAR(MAX); +SET @DynamicQuery = N' SELECT * FROM YourTable WHERE PointColumn.STX > ' + CAST(@XCoordinate AS NVARCHAR(MAX)); +EXEC sp_executesql @DynamicQuery; +GO +~~START~~ +int#!#geometry +2#!#E6100000010C00000000000014400000000000001840 +~~END~~ + + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +DECLARE @DynamicQuery NVARCHAR(MAX); +SET @DynamicQuery = N' SELECT * FROM YourTable WHERE PointColumn.STX > ' + CAST(@point.STX AS NVARCHAR(MAX)); +EXEC sp_executesql @DynamicQuery; +GO +~~START~~ +int#!#geometry +1#!#E6100000010C00000000000008400000000000001040 +2#!#E6100000010C00000000000014400000000000001840 +~~END~~ + + +EXEC GetPointsByXCoordinate @XCoordinate = 4.0; +GO +~~START~~ +int#!#geometry +~~END~~ + + +EXEC GetPointsByXCoordinate1 @XCoordinate = 4.0; +GO +~~START~~ +int#!#float +~~END~~ + + +DECLARE @XCoordinate FLOAT = 3.0; +DECLARE @DynamicQuery NVARCHAR(MAX); +SET @DynamicQuery = N' SELECT * FROM YourTable WHERE PointColumn.STX > ' + CAST(@XCoordinate AS NVARCHAR(MAX)); +EXEC sp_executesql @DynamicQuery; +GO +~~START~~ +int#!#geometry +2#!#E6100000010C00000000000014400000000000001840 +~~END~~ + + +SELECT ID, PointColumn.STX AS XCoordinate, CASE WHEN PointColumn.STX < 0 +THEN 'Negative X' WHEN PointColumn.STX = 0 THEN 'Zero X' +ELSE 'Positive X' END AS XCoordinateCategory FROM YourTable; +GO +~~START~~ +int#!#float#!#text +1#!#3.0#!#Positive X +2#!#5.0#!#Positive X +~~END~~ + + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT ID, @point.STX AS XCoordinate, CASE WHEN @point.STX < 0 +THEN 'Negative X' WHEN @point.STX = 0 THEN 'Zero X' +ELSE 'Positive X' END AS XCoordinateCategory FROM YourTable; +GO +~~START~~ +int#!#float#!#text +1#!#1.0#!#Positive X +2#!#1.0#!#Positive X +~~END~~ + + +SELECT * FROM ( SELECT ID, +CASE WHEN PointColumn.STX BETWEEN 0 AND 5 THEN '0-5' +WHEN PointColumn.STX BETWEEN 5.1 AND 10 THEN '5.1-10' +ELSE '10.1+' +END AS XCoordRange +FROM YourTable +) AS Source +PIVOT ( COUNT(ID) FOR XCoordRange IN ([0-5], [5.1-10], [10.1+])) AS PivotTable; +GO +~~START~~ +int#!#int#!#int +2#!#0#!#0 +~~END~~ + + +SELECT ID, PointColumn.STX AS XCoordinate, +JSON_QUERY('{"XCoordinate":' + CAST(PointColumn.STX AS NVARCHAR(MAX)) + '}') AS XCoordinateJson +FROM YourTable; +GO +~~START~~ +int#!#float#!#nvarchar +1#!#3.0#!#{"XCoordinate": 3} +2#!#5.0#!#{"XCoordinate": 5} +~~END~~ + + +DECLARE @point geometry = geometry::Point(3.0, 2.0, 4326); +SELECT ID, @point.STX AS XCoordinate, +JSON_QUERY('{"XCoordinate":' + CAST(@point.STX AS NVARCHAR(MAX)) + '}') AS XCoordinateJson +FROM YourTable; +GO +~~START~~ +int#!#float#!#nvarchar +1#!#3.0#!#{"XCoordinate": 3} +2#!#3.0#!#{"XCoordinate": 3} +~~END~~ + + +SELECT [PointColumn].[STX] AS XCoordinate FROM [YourTable]; +GO +~~START~~ +float +3.0 +5.0 +~~END~~ + + +DECLARE @point geometry = geometry::Point(3.0, 2.0, 4326); +SELECT @point.[STX] AS XCoordinate +GO +~~START~~ +float +3.0 +~~END~~ + + +SELECT PointColumn.STX AS XCoordinate FROM YourTable; +GO +~~START~~ +float +3.0 +5.0 +~~END~~ + + +SELECT YourTable.PointColumn.STX AS XCoordinate FROM YourTable; +GO +~~START~~ +float +3.0 +5.0 +~~END~~ + + +SELECT dbo.YourTable.PointColumn.STX AS XCoordinate FROM YourTable; +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: The multi-part identifier "dbo.YourTable.PointColumn.STX" could not be bound.)~~ + + +SELECT YourTable1.STX.STX AS XCoordinate FROM YourTable1; +GO +~~START~~ +float +3.0 +5.0 +~~END~~ + + +DECLARE @result geometry; +SET @result = dbo.GetGeometry(); +DECLARE @xCoordinate float; +SET @xCoordinate = @result.STX; +SELECT @result AS ResultGeometry, @xCoordinate AS XCoordinate; +GO +~~START~~ +geometry#!#float +E6100000010C000000000000F03F0000000000000040#!#1.0 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +UPDATE YourTable SET PointColumn = @referencePoint +WHERE PointColumn.STX >= @referencePoint.STX; +GO +~~ROW COUNT: 2~~ + +~~ROW COUNT: 2~~ + +~~ROW COUNT: 2~~ + + +SELECT ID, PointColumn1.STDistance(PointColumn2) AS Distance FROM YourTable2; +GO +~~START~~ +int#!#float +1#!#1.4142135623730951 +~~END~~ + + +DECLARE @point1 geometry = geometry::Point(1.0, 2.0, 4326); +SELECT ID, PointColumn1.STDistance(@point1) AS Distance FROM YourTable2; +GO +~~START~~ +int#!#float +1#!#2.8284271247461903 +~~END~~ + + +DECLARE @point1 geometry = geometry::Point(1.0, 2.0, 4326); +SELECT ID, @point1.STDistance(PointColumn2) AS Distance FROM YourTable2; +GO +~~START~~ +int#!#float +1#!#4.242640687119285 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @maxDistance float = 5.0; +SELECT * FROM YourTable WHERE PointColumn.STDistance(@referencePoint) <= @maxDistance; +GO +~~START~~ +int#!#geometry +1#!#E6100000010C00000000000000000000000000000000 +2#!#E6100000010C00000000000000000000000000000000 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM YourTable WHERE @referencePoint.STDistance(PointColumn) <= @referencePoint.STX; +GO +~~START~~ +int#!#geometry +1#!#E6100000010C00000000000000000000000000000000 +2#!#E6100000010C00000000000000000000000000000000 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM YourTable WHERE PointColumn.STDistance(@referencePoint) <= @referencePoint.STX; +GO +~~START~~ +int#!#geometry +1#!#E6100000010C00000000000000000000000000000000 +2#!#E6100000010C00000000000000000000000000000000 +~~END~~ + + +SELECT ID, dbo.CalculateDistance(PointColumn1, PointColumn2) AS Distance FROM YourTable2; +GO +~~START~~ +int#!#float +1#!#1.4142135623730951 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, dbo.CalculateDistance(@referencePoint, PointColumn2) AS Distance FROM YourTable2; +GO +~~START~~ +int#!#float +1#!#6.4031242374328485 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, dbo.CalculateDistance(PointColumn1, @referencePoint) AS Distance FROM YourTable2; +GO +~~START~~ +int#!#float +1#!#5.0 +~~END~~ + + +SELECT * FROM TableA JOIN TableB ON PointA.STDistance(TableB.PointB) <= 5.0; +GO +~~START~~ +int#!#geometry#!#int#!#geometry +1#!#E6100000010C000000000000F03F0000000000000040#!#1#!#E6100000010C00000000000008400000000000001040 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM TableA JOIN TableB ON @referencePoint.STDistance(TableB.PointB) <= 5.0; +GO +~~START~~ +int#!#geometry#!#int#!#geometry +1#!#E6100000010C000000000000F03F0000000000000040#!#1#!#E6100000010C00000000000008400000000000001040 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM TableA JOIN TableB ON PointA.STDistance(@referencePoint) <= 5.0; +GO +~~START~~ +int#!#geometry#!#int#!#geometry +1#!#E6100000010C000000000000F03F0000000000000040#!#1#!#E6100000010C00000000000008400000000000001040 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM TableA JOIN TableB ON TableB.PointB.STDistance(@referencePoint) <= 5.0; +GO +~~START~~ +int#!#geometry#!#int#!#geometry +1#!#E6100000010C000000000000F03F0000000000000040#!#1#!#E6100000010C00000000000008400000000000001040 +~~END~~ + + +SELECT * FROM YourTable2 ORDER BY PointColumn1.STDistance(PointColumn2); +GO +~~START~~ +int#!#geometry#!#geometry +1#!#E6100000010C00000000000008400000000000001040#!#E6100000010C00000000000010400000000000001440 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM YourTable ORDER BY PointColumn.STDistance(@referencePoint); +GO +~~START~~ +int#!#geometry +1#!#E6100000010C00000000000000000000000000000000 +2#!#E6100000010C00000000000000000000000000000000 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM YourTable ORDER BY @referencePoint.STDistance(PointColumn); +GO +~~START~~ +int#!#geometry +1#!#E6100000010C00000000000000000000000000000000 +2#!#E6100000010C00000000000000000000000000000000 +~~END~~ + + +DECLARE @thresholdDistance float = 3.0; +SELECT ID, PointColumn1.STDistance(PointColumn2) AS DistanceBetweenPoints, +CASE WHEN PointColumn1.STDistance(PointColumn2) <= @thresholdDistance THEN 'Close' ELSE 'Far' +END AS Proximity +FROM YourTable2; +GO +~~START~~ +int#!#float#!#text +1#!#1.4142135623730951#!#Close +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, PointColumn1.STDistance(@referencePoint) AS DistanceBetweenPoints, +CASE WHEN @referencePoint.STDistance(PointColumn2) <= @referencePoint.STX THEN 'Close' ELSE 'Far' +END AS Proximity +FROM YourTable2; +GO +~~START~~ +int#!#float#!#text +1#!#5.0#!#Far +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +WITH DistanceCTE AS ( SELECT ID, PointColumn.STDistance(@referencePoint) AS Distance FROM YourTable) +SELECT * FROM DistanceCTE WHERE Distance <= 3.0; +GO +~~START~~ +int#!#float +1#!#0.0 +2#!#0.0 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +WITH DistanceCTE AS ( SELECT ID, @referencePoint.STDistance(PointColumn) AS Distance FROM YourTable) +SELECT * FROM DistanceCTE WHERE Distance <= 3.0; +GO +~~START~~ +int#!#float +1#!#0.0 +2#!#0.0 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @distanceInterval float = 5.0; +SELECT ROUND(PointColumn.STDistance(@referencePoint) / @distanceInterval, 0) * @distanceInterval AS DistanceGroup, +COUNT(*) AS PointCount +FROM YourTable +GROUP BY ROUND(PointColumn.STDistance(@referencePoint) / @distanceInterval, 0) * @distanceInterval; +GO +~~START~~ +float#!#int +0.0#!#2 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(1.0, 0.0, 4326); +SELECT ROUND(PointColumn.STDistance(@referencePoint) / @referencePoint.STX, 0) * @referencePoint.STX AS DistanceGroup, +COUNT(*) AS PointCount +FROM YourTable +GROUP BY ROUND(PointColumn.STDistance(@referencePoint) / @referencePoint.STX, 0) * @referencePoint.STX; +GO +~~START~~ +float#!#int +1.0#!#2 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, PointColumn1.STDistance(PointColumn2) AS Distance, +PointColumn1.STDistance(@referencePoint) - LAG(PointColumn1.STDistance(PointColumn2)) OVER (ORDER BY ID) AS DistanceDifference +FROM YourTable2; +GO +~~START~~ +int#!#float#!#float +1#!#1.4142135623730951#!# +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, PointColumn.STDistance(@referencePoint) AS Distance, +@referencePoint.STDistance(PointColumn) - LAG(@referencePoint.STX) OVER (ORDER BY ID) AS DistanceDifference +FROM YourTable; +GO +~~START~~ +int#!#float#!#float +1#!#0.0#!# +2#!#0.0#!#0.0 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @maxDistance float = 3.0; +EXEC GetPointsWithinDistance @referencePoint, @maxDistance; +GO +~~START~~ +int#!#geometry +1#!#E6100000010C00000000000000000000000000000000 +2#!#E6100000010C00000000000000000000000000000000 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @maxDistance float = 3.0; +DECLARE @DynamicQuery NVARCHAR(MAX); +SET @DynamicQuery = N' +SELECT * FROM YourTable +WHERE PointColumn.STDistance(geometry::STGeomFromText(' + QUOTENAME(@referencePoint.STAsText(), '''') + ', 4326)) <= ' + CAST(@maxDistance AS NVARCHAR(MAX)); +EXEC sp_executesql @DynamicQuery; +GO +~~START~~ +int#!#geometry +1#!#E6100000010C00000000000000000000000000000000 +2#!#E6100000010C00000000000000000000000000000000 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @DynamicQuery NVARCHAR(MAX); +SET @DynamicQuery = N' +SELECT * FROM YourTable +WHERE PointColumn.STDistance(geometry::STGeomFromText(' + QUOTENAME(@referencePoint.STAsText(), '''') + ', 4326)) <= ' + CAST(@referencePoint.STX AS NVARCHAR(MAX)); +EXEC sp_executesql @DynamicQuery; +GO +~~START~~ +int#!#geometry +1#!#E6100000010C00000000000000000000000000000000 +2#!#E6100000010C00000000000000000000000000000000 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @thresholdDistance float = 3.0; +SELECT ID, PointColumn.STDistance(@referencePoint) AS DistanceToReferencePoint, +CASE WHEN PointColumn.STDistance(@referencePoint) <= @thresholdDistance THEN 'Close' +ELSE 'Far' +END AS Proximity +FROM YourTable; +GO +~~START~~ +int#!#float#!#text +1#!#0.0#!#Close +2#!#0.0#!#Close +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, @referencePoint.STDistance(PointColumn) AS DistanceToReferencePoint, +CASE WHEN @referencePoint.STDistance(PointColumn) <= @referencePoint.STY THEN 'Close' +ELSE 'Far' +END AS Proximity +FROM YourTable; +GO +~~START~~ +int#!#float#!#text +1#!#0.0#!#Close +2#!#0.0#!#Close +~~END~~ + + +DECLARE @distanceRanges TABLE (MinDistance float, MaxDistance float); +INSERT INTO @distanceRanges VALUES (0, 5), (5, 10), (10, 15); +SELECT * FROM ( SELECT ID, +CASE WHEN PointColumn1.STDistance(PointColumn2) BETWEEN 0 AND 5 THEN '0-5' +WHEN PointColumn1.STDistance(PointColumn2) BETWEEN 5.1 AND 10 THEN '5.1-10' +WHEN PointColumn1.STDistance(PointColumn2) BETWEEN 10.1 AND 15 THEN '10.1-15' +ELSE '15.1+' +END AS DistanceRange +FROM YourTable2 +) AS Source +PIVOT ( COUNT(ID) FOR DistanceRange IN ([0-5], [5.1-10], [10.1-15], [15.1+])) AS PivotTable; +GO +~~ROW COUNT: 3~~ + +~~START~~ +int#!#int#!#int#!#int +1#!#0#!#0#!#0 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, PointColumn.STDistance(@referencePoint) AS Distance, +JSON_QUERY('{"Distance":' + CAST(PointColumn.STDistance(@referencePoint) AS NVARCHAR(MAX)) + '}') AS DistanceJson +FROM YourTable; +GO +~~START~~ +int#!#float#!#nvarchar +1#!#0.0#!#{"Distance": 0} +2#!#0.0#!#{"Distance": 0} +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, @referencePoint.STDistance(PointColumn) AS Distance, +JSON_QUERY('{"Distance":' + CAST(@referencePoint.STDistance(PointColumn) AS NVARCHAR(MAX)) + '}') AS DistanceJson +FROM YourTable; +GO +~~START~~ +int#!#float#!#nvarchar +1#!#0.0#!#{"Distance": 0} +2#!#0.0#!#{"Distance": 0} +~~END~~ + + +SELECT [PointColumn1].STDistance([PointColumn2]) AS distance FROM [YourTable2]; +GO +~~START~~ +float +1.4142135623730951 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @thresholdDistance float = 10.0; +DECLARE @sql NVARCHAR(MAX); +DECLARE @params NVARCHAR(MAX); +SET @sql = N' +SELECT ID, PointColumn.STDistance(@referencePoint) AS DistanceToReferencePoint, +CASE WHEN PointColumn.STDistance(@referencePoint) <= @thresholdDistance THEN ''Close'' +ELSE ''Far'' +END AS Proximity +FROM YourTable +WHERE PointColumn.STDistance(@referencePoint) <= @thresholdDistance;'; +SET @params = N'@referencePoint geometry, @thresholdDistance float'; +EXEC sp_executesql @sql, @params, @referencePoint, @thresholdDistance; +GO +~~START~~ +int#!#float#!#text +1#!#0.0#!#Close +2#!#0.0#!#Close +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT PointColumn.STDistance(@referencePoint) AS Distance FROM YourTable; +SELECT YourTable.PointColumn.STDistance(@referencePoint) AS Distance FROM YourTable; +GO +~~START~~ +float +0.0 +0.0 +~~END~~ + +~~START~~ +float +0.0 +0.0 +~~END~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT dbo.YourTable.PointColumn.STDistance(@referencePoint) AS Distance FROM YourTable; +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Remote procedure/function reference with 4-part object name is not currently supported in Babelfish)~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +UPDATE YourTable SET PointColumn = @referencePoint +WHERE PointColumn.STDistance(@referencePoint) <= 2.0; +GO +~~ROW COUNT: 2~~ + + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +UPDATE YourTable SET PointColumn = @referencePoint +WHERE @referencePoint.STDistance(PointColumn) <= 2.0; +GO +~~ROW COUNT: 2~~ + + -- Create Type Test Case currently Babelfish supports it but TSQL doesn't for spatial Types, Although it doesn't break anything -- TODO: Make it similar to T-SQL SELECT * FROM TypeTable; @@ -796,10 +1594,10 @@ POINT(-47.651 22.349) DECLARE @point geography; SET @point = geography::STPointFromText('POINT(-122.34900 47.65100)', 4326); -SELECT long(@point); -SELECT lat(@point); -SELECT @point.long; -SELECT @point.lat; +SELECT LONG(@point); +SELECT LAT(@point); +SELECT @point.LONG; +SELECT @point.LAT; Go ~~START~~ float @@ -824,10 +1622,10 @@ float DECLARE @point geography; SET @point = geography::POINT(22.34900, -47.65100, 4326); -SELECT long(@point); -SELECT lat(@point); -SELECT @point.long; -SELECT @point.lat; +SELECT LONG(@point); +SELECT LAT(@point); +SELECT @point.LONG; +SELECT @point.LAT; Go ~~START~~ float @@ -874,26 +1672,24 @@ go ~~ROW COUNT: 1~~ --- Currently it is not supported --- TODO: Need to support it and make it similar to TSQL DECLARE @LAT geography; SET @LAT = geography::STGeomFromText('POINT(-22.34900 47.65100)', 4326); select geography::Point(@LAT.LONG, @LAT.LAT, 4326).LONG, geography::Point(@LAT.LONG, @LAT.LAT, 4326).LAT; go -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: syntax error at or near ".")~~ +~~START~~ +float#!#float +47.651#!#-22.349 +~~END~~ --- Currently it is not supported --- TODO: Need to support it and make it similar to TSQL DECLARE @LAT geography; SET @LAT = geography::STGeomFromText('POINT(-22.34900 47.65100)', 4326); select geography::Point(@LAT.LONG, @LAT.LAT, 4326).STAsText(), geography::Point(@LAT.LONG, @LAT.LAT, 4326).STAsBinary(), geography::Point(@LAT.LONG, @LAT.LAT, 4326).STDistance(geography::Point(@LAT.LONG, @LAT.LAT, 4326)); go -~~ERROR (Code: 33557097)~~ - -~~ERROR (Message: syntax error at or near ".")~~ +~~START~~ +text#!#varbinary#!#float +POINT(47.651 -22.349)#!#010100000017D9CEF753D34740D34D6210585936C0#!#0.0 +~~END~~ SELECT @@ -903,7 +1699,7 @@ SELECT FROM SpatialData JOIN - SPATIALPOINTGEOG_dt ON SPATIALPOINTGEOG_dt.location.long - SpatialData.SpatialLocation.lat <= 10; + SPATIALPOINTGEOG_dt ON SPATIALPOINTGEOG_dt.location.LONG - SpatialData.SpatialLocation.LAT <= 10; GO ~~START~~ int#!#float#!#float @@ -937,15 +1733,15 @@ WITH RegionLocations AS ( FROM SpatialData JOIN - SPATIALPOINTGEOG_dt ON SPATIALPOINTGEOG_dt.location.long - SpatialData.SpatialLocation.lat <= 10 + SPATIALPOINTGEOG_dt ON SPATIALPOINTGEOG_dt.location.LONG - SpatialData.SpatialLocation.LAT <= 10 ) SELECT - lat, + LAT, COUNT(ID) AS LocationCount FROM RegionLocations GROUP BY - lat; + LAT; GO ~~START~~ float#!#int @@ -958,7 +1754,7 @@ float#!#int with mycte (a) as (select SPATIALPOINTGEOG_dt.location from SPATIALPOINTGEOG_dt) select a.STAsText() - from mycte x inner join SPATIALPOINTGEOG_dt y on x.a.lat >= y.location.long; + from mycte x inner join SPATIALPOINTGEOG_dt y on x.a.LAT >= y.location.LONG; go ~~START~~ text @@ -991,7 +1787,7 @@ POINT(47.651 -22.349) -- Test with tvf select f.STAsText() - from testspatial_tvf(1) f inner join SPATIALPOINTGEOG_dt t on f.location.lat >= t.location.long; + from testspatial_tvf(1) f inner join SPATIALPOINTGEOG_dt t on f.location.LAT >= t.location.LONG; go ~~START~~ text @@ -1086,7 +1882,7 @@ SELECT location.STY from SPATIALPOINTGEOG_dt; GO ~~ERROR (Code: 33557097)~~ -~~ERROR (Message: function sys.sty(geography) does not exist)~~ +~~ERROR (Message: column notation .sty applied to type geography, which is not a composite type)~~ SELECT * FROM GeogView; diff --git a/test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.txt b/test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.txt index fbf811a041..97bad2cc34 100644 --- a/test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.txt +++ b/test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.txt @@ -64,4 +64,34 @@ DROP TABLE IF EXISTS TypeToGeog DROP TABLE IF EXISTS SPATIALPOINT_dt +DROP PROCEDURE IF EXISTS GetPointsByXCoordinate + +DROP PROCEDURE IF EXISTS GetPointsByXCoordinate1 + +DROP FUNCTION IF EXISTS dbo.GetXCoordinate + +DROP FUNCTION IF EXISTS GetGeometry + +DROP TRIGGER IF EXISTS trg_LogXCoordinateChange + +DROP TABLE IF EXISTS XCoordinateChangeLog + +DROP TRIGGER IF EXISTS trg_LogDistanceChange + +DROP TABLE IF EXISTS DistanceChangeLog + +DROP TABLE IF EXISTS YourTable + +DROP TABLE IF EXISTS YourTable1 + +DROP TABLE IF EXISTS TableA + +DROP TABLE IF EXISTS TableB + +DROP PROCEDURE IF EXISTS GetPointsWithinDistance + +DROP FUNCTION IF EXISTS dbo.CalculateDistance + +DROP TABLE IF EXISTS YourTable2 + Drop Table IF EXISTS babelfish_migration_mode_table diff --git a/test/JDBC/input/datatypes/TestSpatialPoint-vu-prepare.txt b/test/JDBC/input/datatypes/TestSpatialPoint-vu-prepare.txt index 50ede8eed3..8c12c32255 100644 --- a/test/JDBC/input/datatypes/TestSpatialPoint-vu-prepare.txt +++ b/test/JDBC/input/datatypes/TestSpatialPoint-vu-prepare.txt @@ -42,6 +42,41 @@ INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::STPointFromText('P #Positive Test for Point with SRID 4326 INSERT INTO SPATIALPOINTGEOM_dt (location) VALUES ( geometry::Point(47.65100, -22.34900, 4326) ) +CREATE TABLE YourTable ( ID INT PRIMARY KEY, PointColumn geometry ); + +INSERT INTO YourTable (ID, PointColumn) VALUES (1, geometry::Point(3.0, 4.0, 4326)), (2, geometry::Point(5.0, 6.0, 4326)); + +CREATE FUNCTION dbo.GetXCoordinate(@point geometry) RETURNS float AS BEGIN RETURN @point.STX; END; + +CREATE TABLE TableA (ID INT PRIMARY KEY, PointA geometry); +CREATE TABLE TableB (ID INT PRIMARY KEY, PointB geometry); +INSERT INTO TableA (ID, PointA) VALUES (1, geometry::Point(1.0, 2.0, 4326)); +INSERT INTO TableB (ID, PointB) VALUES (1, geometry::Point(3.0, 4.0, 4326)); + +CREATE PROCEDURE GetPointsByXCoordinate @XCoordinate FLOAT AS BEGIN SELECT * FROM YourTable WHERE PointColumn.STX = @XCoordinate; END; + +CREATE PROCEDURE GetPointsByXCoordinate1 @XCoordinate FLOAT AS BEGIN DECLARE @Sql NVARCHAR(MAX); SET @Sql = N'SELECT ID, PointColumn.STX AS XCoordinate FROM YourTable WHERE PointColumn.STX = @ParamXCoordinate'; EXEC sp_executesql @Sql,N'@ParamXCoordinate FLOAT',@XCoordinate; END; + +CREATE TABLE YourTable1 ( ID INT PRIMARY KEY, STX geometry ); +INSERT INTO YourTable1 (ID, STX) VALUES (1, geometry::Point(3.0, 4.0, 4326)), (2, geometry::Point(5.0, 6.0, 4326)); + +CREATE FUNCTION GetGeometry() RETURNS geometry AS BEGIN RETURN geometry::Point(1.0, 2.0, 4326); END; + +CREATE TABLE XCoordinateChangeLog (PointID INT,OldXCoordinate FLOAT,NewXCoordinate FLOAT,ChangeDate DATETIME); + +CREATE TRIGGER trg_LogXCoordinateChange ON YourTable AFTER UPDATE AS BEGIN INSERT INTO XCoordinateChangeLog (PointID, OldXCoordinate, NewXCoordinate, ChangeDate) SELECT i.ID, d.PointColumn.STX, i.PointColumn.STX, GETDATE() FROM inserted i JOIN deleted d ON i.ID = d.ID WHERE i.PointColumn.STX <> d.PointColumn.STX; END; + +CREATE TABLE YourTable2 ( ID INT PRIMARY KEY, PointColumn1 geometry, PointColumn2 geometry ); +INSERT INTO YourTable2 (ID, PointColumn1, PointColumn2) VALUES (1, geometry::Point(3.0, 4.0, 4326), geometry::Point(4.0, 5.0, 4326)); + +CREATE FUNCTION dbo.CalculateDistance(@point1 geometry,@point2 geometry) RETURNS float AS BEGIN RETURN @point1.STDistance(@point2); END; + +CREATE PROCEDURE GetPointsWithinDistance @referencePoint geometry, @maxDistance float AS BEGIN SELECT * FROM YourTable WHERE PointColumn.STDistance(@referencePoint) <= @maxDistance; END; + +CREATE TABLE DistanceChangeLog (PointID INT,OldDistance FLOAT,NewDistance FLOAT,ChangeDate DATETIME); + +CREATE TRIGGER trg_LogDistanceChange ON YourTable AFTER UPDATE AS BEGIN DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); INSERT INTO DistanceChangeLog (PointID, OldDistance, NewDistance, ChangeDate) SELECT i.ID, d.PointColumn.STDistance(@referencePoint), i.PointColumn.STDistance(@referencePoint), GETDATE() FROM inserted i JOIN deleted d ON i.ID = d.ID WHERE i.PointColumn.STDistance(@referencePoint) <> d.PointColumn.STDistance(@referencePoint); END; + #Tests for Geometry type Prepared Statements prepst#!#INSERT INTO SPATIALPOINTGEOM_dt(location) values(@location) #!#GEOMETRY|-|location|-|Point(47.65100 -22.34900):4326 prepst#!#exec#!#GEOMETRY|-|location|-|Point(1.0 2.0):4326 @@ -174,7 +209,7 @@ CREATE VIEW TextFromGeog AS SELECT STAsText(location) AS TextRepresentation FROM CREATE VIEW BinaryFromGeog AS SELECT STAsBinary(location) AS BinaryRepresentation FROM SPATIALPOINTGEOG_dt; -CREATE VIEW CoordsFromGeog AS SELECT long(location), lat(location) AS Coordinates FROM SPATIALPOINTGEOG_dt; +CREATE VIEW CoordsFromGeog AS SELECT LONG(location), LAT(location) AS Coordinates FROM SPATIALPOINTGEOG_dt; CREATE VIEW GeogView AS SELECT location.LONG, location.LAT AS Coordinates FROM SPATIALPOINTGEOG_dt; diff --git a/test/JDBC/input/datatypes/TestSpatialPoint-vu-verify.sql b/test/JDBC/input/datatypes/TestSpatialPoint-vu-verify.sql index f15f6a5bd1..340e5d5afa 100644 --- a/test/JDBC/input/datatypes/TestSpatialPoint-vu-verify.sql +++ b/test/JDBC/input/datatypes/TestSpatialPoint-vu-verify.sql @@ -10,20 +10,30 @@ SELECT STAsText(@point); SELECT @point.STAsText(); Go +DECLARE @point geometry; +SET @point = geometry::Point(1.0, 2.0, 4326); +SELECT @point.STX AS XCoordinate; +GO + +DECLARE @point1 geometry = geometry::Point(1.0, 2.0, 4326); +DECLARE @point2 geometry = geometry::Point(3.0, 4.0, 4326); +SELECT @point1.STDistance(@point2) AS Distance; +GO + DECLARE @point geometry; SET @point = geometry::STGeomFromText('POINT(-122.34900 47.65100)', 4326); -SELECT stx(@point); -SELECT sty(@point); -SELECT @point.stx; -SELECT @point.sty; +SELECT STX(@point); +SELECT STY(@point); +SELECT @point.STX; +SELECT @point.STY; Go DECLARE @point geometry; SET @point = geometry::POINT(22.34900, -47.65100, 4326); -SELECT stx(@point); -SELECT sty(@point); -SELECT @point.stx; -SELECT @point.sty; +SELECT STX(@point); +SELECT STY(@point); +SELECT @point.STX; +SELECT @point.STY; Go DECLARE @point1 geometry, @point2 geometry; @@ -38,15 +48,11 @@ SET @point = geometry::STGeomFromText('POINT(-122.34900 47.65100)', 4326); Insert INTO SPATIALPOINTGEOM_dt(location) VALUES(geometry::point(@point.STX, @point.STY,4326)) go --- Currently it is not supported --- TODO: Need to support it and make it similar to TSQL DECLARE @STX geometry; SET @STX = geometry::STGeomFromText('POINT(-122.34900 47.65100)', 4326); select geometry::Point(@STX.STX, @STX.STY, 4326).STX, geometry::Point(@STX.STX, @STX.STY, 4326).STY; go --- Currently it is not supported --- TODO: Need to support it and make it similar to TSQL DECLARE @STX geometry; SET @STX = geometry::STGeomFromText('POINT(-122.34900 47.65100)', 4326); select geometry::Point(@STX.STX, @STX.STY, 4326).STAsText(), geometry::Point(@STX.STX, @STX.STY, 4326).STAsBinary(), geometry::Point(@STX.STX, @STX.STY, 4326).STDistance(geometry::Point(@STX.STX, @STX.STY, 4326)); @@ -124,6 +130,382 @@ GO SELECT location FROM SPATIALPOINTGEOM_dt; GO +SELECT PointColumn.STX AS XCoordinate FROM YourTable; +GO + +SELECT * FROM YourTable WHERE PointColumn.STX > 3.0; +GO + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT * FROM YourTable WHERE PointColumn.STX > @point.STX; +GO + +SELECT ID, PointColumn.STX AS XCoordinate FROM YourTable; +GO + +SELECT ID, dbo.GetXCoordinate(PointColumn) AS XCoordinate FROM YourTable; +GO + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT dbo.GetXCoordinate(@point); +GO + +SELECT * FROM TableA JOIN TableB ON TableA.PointA.STX = TableB.PointB.STX; +GO + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT * FROM TableA JOIN TableB ON TableA.PointA.STX > @point.STX; +GO + +SELECT * FROM YourTable ORDER BY PointColumn.STX; +GO + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT * FROM YourTable ORDER BY @point.STX; +GO + +SELECT ID, PointColumn.STX AS XCoordinate, +CASE WHEN PointColumn.STX > 3.0 THEN 'High X' +ELSE 'Low X' +END AS XCoordinateCategory FROM YourTable; +GO + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT ID, PointColumn.STX AS XCoordinate, +CASE WHEN @point.STX > 3.0 THEN 'High X' +ELSE 'Low X' +END AS XCoordinateCategory FROM YourTable; +GO + +WITH PointData AS ( SELECT ID, PointColumn.STX AS XCoordinate FROM YourTable ) +SELECT * FROM PointData WHERE XCoordinate > 3.0; +GO + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +WITH PointData AS ( SELECT ID, @point.STX AS XCoordinate FROM YourTable ) +SELECT * FROM PointData WHERE XCoordinate > 3.0; +GO + +SELECT PointColumn.STX AS XCoordinate, COUNT(*) AS PointCount +FROM YourTable GROUP BY PointColumn.STX; +GO + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT @point.STX AS XCoordinate, COUNT(*) AS PointCount +FROM YourTable GROUP BY PointColumn.STX; +GO + +SELECT ID, PointColumn.STX AS XCoordinate, +PointColumn.STX - LAG(PointColumn.STX) OVER (ORDER BY ID) AS XCoordinateDifference +FROM YourTable; +GO + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT ID, @point.STX AS XCoordinate, +@point.STX - LAG(@point.STX) OVER (ORDER BY ID) AS XCoordinateDifference +FROM YourTable; +GO + +DECLARE @XCoordinate FLOAT = 3.0; +DECLARE @DynamicQuery NVARCHAR(MAX); +SET @DynamicQuery = N' SELECT * FROM YourTable WHERE PointColumn.STX > ' + CAST(@XCoordinate AS NVARCHAR(MAX)); +EXEC sp_executesql @DynamicQuery; +GO + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +DECLARE @DynamicQuery NVARCHAR(MAX); +SET @DynamicQuery = N' SELECT * FROM YourTable WHERE PointColumn.STX > ' + CAST(@point.STX AS NVARCHAR(MAX)); +EXEC sp_executesql @DynamicQuery; +GO + +EXEC GetPointsByXCoordinate @XCoordinate = 4.0; +GO + +EXEC GetPointsByXCoordinate1 @XCoordinate = 4.0; +GO + +DECLARE @XCoordinate FLOAT = 3.0; +DECLARE @DynamicQuery NVARCHAR(MAX); +SET @DynamicQuery = N' SELECT * FROM YourTable WHERE PointColumn.STX > ' + CAST(@XCoordinate AS NVARCHAR(MAX)); +EXEC sp_executesql @DynamicQuery; +GO + +SELECT ID, PointColumn.STX AS XCoordinate, CASE WHEN PointColumn.STX < 0 +THEN 'Negative X' WHEN PointColumn.STX = 0 THEN 'Zero X' +ELSE 'Positive X' END AS XCoordinateCategory FROM YourTable; +GO + +DECLARE @point geometry = geometry::Point(1.0, 2.0, 4326); +SELECT ID, @point.STX AS XCoordinate, CASE WHEN @point.STX < 0 +THEN 'Negative X' WHEN @point.STX = 0 THEN 'Zero X' +ELSE 'Positive X' END AS XCoordinateCategory FROM YourTable; +GO + +SELECT * FROM ( SELECT ID, +CASE WHEN PointColumn.STX BETWEEN 0 AND 5 THEN '0-5' +WHEN PointColumn.STX BETWEEN 5.1 AND 10 THEN '5.1-10' +ELSE '10.1+' +END AS XCoordRange +FROM YourTable +) AS Source +PIVOT ( COUNT(ID) FOR XCoordRange IN ([0-5], [5.1-10], [10.1+])) AS PivotTable; +GO + +SELECT ID, PointColumn.STX AS XCoordinate, +JSON_QUERY('{"XCoordinate":' + CAST(PointColumn.STX AS NVARCHAR(MAX)) + '}') AS XCoordinateJson +FROM YourTable; +GO + +DECLARE @point geometry = geometry::Point(3.0, 2.0, 4326); +SELECT ID, @point.STX AS XCoordinate, +JSON_QUERY('{"XCoordinate":' + CAST(@point.STX AS NVARCHAR(MAX)) + '}') AS XCoordinateJson +FROM YourTable; +GO + +SELECT [PointColumn].[STX] AS XCoordinate FROM [YourTable]; +GO + +DECLARE @point geometry = geometry::Point(3.0, 2.0, 4326); +SELECT @point.[STX] AS XCoordinate +GO + +SELECT PointColumn.STX AS XCoordinate FROM YourTable; +GO + +SELECT YourTable.PointColumn.STX AS XCoordinate FROM YourTable; +GO + +SELECT dbo.YourTable.PointColumn.STX AS XCoordinate FROM YourTable; +GO + +SELECT YourTable1.STX.STX AS XCoordinate FROM YourTable1; +GO + +DECLARE @result geometry; +SET @result = dbo.GetGeometry(); +DECLARE @xCoordinate float; +SET @xCoordinate = @result.STX; +SELECT @result AS ResultGeometry, @xCoordinate AS XCoordinate; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +UPDATE YourTable SET PointColumn = @referencePoint +WHERE PointColumn.STX >= @referencePoint.STX; +GO + +SELECT ID, PointColumn1.STDistance(PointColumn2) AS Distance FROM YourTable2; +GO + +DECLARE @point1 geometry = geometry::Point(1.0, 2.0, 4326); +SELECT ID, PointColumn1.STDistance(@point1) AS Distance FROM YourTable2; +GO + +DECLARE @point1 geometry = geometry::Point(1.0, 2.0, 4326); +SELECT ID, @point1.STDistance(PointColumn2) AS Distance FROM YourTable2; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @maxDistance float = 5.0; +SELECT * FROM YourTable WHERE PointColumn.STDistance(@referencePoint) <= @maxDistance; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM YourTable WHERE @referencePoint.STDistance(PointColumn) <= @referencePoint.STX; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM YourTable WHERE PointColumn.STDistance(@referencePoint) <= @referencePoint.STX; +GO + +SELECT ID, dbo.CalculateDistance(PointColumn1, PointColumn2) AS Distance FROM YourTable2; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, dbo.CalculateDistance(@referencePoint, PointColumn2) AS Distance FROM YourTable2; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, dbo.CalculateDistance(PointColumn1, @referencePoint) AS Distance FROM YourTable2; +GO + +SELECT * FROM TableA JOIN TableB ON PointA.STDistance(TableB.PointB) <= 5.0; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM TableA JOIN TableB ON @referencePoint.STDistance(TableB.PointB) <= 5.0; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM TableA JOIN TableB ON PointA.STDistance(@referencePoint) <= 5.0; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM TableA JOIN TableB ON TableB.PointB.STDistance(@referencePoint) <= 5.0; +GO + +SELECT * FROM YourTable2 ORDER BY PointColumn1.STDistance(PointColumn2); +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM YourTable ORDER BY PointColumn.STDistance(@referencePoint); +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT * FROM YourTable ORDER BY @referencePoint.STDistance(PointColumn); +GO + +DECLARE @thresholdDistance float = 3.0; +SELECT ID, PointColumn1.STDistance(PointColumn2) AS DistanceBetweenPoints, +CASE WHEN PointColumn1.STDistance(PointColumn2) <= @thresholdDistance THEN 'Close' ELSE 'Far' +END AS Proximity +FROM YourTable2; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, PointColumn1.STDistance(@referencePoint) AS DistanceBetweenPoints, +CASE WHEN @referencePoint.STDistance(PointColumn2) <= @referencePoint.STX THEN 'Close' ELSE 'Far' +END AS Proximity +FROM YourTable2; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +WITH DistanceCTE AS ( SELECT ID, PointColumn.STDistance(@referencePoint) AS Distance FROM YourTable) +SELECT * FROM DistanceCTE WHERE Distance <= 3.0; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +WITH DistanceCTE AS ( SELECT ID, @referencePoint.STDistance(PointColumn) AS Distance FROM YourTable) +SELECT * FROM DistanceCTE WHERE Distance <= 3.0; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @distanceInterval float = 5.0; +SELECT ROUND(PointColumn.STDistance(@referencePoint) / @distanceInterval, 0) * @distanceInterval AS DistanceGroup, +COUNT(*) AS PointCount +FROM YourTable +GROUP BY ROUND(PointColumn.STDistance(@referencePoint) / @distanceInterval, 0) * @distanceInterval; +GO + +DECLARE @referencePoint geometry = geometry::Point(1.0, 0.0, 4326); +SELECT ROUND(PointColumn.STDistance(@referencePoint) / @referencePoint.STX, 0) * @referencePoint.STX AS DistanceGroup, +COUNT(*) AS PointCount +FROM YourTable +GROUP BY ROUND(PointColumn.STDistance(@referencePoint) / @referencePoint.STX, 0) * @referencePoint.STX; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, PointColumn1.STDistance(PointColumn2) AS Distance, +PointColumn1.STDistance(@referencePoint) - LAG(PointColumn1.STDistance(PointColumn2)) OVER (ORDER BY ID) AS DistanceDifference +FROM YourTable2; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, PointColumn.STDistance(@referencePoint) AS Distance, +@referencePoint.STDistance(PointColumn) - LAG(@referencePoint.STX) OVER (ORDER BY ID) AS DistanceDifference +FROM YourTable; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @maxDistance float = 3.0; +EXEC GetPointsWithinDistance @referencePoint, @maxDistance; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @maxDistance float = 3.0; +DECLARE @DynamicQuery NVARCHAR(MAX); +SET @DynamicQuery = N' +SELECT * FROM YourTable +WHERE PointColumn.STDistance(geometry::STGeomFromText(' + QUOTENAME(@referencePoint.STAsText(), '''') + ', 4326)) <= ' + CAST(@maxDistance AS NVARCHAR(MAX)); +EXEC sp_executesql @DynamicQuery; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @DynamicQuery NVARCHAR(MAX); +SET @DynamicQuery = N' +SELECT * FROM YourTable +WHERE PointColumn.STDistance(geometry::STGeomFromText(' + QUOTENAME(@referencePoint.STAsText(), '''') + ', 4326)) <= ' + CAST(@referencePoint.STX AS NVARCHAR(MAX)); +EXEC sp_executesql @DynamicQuery; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @thresholdDistance float = 3.0; +SELECT ID, PointColumn.STDistance(@referencePoint) AS DistanceToReferencePoint, +CASE WHEN PointColumn.STDistance(@referencePoint) <= @thresholdDistance THEN 'Close' +ELSE 'Far' +END AS Proximity +FROM YourTable; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, @referencePoint.STDistance(PointColumn) AS DistanceToReferencePoint, +CASE WHEN @referencePoint.STDistance(PointColumn) <= @referencePoint.STY THEN 'Close' +ELSE 'Far' +END AS Proximity +FROM YourTable; +GO + +DECLARE @distanceRanges TABLE (MinDistance float, MaxDistance float); +INSERT INTO @distanceRanges VALUES (0, 5), (5, 10), (10, 15); +SELECT * FROM ( SELECT ID, +CASE WHEN PointColumn1.STDistance(PointColumn2) BETWEEN 0 AND 5 THEN '0-5' +WHEN PointColumn1.STDistance(PointColumn2) BETWEEN 5.1 AND 10 THEN '5.1-10' +WHEN PointColumn1.STDistance(PointColumn2) BETWEEN 10.1 AND 15 THEN '10.1-15' +ELSE '15.1+' +END AS DistanceRange +FROM YourTable2 +) AS Source +PIVOT ( COUNT(ID) FOR DistanceRange IN ([0-5], [5.1-10], [10.1-15], [15.1+])) AS PivotTable; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, PointColumn.STDistance(@referencePoint) AS Distance, +JSON_QUERY('{"Distance":' + CAST(PointColumn.STDistance(@referencePoint) AS NVARCHAR(MAX)) + '}') AS DistanceJson +FROM YourTable; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT ID, @referencePoint.STDistance(PointColumn) AS Distance, +JSON_QUERY('{"Distance":' + CAST(@referencePoint.STDistance(PointColumn) AS NVARCHAR(MAX)) + '}') AS DistanceJson +FROM YourTable; +GO + +SELECT [PointColumn1].STDistance([PointColumn2]) AS distance FROM [YourTable2]; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +DECLARE @thresholdDistance float = 10.0; +DECLARE @sql NVARCHAR(MAX); +DECLARE @params NVARCHAR(MAX); +SET @sql = N' +SELECT ID, PointColumn.STDistance(@referencePoint) AS DistanceToReferencePoint, +CASE WHEN PointColumn.STDistance(@referencePoint) <= @thresholdDistance THEN ''Close'' +ELSE ''Far'' +END AS Proximity +FROM YourTable +WHERE PointColumn.STDistance(@referencePoint) <= @thresholdDistance;'; +SET @params = N'@referencePoint geometry, @thresholdDistance float'; +EXEC sp_executesql @sql, @params, @referencePoint, @thresholdDistance; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT PointColumn.STDistance(@referencePoint) AS Distance FROM YourTable; +SELECT YourTable.PointColumn.STDistance(@referencePoint) AS Distance FROM YourTable; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT dbo.YourTable.PointColumn.STDistance(@referencePoint) AS Distance FROM YourTable; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +UPDATE YourTable SET PointColumn = @referencePoint +WHERE PointColumn.STDistance(@referencePoint) <= 2.0; +GO + +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +UPDATE YourTable SET PointColumn = @referencePoint +WHERE @referencePoint.STDistance(PointColumn) <= 2.0; +GO + -- Create Type Test Case currently Babelfish supports it but TSQL doesn't for spatial Types, Although it doesn't break anything -- TODO: Make it similar to T-SQL SELECT * FROM TypeTable; @@ -230,18 +612,18 @@ Go DECLARE @point geography; SET @point = geography::STPointFromText('POINT(-122.34900 47.65100)', 4326); -SELECT long(@point); -SELECT lat(@point); -SELECT @point.long; -SELECT @point.lat; +SELECT LONG(@point); +SELECT LAT(@point); +SELECT @point.LONG; +SELECT @point.LAT; Go DECLARE @point geography; SET @point = geography::POINT(22.34900, -47.65100, 4326); -SELECT long(@point); -SELECT lat(@point); -SELECT @point.long; -SELECT @point.lat; +SELECT LONG(@point); +SELECT LAT(@point); +SELECT @point.LONG; +SELECT @point.LAT; Go DECLARE @point1 geography, @point2 geography; @@ -256,15 +638,11 @@ SET @point = geography::STGeomFromText('POINT(-22.34900 47.65100)', 4326); Insert INTO SPATIALPOINTGEOG_dt(location) VALUES(geography::point(@point.LONG, @point.LAT, 4326)) go --- Currently it is not supported --- TODO: Need to support it and make it similar to TSQL DECLARE @LAT geography; SET @LAT = geography::STGeomFromText('POINT(-22.34900 47.65100)', 4326); select geography::Point(@LAT.LONG, @LAT.LAT, 4326).LONG, geography::Point(@LAT.LONG, @LAT.LAT, 4326).LAT; go --- Currently it is not supported --- TODO: Need to support it and make it similar to TSQL DECLARE @LAT geography; SET @LAT = geography::STGeomFromText('POINT(-22.34900 47.65100)', 4326); select geography::Point(@LAT.LONG, @LAT.LAT, 4326).STAsText(), geography::Point(@LAT.LONG, @LAT.LAT, 4326).STAsBinary(), geography::Point(@LAT.LONG, @LAT.LAT, 4326).STDistance(geography::Point(@LAT.LONG, @LAT.LAT, 4326)); @@ -277,7 +655,7 @@ SELECT FROM SpatialData JOIN - SPATIALPOINTGEOG_dt ON SPATIALPOINTGEOG_dt.location.long - SpatialData.SpatialLocation.lat <= 10; + SPATIALPOINTGEOG_dt ON SPATIALPOINTGEOG_dt.location.LONG - SpatialData.SpatialLocation.LAT <= 10; GO WITH RegionLocations AS ( @@ -287,27 +665,27 @@ WITH RegionLocations AS ( FROM SpatialData JOIN - SPATIALPOINTGEOG_dt ON SPATIALPOINTGEOG_dt.location.long - SpatialData.SpatialLocation.lat <= 10 + SPATIALPOINTGEOG_dt ON SPATIALPOINTGEOG_dt.location.LONG - SpatialData.SpatialLocation.LAT <= 10 ) SELECT - lat, + LAT, COUNT(ID) AS LocationCount FROM RegionLocations GROUP BY - lat; + LAT; GO -- Test with CTE with mycte (a) as (select SPATIALPOINTGEOG_dt.location from SPATIALPOINTGEOG_dt) select a.STAsText() - from mycte x inner join SPATIALPOINTGEOG_dt y on x.a.lat >= y.location.long; + from mycte x inner join SPATIALPOINTGEOG_dt y on x.a.LAT >= y.location.LONG; go -- Test with tvf select f.STAsText() - from testspatial_tvf(1) f inner join SPATIALPOINTGEOG_dt t on f.location.lat >= t.location.long; + from testspatial_tvf(1) f inner join SPATIALPOINTGEOG_dt t on f.location.LAT >= t.location.LONG; go -- Null test for Geospatial functions