diff --git a/contrib/babelfishpg_tsql/src/pl_comp.c b/contrib/babelfishpg_tsql/src/pl_comp.c index af89f2f5a1..c88cf394e3 100644 --- a/contrib/babelfishpg_tsql/src/pl_comp.c +++ b/contrib/babelfishpg_tsql/src/pl_comp.c @@ -27,6 +27,7 @@ #include "catalog/pg_type.h" #include "funcapi.h" #include "nodes/makefuncs.h" +#include "parser/parse_expr.h" #include "parser/parse_relation.h" #include "parser/parse_type.h" #include "utils/builtins.h" @@ -44,6 +45,8 @@ #include "codegen.h" #include "iterative_exec.h" #include "multidb.h" +#include "session.h" +#include "catalog.h" /* ---------- * Our own local and global variables @@ -74,6 +77,12 @@ MemoryContext pltsql_compile_tmp_cxt; */ static HTAB *pltsql_HashTable = NULL; +/* ---------- + * Hash table for geospatial functions + * ---------- + */ +static HTAB *ht_spatial_func_info = NULL; + typedef struct pltsql_hashent { PLtsql_func_hashkey key; @@ -82,6 +91,13 @@ typedef struct pltsql_hashent #define FUNCS_PER_USER 128 /* initial table size */ +/* Macro to check if field is a geospatial function */ +#define IS_GEOSPATIAL_FIELD(field) \ + (pg_strcasecmp(strVal(field), "stx") == 0 || \ + pg_strcasecmp(strVal(field), "sty") == 0 || \ + pg_strcasecmp(strVal(field), "lat") == 0 || \ + pg_strcasecmp(strVal(field), "long") == 0) + /* ---------- * Lookup table for EXCEPTION condition names * ---------- @@ -97,6 +113,25 @@ static const ExceptionLabelMap exception_label_map[] = { {NULL, 0} }; +typedef struct geospatial_hash_entry_t +{ + int key; + Oid funcid; + Oid returntype; +} geospatial_hash_entry_t; + +enum geospatial_type +{ + GEOM_STX, + GEOM_STY, + GEOG_LAT, + GEOG_LONG, + INVALID_TYPE +}; + +static Oid geomId = InvalidOid; +static Oid geogId = InvalidOid; + /* ---------- * Current session's handler * ---------- @@ -104,6 +139,12 @@ static const ExceptionLabelMap exception_label_map[] = { static int cur_handle_id = 1; +/* + * Global variable used to prevent recurring check for TSQL functional call for Geospatial types + * Eg: table.col.stx (here stx will be considered as a Geospatial function) + */ +static bool is_geospatial_function = false; + /* ---------- * static prototypes * ---------- @@ -142,6 +183,9 @@ static void pltsql_HashTableInsert(PLtsql_function *function, PLtsql_func_hashkey *func_key); static void pltsql_HashTableDelete(PLtsql_function *function); static void delete_function(PLtsql_function *func); +static Node *resolve_geospatial_col_ref(ParseState *pstate, ColumnRef *cref); +static List *resolve_geospatial_func_ref(ParseState *pstate, FuncCall *fn, List *fargs); +static char *extract_logical_schema_name(char *db_name, char *schema_name, MigrationMode mode); extern Portal ActivePortal; extern bool pltsql_function_parse_error_transpose(const char *prosrc); @@ -1479,6 +1523,7 @@ pltsql_parser_setup(struct ParseState *pstate, PLtsql_expr *expr) { pstate->p_pre_columnref_hook = pltsql_pre_column_ref; pstate->p_post_columnref_hook = pltsql_post_column_ref; + pstate->p_pre_funcref_hook = resolve_geospatial_func_ref; pstate->p_post_expand_star_hook = pltsql_post_expand_star; pstate->p_paramref_hook = pltsql_param_ref; /* no need to use p_coerce_param_hook */ @@ -1539,6 +1584,20 @@ pltsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var) errdetail("It could refer to either a PL/tsql variable or a table column."), parser_errposition(pstate, cref->location))); } + /* + * We check if the current colRef represents a geospatial function + * Eg: SELECT col.STX from t1; + * where col is a column of table t1 + */ + else if (var == NULL) + { + Node *geovar; + geovar = resolve_geospatial_col_ref(pstate, cref); + if(geovar != NULL){ + printf("lol"); + } + //return geovar; + } return myvar; } @@ -1633,8 +1692,8 @@ pltsql_param_ref(ParseState *pstate, ParamRef *pref) snprintf(pname, sizeof(pname), "$%d", pref->number); nse = pltsql_ns_lookup(expr->ns, false, - pname, NULL, NULL, - NULL); + pname, NULL, NULL, + NULL); if (nse == NULL) return NULL; /* name not known to pltsql */ @@ -1642,6 +1701,246 @@ pltsql_param_ref(ParseState *pstate, ParamRef *pref) return make_datum_param(expr, nse->itemno, pref->location); } +/* + * extract_logical_schema_name + * converts physical schema name to logical schema name using given db_name and migration mode. + * This can be used in places where we want to revert the schema rewrites which have happened earlier, such + * as 'master_t2.geom.STX' -> 't2.geom.STX' + */ +static char * +extract_logical_schema_name(char *db_name, char *physical_schema_name, MigrationMode mode) +{ + + if (SINGLE_DB == mode) + { + if ((strlen(db_name) == 6 && (strncmp(db_name, "master", 6) == 0)) || + (strlen(db_name) == 6 && (strncmp(db_name, "tempdb", 6) == 0)) || + (strlen(db_name) == 4 && (strncmp(db_name, "msdb", 4) == 0))) + { + return physical_schema_name + strlen(db_name) + 1; + } + else + { + /* all schema names are not prepended with db name on single-db */ + return physical_schema_name; + } + } + else + { + return physical_schema_name + strlen(db_name) + 1; + } + + return physical_schema_name; +} + +/* + * This function handles geospatial syntax such as STX, STY, LAT, LONG notations and converts them to function calls. + */ +static Node * +resolve_geospatial_col_ref(ParseState *pstate, ColumnRef *cref) +{ + Node *last_field; /* represents the geospatial function name */ + Node *col; + + /* Initializing Hash Table to store func and return id's for geospatial functions */ + if (ht_spatial_func_info == NULL) + { + geospatial_hash_entry_t *t1 = (geospatial_hash_entry_t*)palloc(sizeof(geospatial_hash_entry_t)); + int key = GEOM_STX; + HASHCTL hashCtl; + geomId = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid, CStringGetDatum("geometry"), ObjectIdGetDatum(get_namespace_oid("sys", false))); + geogId = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid, CStringGetDatum("geography"), ObjectIdGetDatum(get_namespace_oid("sys", false))); + MemSet(&hashCtl, 0, sizeof(hashCtl)); + hashCtl.keysize = sizeof(int); + hashCtl.entrysize = sizeof(geospatial_hash_entry_t); + ht_spatial_func_info = hash_create("T-SQL geospatial function info hash", + SPI_processed, + &hashCtl, + HASH_ELEM | HASH_BLOBS); + /* stx */ + t1 = hash_search(ht_spatial_func_info, &key, HASH_ENTER, NULL); + t1->funcid = LookupFuncName(list_make2(makeString("sys"), makeString("stx")), 1, &geomId, false); + t1->returntype = get_func_rettype(t1->funcid); + /* sty */ + key = GEOM_STY; + t1 = hash_search(ht_spatial_func_info, &key, HASH_ENTER, NULL); + t1->funcid = LookupFuncName(list_make2(makeString("sys"), makeString("sty")), 1, &geomId, false); + t1->returntype = get_func_rettype(t1->funcid); + /* lat */ + key = GEOG_LAT; + t1 = hash_search(ht_spatial_func_info, &key, HASH_ENTER, NULL); + t1->funcid = LookupFuncName(list_make2(makeString("sys"), makeString("lat")), 1, &geogId, false); + t1->returntype = get_func_rettype(t1->funcid); + /* long */ + key = GEOG_LONG; + t1 = hash_search(ht_spatial_func_info, &key, HASH_ENTER, NULL); + t1->funcid = LookupFuncName(list_make2(makeString("sys"), makeString("long")), 1, &geogId, false); + t1->returntype = get_func_rettype(t1->funcid); + } + + /* if there is only one field then it cannot be a geospatial function call */ + if (list_length(cref->fields) <= 1) + { + is_geospatial_function = false; /* resetting the global variable */ + return NULL; + } + + last_field = (Node *) llast(cref->fields); + /* + * check if last field matches any of the geospatial functions - stx, sty, lat, long + * is_geospatial_function is used to make sure that we don't get stuck in infinite loop. + */ + if (IsA(last_field, String) && !is_geospatial_function && + IS_GEOSPATIAL_FIELD(last_field)) + { + FuncExpr *funcexpr = makeNode(FuncExpr); /* func expression to modify colref to funcref */ + char *name = strVal(last_field); + Oid dataTypeId; + int key; + geospatial_hash_entry_t *t1; + ColumnRef *colref = makeNode(ColumnRef); /* new colref to avoid making changes to existing structure */ + + colref->fields = list_copy(cref->fields); + /* if length is 3 then colref would have been modified by rewrite_column_refs function */ + if(list_length(colref->fields) == 3) + { + Node *schema = (Node *) linitial(colref->fields); + char *cur_db = get_cur_db_name(); + String *new_schema; + + if (!is_shared_schema(strVal(schema))) + { + new_schema = makeString(extract_logical_schema_name(cur_db, strVal(schema), get_migration_mode())); + colref->fields = list_delete_first(colref->fields); + colref->fields = lcons(new_schema, colref->fields); + } + pfree(cur_db); + } + colref->fields = list_delete_last(colref->fields); /* deletes the function name and check if the remaining colref is a valid column reference */ + is_geospatial_function = true; + PG_TRY(); + { + col = transformExpr(pstate, (Node *) colref, pstate->p_expr_kind); /* Recursive call to check for valid column reference */ + } + PG_CATCH(); + { + is_geospatial_function = false; /* resetting the global variable */ + pfree(colref); + pfree(last_field); + return NULL; /* if not a valid column ref */ + } + PG_END_TRY(); + + is_geospatial_function = false; /* resetting the global variable */ + dataTypeId = ((Var *)col)->vartype; + + /* check key for hash table search */ + if (pg_strcasecmp(name, "stx") == 0 && (int)geomId == (int)dataTypeId) + key = GEOM_STX; + else if (pg_strcasecmp(name, "sty") == 0 && (int)geomId == (int)dataTypeId) + key = GEOM_STY; + else if (pg_strcasecmp(name, "lat") == 0 && (int)geogId == (int)dataTypeId) + key = GEOG_LAT; + else if (pg_strcasecmp(name, "long") == 0 && (int)geogId == (int)dataTypeId) + key = GEOG_LONG; + else + key = INVALID_TYPE; + + t1 = hash_search(ht_spatial_func_info, &key, HASH_FIND, NULL); + /* Prepare a Funcexpr node for the corresponding geospatial function. */ + /* if key is Invalid then we need to throw an error */ + if (key == INVALID_TYPE) + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("function sys.%s(%s) does not exist", name, format_type_be(dataTypeId)))); + } + + funcexpr = makeFuncExpr(t1->funcid, t1->returntype, list_make1(col), 0, 0, COERCE_EXPLICIT_CALL); + + funcexpr->location = cref->location; + + pfree(colref); + pfree(last_field); + return (Node *) funcexpr; + } + + is_geospatial_function = false; /* resetting the global variable */ + pfree(last_field); + return NULL; +} + +/* + * This function handles geospatial syntax such as STDistance, STAsText, STAsBinary notations and converts them to function calls. + */ +static List * +resolve_geospatial_func_ref(ParseState *pstate, FuncCall *fn, List *fargs) +{ + return fargs; + + if(list_length(fn->funcname) > 1 && list_length(fn->args) <= 1 + && fn->agg_order == NULL && fn->agg_filter == NULL + && !fn->agg_within_group && !fn->agg_star + && !fn->agg_distinct && !fn->func_variadic) + { + Node *fname; /* represents the geospatial function name */ + Node *col; + fname = (Node *) llast(fn->funcname); + /* + * check if last field matches any of the geospatial functions - stdistance, stastext, stasbinary + * is_geospatial_function is used to make sure that we don't get stuck in infinite loop. + */ + if (IsA(fname, String) && !is_geospatial_function && + ((pg_strcasecmp(strVal(fname), "stdistance") == 0 && list_length(fn->args) == 1) || + (pg_strcasecmp(strVal(fname), "stastext") == 0 && list_length(fn->args) == 0) || + (pg_strcasecmp(strVal(fname), "stasbinary") == 0 && list_length(fn->args) == 0))) + { + ColumnRef *cref = makeNode(ColumnRef); /* new colref to avoid making changes to existing structure */ + cref->fields = list_copy(fn->funcname); + cref->fields = list_delete_last(cref->fields); /* deletes the function name and check if the remaining colref is a valid column reference */ + + /* if length is 1 then colref would have been modified by rewrite_plain_name function */ + if(list_length(cref->fields) == 1) + { + Node *schema = (Node *) linitial(cref->fields); + char *cur_db = get_cur_db_name(); + String *new_schema; + + if (!is_shared_schema(strVal(schema))) + { + new_schema = makeString(extract_logical_schema_name(cur_db, strVal(schema), get_migration_mode())); + cref->fields = list_delete_first(cref->fields); + cref->fields = lcons(new_schema, cref->fields); + } + pfree(cur_db); + } + is_geospatial_function = true; + PG_TRY(); + { + col = transformExpr(pstate, (Node *) cref, pstate->p_expr_kind); /* Recursive call to check for valid column reference */ + } + PG_CATCH(); + { + is_geospatial_function = false; /* resetting the global variable */ + pfree(cref); + return fargs; + } + PG_END_TRY(); + + /* Modify Funcexpr node for the corresponding geospatial function. */ + is_geospatial_function = false; /* resetting the global variable */ + fn->args = lcons(cref, fn->args); + fargs = lcons(col, fargs); + fn->funcname = list_delete_first(fn->funcname); + pfree(cref); + return fargs; + } + } + is_geospatial_function = false; /* resetting the global variable */ + + return fargs; +} + /* * resolve_column_ref attempt to resolve a ColumnRef as a pltsql var * diff --git a/contrib/babelfishpg_tsql/src/pl_handler.c b/contrib/babelfishpg_tsql/src/pl_handler.c index 207f16656a..e4bb832a8b 100644 --- a/contrib/babelfishpg_tsql/src/pl_handler.c +++ b/contrib/babelfishpg_tsql/src/pl_handler.c @@ -487,6 +487,11 @@ pltsql_pre_parse_analyze(ParseState *pstate, RawStmt *parseTree) if (prev_pre_parse_analyze_hook) prev_pre_parse_analyze_hook(pstate, parseTree); + // if (pstate->p_pre_columnref_hook == NULL && pstate->p_post_columnref_hook == NULL + // && pstate->p_pre_funcref_hook == NULL && pstate->p_post_expand_star_hook == NULL + // && pstate->p_paramref_hook == NULL && parseTree->stmt->type == T_SelectStmt && sql_dialect == SQL_DIALECT_TSQL) + // pltsql_parser_setup(pstate, NULL); + switch (parseTree->stmt->type) { case T_InsertStmt: 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 cfd1c8615f..97bad2cc34 100644 --- a/test/JDBC/expected/TestSpatialPoint-vu-cleanup.out +++ b/test/JDBC/expected/TestSpatialPoint-vu-cleanup.out @@ -18,8 +18,26 @@ DROP VIEW IF EXISTS TransformFromGeog DROP VIEW IF EXISTS equal_geog +DROP VIEW IF EXISTS GeomView + +DROP PROCEDURE IF EXISTS dbo.p_getcoordinates + +DROP FUNCTION IF EXISTS f_getval + +DROP VIEW IF EXISTS ValFromGeom + +DROP VIEW IF EXISTS GeogView + +DROP PROCEDURE IF EXISTS dbo.proc_getdata + +DROP FUNCTION IF EXISTS func_getval + DROP VIEW IF EXISTS point_distances_geog +DROP function IF EXISTS testspatial_tvf; + +DROP TABLE IF EXISTS SpatialData; + DROP TABLE IF EXISTS SPATIALPOINTGEOM_dt DROP TABLE IF EXISTS GeomToVarbinary @@ -45,3 +63,35 @@ DROP TABLE IF EXISTS GeogToVarchar 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 e644e6d4de..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~~ @@ -128,6 +173,14 @@ CREATE VIEW BinaryFromGeom AS SELECT STAsBinary(location) AS BinaryRepresentatio CREATE VIEW CoordsFromGeom AS SELECT STX(location), STY(location) AS Coordinates FROM SPATIALPOINTGEOM_dt; +CREATE VIEW GeomView AS SELECT location.STX, location.STY AS Coordinates FROM SPATIALPOINTGEOM_dt; + +CREATE VIEW ValFromGeom AS SELECT location.STAsText(), location.STAsBinary() FROM SPATIALPOINTGEOM_dt; + +CREATE FUNCTION f_getval() RETURNS TABLE AS RETURN ( SELECT location.STX AS XCoordinate, location.STY AS YCoordinate FROM SPATIALPOINTGEOM_dt ); + +CREATE PROCEDURE dbo.p_getcoordinates AS BEGIN DECLARE @Coordinates TABLE ( XCoordinate float, YCoordinate float ); INSERT INTO @Coordinates SELECT * FROM dbo.f_getval(); SELECT * FROM @Coordinates; END; + CREATE VIEW equal_geom AS SELECT p1.location AS point FROM SPATIALPOINTGEOM_dt p1 CROSS JOIN SPATIALPOINTGEOM_dt p2 WHERE p1.location = p2.location; CREATE VIEW point_distances_geom AS SELECT p1.location AS point1, p2.location AS point2, STDistance( p1.location, p2.location ) AS distance FROM SPATIALPOINTGEOM_dt p1 CROSS JOIN SPATIALPOINTGEOM_dt p2 WHERE p1.location <> p2.location; @@ -338,8 +391,13 @@ 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; + +CREATE FUNCTION func_getval() RETURNS TABLE AS RETURN ( SELECT location.STAsText() AS TextPoint FROM SPATIALPOINTGEOG_dt ); +CREATE PROCEDURE dbo.proc_getdata AS BEGIN DECLARE @Data TABLE ( TextPoint text ); INSERT INTO @Data SELECT * FROM dbo.func_getval(); SELECT * FROM @Data; END; CREATE VIEW TransformFromGeog AS SELECT ST_Transform(location, 4326) AS Modified_points FROM SPATIALPOINTGEOG_dt; @@ -347,6 +405,15 @@ CREATE VIEW equal_geog AS SELECT p1.location AS point FROM SPATIALPOINTGEOG_dt p CREATE VIEW point_distances_geog AS SELECT p1.location AS point1, p2.location AS point2, STDistance( p1.location, p2.location ) AS distance FROM SPATIALPOINTGEOG_dt p1 CROSS JOIN SPATIALPOINTGEOG_dt p2 WHERE p1.location <> p2.location; +CREATE TABLE SpatialData(ID INT PRIMARY KEY, SpatialLocation GEOGRAPHY); +INSERT INTO SpatialData (ID, SpatialLocation) VALUES (1, geography::Point(1, 2, 4326)), (2, geography::Point(3, 4, 4326)), (3, geography::Point(5, 6, 4326)), (4, geography::Point(7, 8, 4326)), (5, geography::Point(9, 10, 4326)); +~~ROW COUNT: 5~~ + + +create function testspatial_tvf(@x int) returns table as return select location from SPATIALPOINTGEOG_dt; + +CREATE TABLE babelfish_migration_mode_table (id_num INT IDENTITY(1,1), mig_mode VARCHAR(10)) + #Testing Implicit CASTs to and from Geography data type for supported Explicit CASTs #UnSupported CASTs to and from Geography data type CREATE TABLE GeogToVarbinary(p varbinary) diff --git a/test/JDBC/expected/TestSpatialPoint-vu-verify.out b/test/JDBC/expected/TestSpatialPoint-vu-verify.out index 9521a1164e..fbc3cf15dc 100644 --- a/test/JDBC/expected/TestSpatialPoint-vu-verify.out +++ b/test/JDBC/expected/TestSpatialPoint-vu-verify.out @@ -1,27 +1,61 @@ DECLARE @point geometry; SET @point = geometry::STPointFromText('POINT(-122.34900 47.65100)', 4326); SELECT STAsText(@point); +SELECT @point.STAsText(); Go ~~START~~ text POINT(-122.349 47.651) ~~END~~ +~~START~~ +text +POINT(-122.349 47.651) +~~END~~ + DECLARE @point geometry; SET @point = geometry::POINT(22.34900, -47.65100, 4326); SELECT STAsText(@point); +SELECT @point.STAsText(); Go ~~START~~ text POINT(22.349 -47.651) ~~END~~ +~~START~~ +text +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 STX(@point); +SELECT STY(@point); +SELECT @point.STX; +SELECT @point.STY; Go ~~START~~ float @@ -33,11 +67,23 @@ float 47.651 ~~END~~ +~~START~~ +float +-122.349 +~~END~~ + +~~START~~ +float +47.651 +~~END~~ + DECLARE @point geometry; SET @point = geometry::POINT(22.34900, -47.65100, 4326); -SELECT stx(@point); -SELECT sty(@point); +SELECT STX(@point); +SELECT STY(@point); +SELECT @point.STX; +SELECT @point.STY; Go ~~START~~ float @@ -49,17 +95,183 @@ float -47.651 ~~END~~ +~~START~~ +float +22.349 +~~END~~ + +~~START~~ +float +-47.651 +~~END~~ + DECLARE @point1 geometry, @point2 geometry; SET @point1 = geometry::STPointFromText('POINT(-122.34900 47.65100)', 4326); SET @point2 = geometry::STGeomFromText('POINT(-122.35000 47.65000)', 4326); SELECT STDistance(@point1, @point2); +SELECT @point1.STDistance(@point2); Go ~~START~~ float 0.0014142135623697993 ~~END~~ +~~START~~ +float +0.0014142135623697993 +~~END~~ + + +DECLARE @point geometry; +SET @point = geometry::STGeomFromText('POINT(-122.34900 47.65100)', 4326); +Insert INTO SPATIALPOINTGEOM_dt(location) VALUES(geometry::point(@point.STX, @point.STY,4326)) +go +~~ROW COUNT: 1~~ + + +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 +~~START~~ +float#!#float +-122.349#!#47.651 +~~END~~ + + +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 +~~START~~ +text#!#varbinary#!#float +POINT(-122.349 47.651)#!#01010000007593180456965EC017D9CEF753D34740#!#0.0 +~~END~~ + + +-- Null test for Geospatial functions +DECLARE @point1 geometry, @point2 geometry, @point3 geometry; +SET @point1 = geometry::STPointFromText(null, 4326); +SET @point2 = geometry::STGeomFromText(null, 4326); +SET @point3 = geometry::POINT(22.34900, -47.65100, 4326); +SELECT @point1.STX; +SELECT @point1.STY; +SELECT @point1.STAsText(); +SELECT @point1.STAsBinary(); +SELECT @point1.STDistance(@point2); +SELECT @point3.STDistance(@point2); +SELECT @point1.STDistance(@point3); +Go +~~START~~ +float + +~~END~~ + +~~START~~ +float + +~~END~~ + +~~START~~ +text + +~~END~~ + +~~START~~ +varbinary + +~~END~~ + +~~START~~ +float + +~~END~~ + +~~START~~ +float + +~~END~~ + +~~START~~ +float + +~~END~~ + + +-- Negative test for Geospatial functions +DECLARE @point1 geometry, @point2 varchar(50), @point3 int; +SET @point1 = geometry::POINT(22.34900, -47.65100, 4326);; +SET @point2 = 'Test_String'; +SELECT @point1.STDistance(@point2); +Go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + + +SELECT location.LAT from SPATIALPOINTGEOM_dt; +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: column notation .lat applied to type geometry, which is not a composite type)~~ + + +SELECT * FROM GeomView; +GO +~~START~~ +float#!#float +47.651#!#-22.349 +1.0#!#2.0 +47.651#!#-22.349 +#!# +47.651#!#-22.349 +1.0#!#2.0 +47.651#!#-22.349 +47.651#!#-22.349 +1.0#!#2.0 +47.651#!#-22.349 +-122.349#!#47.651 +~~END~~ + + +SELECT * FROM ValFromGeom; +GO +~~START~~ +text#!#varbinary +POINT(47.651 -22.349)#!#010100000017D9CEF753D34740D34D6210585936C0 +POINT(1 2)#!#0101000000000000000000F03F0000000000000040 +POINT(47.651 -22.349)#!#010100000017D9CEF753D34740D34D6210585936C0 +#!# +POINT(47.651 -22.349)#!#010100000017D9CEF753D34740D34D6210585936C0 +POINT(1 2)#!#0101000000000000000000F03F0000000000000040 +POINT(47.651 -22.349)#!#010100000017D9CEF753D34740D34D6210585936C0 +POINT(47.651 -22.349)#!#010100000017D9CEF753D34740D34D6210585936C0 +POINT(1 2)#!#0101000000000000000000F03F0000000000000040 +POINT(47.651 -22.349)#!#010100000017D9CEF753D34740D34D6210585936C0 +POINT(-122.349 47.651)#!#01010000007593180456965EC017D9CEF753D34740 +~~END~~ + + +EXEC dbo.p_getcoordinates; +GO +~~ROW COUNT: 11~~ + +~~START~~ +float#!#float +47.651#!#-22.349 +1.0#!#2.0 +47.651#!#-22.349 +#!# +47.651#!#-22.349 +1.0#!#2.0 +47.651#!#-22.349 +47.651#!#-22.349 +1.0#!#2.0 +47.651#!#-22.349 +-122.349#!#47.651 +~~END~~ + SELECT * FROM TextFromGeom; GO @@ -75,6 +287,7 @@ POINT(47.651 -22.349) POINT(47.651 -22.349) POINT(1 2) POINT(47.651 -22.349) +POINT(-122.349 47.651) ~~END~~ @@ -92,87 +305,990 @@ varbinary 010100000017D9CEF753D34740D34D6210585936C0 0101000000000000000000F03F0000000000000040 010100000017D9CEF753D34740D34D6210585936C0 +01010000007593180456965EC017D9CEF753D34740 +~~END~~ + + +SELECT * FROM CoordsFromGeom; +GO +~~START~~ +float#!#float +47.651#!#-22.349 +1.0#!#2.0 +47.651#!#-22.349 +#!# +47.651#!#-22.349 +1.0#!#2.0 +47.651#!#-22.349 +47.651#!#-22.349 +1.0#!#2.0 +47.651#!#-22.349 +-122.349#!#47.651 +~~END~~ + + +SELECT * FROM equal_geom; +GO +~~START~~ +geometry +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C000000000000F03F0000000000000040 +E6100000010C000000000000F03F0000000000000040 +E6100000010C000000000000F03F0000000000000040 +00000000010C17D9CEF753D34740D34D6210585936C0 +00000000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C000000000000F03F0000000000000040 +E6100000010C000000000000F03F0000000000000040 +E6100000010C000000000000F03F0000000000000040 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C000000000000F03F0000000000000040 +E6100000010C000000000000F03F0000000000000040 +E6100000010C000000000000F03F0000000000000040 +00000000010C17D9CEF753D34740D34D6210585936C0 +00000000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C7593180456965EC017D9CEF753D34740 +~~END~~ + + +SELECT * FROM point_distances_geom; +GO +~~START~~ +geometry#!#geometry#!#float +E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010C000000000000F03F0000000000000040#!#52.62309000809436 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: ST_Distance: Operation on mixed SRID geometries (Point, 4326) != (Point, 0))~~ + + +SELECT location.STX from SPATIALPOINTGEOM_dt; +GO +~~START~~ +float +47.651 +1.0 +47.651 + +47.651 +1.0 +47.651 +47.651 +1.0 +47.651 +-122.349 +~~END~~ + + +SELECT SPATIALPOINTGEOM_dt.location.STY from SPATIALPOINTGEOM_dt; +GO +~~START~~ +float +-22.349 +2.0 +-22.349 + +-22.349 +2.0 +-22.349 +-22.349 +2.0 +-22.349 +47.651 +~~END~~ + + +SELECT location.STAsText() from SPATIALPOINTGEOM_dt; +GO +~~START~~ +text +POINT(47.651 -22.349) +POINT(1 2) +POINT(47.651 -22.349) + +POINT(47.651 -22.349) +POINT(1 2) +POINT(47.651 -22.349) +POINT(47.651 -22.349) +POINT(1 2) +POINT(47.651 -22.349) +POINT(-122.349 47.651) +~~END~~ + + +SELECT location.STAsBinary() from SPATIALPOINTGEOM_dt; +GO +~~START~~ +varbinary +010100000017D9CEF753D34740D34D6210585936C0 +0101000000000000000000F03F0000000000000040 +010100000017D9CEF753D34740D34D6210585936C0 + +010100000017D9CEF753D34740D34D6210585936C0 +0101000000000000000000F03F0000000000000040 +010100000017D9CEF753D34740D34D6210585936C0 +010100000017D9CEF753D34740D34D6210585936C0 +0101000000000000000000F03F0000000000000040 +010100000017D9CEF753D34740D34D6210585936C0 +01010000007593180456965EC017D9CEF753D34740 +~~END~~ + + +SELECT location.STDistance(geometry::STGeomFromText('POINT(-122.34900 47.65100)', 4326)) from SPATIALPOINTGEOM_dt; +GO +~~START~~ +float +183.84776310850236 +131.52562336670374 +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: ST_Distance: Operation on mixed SRID geometries (Point, 4326) != (Point, 0))~~ + + +SELECT [SPATIALPOINTGEOM_dt].[location].[STX] from [SPATIALPOINTGEOM_dt]; +GO +~~START~~ +float +47.651 +1.0 +47.651 + +47.651 +1.0 +47.651 +47.651 +1.0 +47.651 +-122.349 +~~END~~ + + +SELECT [location].[STY] from [SPATIALPOINTGEOM_dt]; +GO +~~START~~ +float +-22.349 +2.0 +-22.349 + +-22.349 +2.0 +-22.349 +-22.349 +2.0 +-22.349 +47.651 +~~END~~ + + +SELECT location FROM SPATIALPOINTGEOM_dt; +GO +~~START~~ +geometry +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C000000000000F03F0000000000000040 +00000000010C17D9CEF753D34740D34D6210585936C0 + +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C000000000000F03F0000000000000040 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C17D9CEF753D34740D34D6210585936C0 +E6100000010C000000000000F03F0000000000000040 +00000000010C17D9CEF753D34740D34D6210585936C0 +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~~ -SELECT * FROM CoordsFromGeom; +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~~ -float#!#float -47.651#!#-22.349 -1.0#!#2.0 -47.651#!#-22.349 -#!# -47.651#!#-22.349 -1.0#!#2.0 -47.651#!#-22.349 -47.651#!#-22.349 -1.0#!#2.0 -47.651#!#-22.349 +int#!#float#!#text +1#!#0.0#!#Close +2#!#0.0#!#Close ~~END~~ -SELECT * FROM equal_geom; +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~~ -geometry -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C000000000000F03F0000000000000040 -E6100000010C000000000000F03F0000000000000040 -E6100000010C000000000000F03F0000000000000040 -00000000010C17D9CEF753D34740D34D6210585936C0 -00000000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C000000000000F03F0000000000000040 -E6100000010C000000000000F03F0000000000000040 -E6100000010C000000000000F03F0000000000000040 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C000000000000F03F0000000000000040 -E6100000010C000000000000F03F0000000000000040 -E6100000010C000000000000F03F0000000000000040 -00000000010C17D9CEF753D34740D34D6210585936C0 -00000000010C17D9CEF753D34740D34D6210585936C0 +float +0.0 +0.0 +~~END~~ + +~~START~~ +float +0.0 +0.0 ~~END~~ -SELECT * FROM point_distances_geom; +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +SELECT dbo.YourTable.PointColumn.STDistance(@referencePoint) AS Distance FROM YourTable; GO -~~START~~ -geometry#!#geometry#!#float -E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010C000000000000F03F0000000000000040#!#52.62309000809436 ~~ERROR (Code: 33557097)~~ -~~ERROR (Message: ST_Distance: Operation on mixed SRID geometries (Point, 4326) != (Point, 0))~~ +~~ERROR (Message: Remote procedure/function reference with 4-part object name is not currently supported in Babelfish)~~ -SELECT location FROM SPATIALPOINTGEOM_dt; +DECLARE @referencePoint geometry = geometry::Point(0.0, 0.0, 4326); +UPDATE YourTable SET PointColumn = @referencePoint +WHERE PointColumn.STDistance(@referencePoint) <= 2.0; GO -~~START~~ -geometry -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C000000000000F03F0000000000000040 -00000000010C17D9CEF753D34740D34D6210585936C0 - -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C000000000000F03F0000000000000040 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C17D9CEF753D34740D34D6210585936C0 -E6100000010C000000000000F03F0000000000000040 -00000000010C17D9CEF753D34740D34D6210585936C0 -~~END~~ +~~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 @@ -427,83 +1543,379 @@ GO ~~ERROR (Message: cannot cast type geography to geometry)~~ --- UnSupported CASTs which are currently supported for geometry --- This is because Image type is created as -> CREATE DOMAIN sys.IMAGE AS sys.BBF_VARBINARY; so it is always converted to it's baseType i.e. varbinary -Select CAST (geometry::STGeomFromText('POINT(1.0 2.0)', 4326) AS image) -GO +-- UnSupported CASTs which are currently supported for geometry +-- This is because Image type is created as -> CREATE DOMAIN sys.IMAGE AS sys.BBF_VARBINARY; so it is always converted to it's baseType i.e. varbinary +Select CAST (geometry::STGeomFromText('POINT(1.0 2.0)', 4326) AS image) +GO +~~START~~ +image +E6100000010C000000000000F03F0000000000000040 +~~END~~ + +Select CAST(CAST (0xE6100000010C17D9CEF753D34740D34D6210585936C0 AS image) as geometry) +GO +~~START~~ +geometry +E6100000010C17D9CEF753D34740D34D6210585936C0 +~~END~~ + + +DECLARE @point geography; +SET @point = geography::STGeomFromText('POINT(-122.34900 47.65100)', 4326); +SELECT STAsText(@point); +SELECT @point.STAsText(); +Go +~~START~~ +text +POINT(-122.349 47.651) +~~END~~ + +~~START~~ +text +POINT(-122.349 47.651) +~~END~~ + + +DECLARE @point geography; +SET @point = geography::POINT(22.34900, -47.65100, 4326); +SELECT STAsText(@point); +SELECT @point.STAsText(); +Go +~~START~~ +text +POINT(-47.651 22.349) +~~END~~ + +~~START~~ +text +POINT(-47.651 22.349) +~~END~~ + + +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; +Go +~~START~~ +float +-122.349 +~~END~~ + +~~START~~ +float +47.651 +~~END~~ + +~~START~~ +float +-122.349 +~~END~~ + +~~START~~ +float +47.651 +~~END~~ + + +DECLARE @point geography; +SET @point = geography::POINT(22.34900, -47.65100, 4326); +SELECT LONG(@point); +SELECT LAT(@point); +SELECT @point.LONG; +SELECT @point.LAT; +Go +~~START~~ +float +-47.651 +~~END~~ + +~~START~~ +float +22.349 +~~END~~ + +~~START~~ +float +-47.651 +~~END~~ + +~~START~~ +float +22.349 +~~END~~ + + +DECLARE @point1 geography, @point2 geography; +SET @point1 = geography::STPointFromText('POINT(-122.34900 47.65100)', 4326); +SET @point2 = geography::STGeomFromText('POINT(-122.35000 47.65000)', 4326); +SELECT STDistance(@point1, @point2); +SELECT @point1.STDistance(@point2); +Go +~~START~~ +float +134.1864008701007 +~~END~~ + +~~START~~ +float +134.1864008701007 +~~END~~ + + +DECLARE @point geography; +SET @point = geography::STGeomFromText('POINT(-22.34900 47.65100)', 4326); +Insert INTO SPATIALPOINTGEOG_dt(location) VALUES(geography::point(@point.LONG, @point.LAT, 4326)) +go +~~ROW COUNT: 1~~ + + +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 +~~START~~ +float#!#float +47.651#!#-22.349 +~~END~~ + + +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 +~~START~~ +text#!#varbinary#!#float +POINT(47.651 -22.349)#!#010100000017D9CEF753D34740D34D6210585936C0#!#0.0 +~~END~~ + + +SELECT + SpatialData.ID, + SPATIALPOINTGEOG_dt.location.LAT, + SpatialLocation.STDistance(SPATIALPOINTGEOG_dt.location) +FROM + SpatialData +JOIN + SPATIALPOINTGEOG_dt ON SPATIALPOINTGEOG_dt.location.LONG - SpatialData.SpatialLocation.LAT <= 10; +GO +~~START~~ +int#!#float#!#float +1#!#2.0#!#156876.14940188668 +2#!#2.0#!#351485.0664919168 +3#!#2.0#!#647017.0083805197 +4#!#2.0#!#953316.5401136167 +5#!#2.0#!#1261960.137843746 +1#!#2.0#!#156876.14940188668 +2#!#2.0#!#351485.0664919168 +3#!#2.0#!#647017.0083805197 +4#!#2.0#!#953316.5401136167 +5#!#2.0#!#1261960.137843746 +1#!#47.651#!#5678803.288585193 +2#!#47.651#!#5557193.284430087 +3#!#47.651#!#5446042.320579326 +4#!#47.651#!#5345543.26741007 +5#!#47.651#!#5255813.671417903 +1#!#2.0#!#156876.14940188668 +2#!#2.0#!#351485.0664919168 +3#!#2.0#!#647017.0083805197 +4#!#2.0#!#953316.5401136167 +5#!#2.0#!#1261960.137843746 +~~END~~ + + +WITH RegionLocations AS ( + SELECT + SpatialData.ID, + SPATIALPOINTGEOG_dt.location.LAT + FROM + SpatialData + JOIN + SPATIALPOINTGEOG_dt ON SPATIALPOINTGEOG_dt.location.LONG - SpatialData.SpatialLocation.LAT <= 10 +) +SELECT + LAT, + COUNT(ID) AS LocationCount +FROM + RegionLocations +GROUP BY + LAT; +GO +~~START~~ +float#!#int +47.651#!#5 +2.0#!#15 +~~END~~ + + +-- 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; +go +~~START~~ +text +POINT(47.651 -22.349) +POINT(1 2) +POINT(1 2) +POINT(1 2) +POINT(1 2) +POINT(47.651 -22.349) +POINT(1 2) +POINT(1 2) +POINT(1 2) +POINT(1 2) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(47.651 -22.349) +POINT(1 2) +POINT(1 2) +POINT(1 2) +POINT(1 2) +POINT(47.651 -22.349) +~~END~~ + + +-- Test with tvf +select f.STAsText() + from testspatial_tvf(1) f inner join SPATIALPOINTGEOG_dt t on f.location.LAT >= t.location.LONG; +go +~~START~~ +text +POINT(47.651 -22.349) +POINT(1 2) +POINT(1 2) +POINT(1 2) +POINT(1 2) +POINT(47.651 -22.349) +POINT(1 2) +POINT(1 2) +POINT(1 2) +POINT(1 2) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(-22.349 47.651) +POINT(47.651 -22.349) +POINT(1 2) +POINT(1 2) +POINT(1 2) +POINT(1 2) +POINT(47.651 -22.349) +~~END~~ + + +-- Null test for Geospatial functions +DECLARE @point1 geography, @point2 geography, @point3 geography; +SET @point1 = geography::STPointFromText(null, 4326); +SET @point2 = geography::STGeomFromText(null, 4326); +SET @point3 = geography::POINT(22.34900, -47.65100, 4326); +SELECT @point1.LONG; +SELECT @point1.LAT; +SELECT @point1.STAsText(); +SELECT @point1.STAsBinary(); +SELECT @point1.STDistance(@point2); +SELECT @point3.STDistance(@point2); +SELECT @point1.STDistance(@point3); +Go ~~START~~ -image -E6100000010C000000000000F03F0000000000000040 +float + ~~END~~ -Select CAST(CAST (0xE6100000010C17D9CEF753D34740D34D6210585936C0 AS image) as geometry) -GO ~~START~~ -geometry -E6100000010C17D9CEF753D34740D34D6210585936C0 +float + ~~END~~ - -DECLARE @point geography; -SET @point = geography::STGeomFromText('POINT(-122.34900 47.65100)', 4326); -SELECT STAsText(@point); -Go ~~START~~ text -POINT(-122.349 47.651) + ~~END~~ - -DECLARE @point geography; -SET @point = geography::POINT(22.34900, -47.65100, 4326); -SELECT STAsText(@point); -Go ~~START~~ -text -POINT(-47.651 22.349) +varbinary + ~~END~~ - -DECLARE @point geography; -SET @point = geography::STPointFromText('POINT(-122.34900 47.65100)', 4326); -SELECT long(@point); -SELECT lat(@point); -Go ~~START~~ float --122.349 + ~~END~~ ~~START~~ float -47.651 + ~~END~~ - -DECLARE @point geography; -SET @point = geography::POINT(22.34900, -47.65100, 4326); -SELECT long(@point); -SELECT lat(@point); -Go ~~START~~ float --47.651 + ~~END~~ + +-- Negative test for Geospatial functions +DECLARE @point1 geography, @point2 varchar(50), @point3 int; +SET @point1 = geography::POINT(22.34900, -47.65100, 4326); +SET @point2 = 'Test_String'; +SELECT @point2.STDistance(@point1); +Go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + + +SELECT location.STY from SPATIALPOINTGEOG_dt; +GO +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: column notation .sty applied to type geography, which is not a composite type)~~ + + +SELECT * FROM GeogView; +GO ~~START~~ -float -22.349 +float#!#float +47.651#!#-22.349 +1.0#!#2.0 +#!# +47.651#!#-22.349 +1.0#!#2.0 +-22.349#!#47.651 +47.651#!#-22.349 +1.0#!#2.0 +47.651#!#-22.349 ~~END~~ -DECLARE @point1 geography, @point2 geography; -SET @point1 = geography::STPointFromText('POINT(-122.34900 47.65100)', 4326); -SET @point2 = geography::STGeomFromText('POINT(-122.35000 47.65000)', 4326); -SELECT STDistance(@point1, @point2); -Go +EXEC dbo.proc_getdata; +GO +~~ROW COUNT: 9~~ + ~~START~~ -float -134.1864008701007 +text +POINT(47.651 -22.349) +POINT(1 2) + +POINT(47.651 -22.349) +POINT(1 2) +POINT(-22.349 47.651) +POINT(47.651 -22.349) +POINT(1 2) +POINT(47.651 -22.349) ~~END~~ @@ -519,6 +1931,7 @@ POINT(1 2) POINT(-22.349 47.651) POINT(47.651 -22.349) POINT(1 2) +POINT(47.651 -22.349) ~~END~~ @@ -534,6 +1947,7 @@ varbinary 0101000000D34D6210585936C017D9CEF753D34740 010100000017D9CEF753D34740D34D6210585936C0 0101000000000000000000F03F0000000000000040 +010100000017D9CEF753D34740D34D6210585936C0 ~~END~~ @@ -549,6 +1963,7 @@ float#!#float -22.349#!#47.651 47.651#!#-22.349 1.0#!#2.0 +47.651#!#-22.349 ~~END~~ @@ -564,6 +1979,7 @@ E6100000010C0000000000000040000000000000F03F E6100000010C17D9CEF753D34740D34D6210585936C0 E6100000010CD34D6210585936C017D9CEF753D34740 E6100000010C0000000000000040000000000000F03F +E6100000010CD34D6210585936C017D9CEF753D34740 ~~END~~ @@ -574,12 +1990,14 @@ geography E6100000010CD34D6210585936C017D9CEF753D34740 E6100000010CD34D6210585936C017D9CEF753D34740 E6100000010CD34D6210585936C017D9CEF753D34740 +E6100000010CD34D6210585936C017D9CEF753D34740 E6100000010C0000000000000040000000000000F03F E6100000010C0000000000000040000000000000F03F E6100000010C0000000000000040000000000000F03F E6100000010CD34D6210585936C017D9CEF753D34740 E6100000010CD34D6210585936C017D9CEF753D34740 E6100000010CD34D6210585936C017D9CEF753D34740 +E6100000010CD34D6210585936C017D9CEF753D34740 E6100000010C0000000000000040000000000000F03F E6100000010C0000000000000040000000000000F03F E6100000010C0000000000000040000000000000F03F @@ -587,9 +2005,14 @@ E6100000010C17D9CEF753D34740D34D6210585936C0 E6100000010CD34D6210585936C017D9CEF753D34740 E6100000010CD34D6210585936C017D9CEF753D34740 E6100000010CD34D6210585936C017D9CEF753D34740 +E6100000010CD34D6210585936C017D9CEF753D34740 E6100000010C0000000000000040000000000000F03F E6100000010C0000000000000040000000000000F03F E6100000010C0000000000000040000000000000F03F +E6100000010CD34D6210585936C017D9CEF753D34740 +E6100000010CD34D6210585936C017D9CEF753D34740 +E6100000010CD34D6210585936C017D9CEF753D34740 +E6100000010CD34D6210585936C017D9CEF753D34740 ~~END~~ @@ -605,6 +2028,7 @@ E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9C E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 E6100000010C0000000000000040000000000000F03F#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!#5535965.307328846 E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 +E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!#1.04243622548279E7 @@ -613,12 +2037,14 @@ E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9C E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 E6100000010C0000000000000040000000000000F03F#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!#5535965.307328846 E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 +E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#1.04243622548279E7 E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010C0000000000000040000000000000F03F#!#5535965.307328846 E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#1.04243622548279E7 E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010C0000000000000040000000000000F03F#!#5535965.307328846 E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#1.04243622548279E7 E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010C0000000000000040000000000000F03F#!#5535965.307328846 +E6100000010C17D9CEF753D34740D34D6210585936C0#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#1.04243622548279E7 E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!#1.04243622548279E7 @@ -627,6 +2053,123 @@ E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9C E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 E6100000010C0000000000000040000000000000F03F#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!#5535965.307328846 E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 +E6100000010C0000000000000040000000000000F03F#!#E6100000010CD34D6210585936C017D9CEF753D34740#!#5736178.674863189 +E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 +E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 +E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C17D9CEF753D34740D34D6210585936C0#!#1.04243622548279E7 +E6100000010CD34D6210585936C017D9CEF753D34740#!#E6100000010C0000000000000040000000000000F03F#!#5736178.674863189 +~~END~~ + + +SELECT location.LAT from SPATIALPOINTGEOG_dt; +GO +~~START~~ +float +-22.349 +2.0 + +-22.349 +2.0 +47.651 +-22.349 +2.0 +-22.349 +~~END~~ + + +SELECT SPATIALPOINTGEOG_dt.location.LONG from SPATIALPOINTGEOG_dt; +GO +~~START~~ +float +47.651 +1.0 + +47.651 +1.0 +-22.349 +47.651 +1.0 +47.651 +~~END~~ + + +SELECT location.STAsText() from SPATIALPOINTGEOG_dt; +GO +~~START~~ +text +POINT(47.651 -22.349) +POINT(1 2) + +POINT(47.651 -22.349) +POINT(1 2) +POINT(-22.349 47.651) +POINT(47.651 -22.349) +POINT(1 2) +POINT(47.651 -22.349) +~~END~~ + + +SELECT location.STAsBinary() from SPATIALPOINTGEOG_dt; +GO +~~START~~ +varbinary +010100000017D9CEF753D34740D34D6210585936C0 +0101000000000000000000F03F0000000000000040 + +010100000017D9CEF753D34740D34D6210585936C0 +0101000000000000000000F03F0000000000000040 +0101000000D34D6210585936C017D9CEF753D34740 +010100000017D9CEF753D34740D34D6210585936C0 +0101000000000000000000F03F0000000000000040 +010100000017D9CEF753D34740D34D6210585936C0 +~~END~~ + + +SELECT location.STDistance(geography::STGeomFromText('POINT(-122.34900 47.65100)', 4326)) from SPATIALPOINTGEOG_dt; +GO +~~START~~ +float +1.7059874617785625E7 +1.2255731559616795E7 + +1.7059874617785625E7 +1.2255731559616795E7 +6929242.948674276 +1.7059874617785625E7 +1.2255731559616795E7 +1.7059874617785625E7 +~~END~~ + + +SELECT [SPATIALPOINTGEOG_dt].[location].[LONG] from [SPATIALPOINTGEOG_dt]; +GO +~~START~~ +float +47.651 +1.0 + +47.651 +1.0 +-22.349 +47.651 +1.0 +47.651 +~~END~~ + + +SELECT [location].[LAT] from [SPATIALPOINTGEOG_dt]; +GO +~~START~~ +float +-22.349 +2.0 + +-22.349 +2.0 +47.651 +-22.349 +2.0 +-22.349 ~~END~~ @@ -642,6 +2185,7 @@ E6100000010C0000000000000040000000000000F03F E6100000010C17D9CEF753D34740D34D6210585936C0 E6100000010CD34D6210585936C017D9CEF753D34740 E6100000010C0000000000000040000000000000F03F +E6100000010CD34D6210585936C017D9CEF753D34740 ~~END~~ @@ -892,6 +2436,48 @@ E6100000010C17D9CEF753D34740D34D6210585936C0 ~~END~~ +SELECT + GeomColumn.STX AS XCoordinate, + GeomColumn.STY AS YCoordinate, + PrimaryKey, + GeogColumn.STDistance(geography::Point(7, 8, 4326)) AS DistanceToFixedPoint +FROM + SPATIALPOINT_dt; +GO +~~START~~ +float#!#float#!#int#!#float +47.651#!#-22.349#!#1#!# +#!##!#2#!#5405374.929245813 +1.0#!#2.0#!#3#!#953316.5401136167 +47.651#!#-22.349#!#4#!# +#!##!#5#!#5405374.929245813 +1.0#!#2.0#!#6#!#953316.5401136167 +~~END~~ + + +DECLARE @sql NVARCHAR(MAX); +SET @sql = + N'SELECT ' + + N'GeomColumn.STX AS XCoordinate, ' + + N'GeomColumn.STY AS YCoordinate, ' + + N'PrimaryKey, ' + + N'GeogColumn.STDistance(geography::Point(7, 8, 4326)) AS DistanceToFixedPoint ' + + N'FROM SPATIALPOINT_dt'; + +-- Execute the dynamic SQL +EXEC sp_executesql @sql; +GO +~~START~~ +float#!#float#!#int#!#float +47.651#!#-22.349#!#1#!# +#!##!#2#!#5405374.929245813 +1.0#!#2.0#!#3#!#953316.5401136167 +47.651#!#-22.349#!#4#!# +#!##!#5#!#5405374.929245813 +1.0#!#2.0#!#6#!#953316.5401136167 +~~END~~ + + SELECT * FROM SPATIALPOINT_dt; GO ~~START~~ @@ -904,3 +2490,123 @@ int#!#geometry#!#geography 6#!#E6100000010C000000000000F03F0000000000000040#!#E6100000010C0000000000000040000000000000F03F ~~END~~ + +INSERT INTO babelfish_migration_mode_table SELECT current_setting('babelfishpg_tsql.migration_mode') +GO +~~ROW COUNT: 1~~ + + +-- test multi-db mode +SELECT set_config('role', 'jdbc_user', false); +GO +~~START~~ +text +jdbc_user +~~END~~ + +SELECT set_config('babelfishpg_tsql.migration_mode', 'multi-db', false); +GO +~~START~~ +text +multi-db +~~END~~ + + +CREATE DATABASE db1; +GO + +CREATE DATABASE db2; +GO + +USE db1; +GO + +CREATE TABLE SpatialData +( + SpatialPoint GEOMETRY, + PrimaryKey INT +); +GO + +INSERT INTO SpatialData (SpatialPoint, PrimaryKey) +VALUES + (geometry::Point(1, 2, 0), 1), + (geometry::Point(3, 4, 0), 2), + (geometry::Point(5, 6, 0), 3); +GO +~~ROW COUNT: 3~~ + + +USE db2; +GO + +CREATE TABLE SpatialData +( + SpatialPoint GEOMETRY, + PrimaryKey INT +); +GO + +INSERT INTO SpatialData (SpatialPoint, PrimaryKey) +VALUES + (geometry::Point(7, 8, 0), 4), + (geometry::Point(9, 10, 0), 5), + (geometry::Point(11, 12, 0), 6); +GO +~~ROW COUNT: 3~~ + + +DECLARE @sql NVARCHAR(MAX); +SET @sql = + N'SELECT ' + + N'[SpatialPoint].[STX] AS XCoordinate, ' + + N'[SpatialPoint].[STY] AS YCoordinate, ' + + N'[PrimaryKey] ' + + N'FROM [db1].[dbo].[SpatialData] ' + + N'UNION ALL ' + + N'SELECT ' + + N'[SpatialPoint].[STX] AS XCoordinate, ' + + N'[SpatialPoint].[STY] AS YCoordinate, ' + + N'[PrimaryKey] ' + + N'FROM [db2].[dbo].[SpatialData]'; +-- Execute the dynamic SQL +EXEC sp_executesql @sql; +GO +~~START~~ +float#!#float#!#int +1.0#!#2.0#!#1 +3.0#!#4.0#!#2 +5.0#!#6.0#!#3 +7.0#!#8.0#!#4 +9.0#!#10.0#!#5 +11.0#!#12.0#!#6 +~~END~~ + + +USE master +GO + +DROP DATABASE db1; +GO + +DROP DATABASE db2; +GO + +SELECT set_config('role', 'jdbc_user', false); +GO +~~START~~ +text +jdbc_user +~~END~~ + + +-- Reset migration mode to default +DECLARE @mig_mode VARCHAR(10) +SET @mig_mode = (SELECT mig_mode FROM babelfish_migration_mode_table WHERE id_num = 1) +SELECT CASE WHEN (SELECT set_config('babelfishpg_tsql.migration_mode', @mig_mode, false)) IS NOT NULL THEN 1 ELSE 0 END +GO +~~START~~ +int +1 +~~END~~ + diff --git a/test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.txt b/test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.txt index cfd1c8615f..97bad2cc34 100644 --- a/test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.txt +++ b/test/JDBC/input/datatypes/TestSpatialPoint-vu-cleanup.txt @@ -18,8 +18,26 @@ DROP VIEW IF EXISTS TransformFromGeog DROP VIEW IF EXISTS equal_geog +DROP VIEW IF EXISTS GeomView + +DROP PROCEDURE IF EXISTS dbo.p_getcoordinates + +DROP FUNCTION IF EXISTS f_getval + +DROP VIEW IF EXISTS ValFromGeom + +DROP VIEW IF EXISTS GeogView + +DROP PROCEDURE IF EXISTS dbo.proc_getdata + +DROP FUNCTION IF EXISTS func_getval + DROP VIEW IF EXISTS point_distances_geog +DROP function IF EXISTS testspatial_tvf; + +DROP TABLE IF EXISTS SpatialData; + DROP TABLE IF EXISTS SPATIALPOINTGEOM_dt DROP TABLE IF EXISTS GeomToVarbinary @@ -45,3 +63,35 @@ DROP TABLE IF EXISTS GeogToVarchar 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 67f3e3419f..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 @@ -64,6 +99,14 @@ CREATE VIEW BinaryFromGeom AS SELECT STAsBinary(location) AS BinaryRepresentatio CREATE VIEW CoordsFromGeom AS SELECT STX(location), STY(location) AS Coordinates FROM SPATIALPOINTGEOM_dt; +CREATE VIEW GeomView AS SELECT location.STX, location.STY AS Coordinates FROM SPATIALPOINTGEOM_dt; + +CREATE VIEW ValFromGeom AS SELECT location.STAsText(), location.STAsBinary() FROM SPATIALPOINTGEOM_dt; + +CREATE FUNCTION f_getval() RETURNS TABLE AS RETURN ( SELECT location.STX AS XCoordinate, location.STY AS YCoordinate FROM SPATIALPOINTGEOM_dt ); + +CREATE PROCEDURE dbo.p_getcoordinates AS BEGIN DECLARE @Coordinates TABLE ( XCoordinate float, YCoordinate float ); INSERT INTO @Coordinates SELECT * FROM dbo.f_getval(); SELECT * FROM @Coordinates; END; + CREATE VIEW equal_geom AS SELECT p1.location AS point FROM SPATIALPOINTGEOM_dt p1 CROSS JOIN SPATIALPOINTGEOM_dt p2 WHERE p1.location = p2.location; CREATE VIEW point_distances_geom AS SELECT p1.location AS point1, p2.location AS point2, STDistance( p1.location, p2.location ) AS distance FROM SPATIALPOINTGEOM_dt p1 CROSS JOIN SPATIALPOINTGEOM_dt p2 WHERE p1.location <> p2.location; @@ -166,8 +209,13 @@ 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; + +CREATE FUNCTION func_getval() RETURNS TABLE AS RETURN ( SELECT location.STAsText() AS TextPoint FROM SPATIALPOINTGEOG_dt ); +CREATE PROCEDURE dbo.proc_getdata AS BEGIN DECLARE @Data TABLE ( TextPoint text ); INSERT INTO @Data SELECT * FROM dbo.func_getval(); SELECT * FROM @Data; END; CREATE VIEW TransformFromGeog AS SELECT ST_Transform(location, 4326) AS Modified_points FROM SPATIALPOINTGEOG_dt; @@ -175,6 +223,13 @@ CREATE VIEW equal_geog AS SELECT p1.location AS point FROM SPATIALPOINTGEOG_dt p CREATE VIEW point_distances_geog AS SELECT p1.location AS point1, p2.location AS point2, STDistance( p1.location, p2.location ) AS distance FROM SPATIALPOINTGEOG_dt p1 CROSS JOIN SPATIALPOINTGEOG_dt p2 WHERE p1.location <> p2.location; +CREATE TABLE SpatialData(ID INT PRIMARY KEY, SpatialLocation GEOGRAPHY); +INSERT INTO SpatialData (ID, SpatialLocation) VALUES (1, geography::Point(1, 2, 4326)), (2, geography::Point(3, 4, 4326)), (3, geography::Point(5, 6, 4326)), (4, geography::Point(7, 8, 4326)), (5, geography::Point(9, 10, 4326)); + +create function testspatial_tvf(@x int) returns table as return select location from SPATIALPOINTGEOG_dt; + +CREATE TABLE babelfish_migration_mode_table (id_num INT IDENTITY(1,1), mig_mode VARCHAR(10)) + #Testing Implicit CASTs to and from Geography data type for supported Explicit CASTs #UnSupported CASTs to and from Geography data type CREATE TABLE GeogToVarbinary(p varbinary) diff --git a/test/JDBC/input/datatypes/TestSpatialPoint-vu-verify.sql b/test/JDBC/input/datatypes/TestSpatialPoint-vu-verify.sql index 239f4e93ad..340e5d5afa 100644 --- a/test/JDBC/input/datatypes/TestSpatialPoint-vu-verify.sql +++ b/test/JDBC/input/datatypes/TestSpatialPoint-vu-verify.sql @@ -1,31 +1,96 @@ DECLARE @point geometry; SET @point = geometry::STPointFromText('POINT(-122.34900 47.65100)', 4326); SELECT STAsText(@point); +SELECT @point.STAsText(); Go DECLARE @point geometry; SET @point = geometry::POINT(22.34900, -47.65100, 4326); 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 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 STX(@point); +SELECT STY(@point); +SELECT @point.STX; +SELECT @point.STY; Go DECLARE @point1 geometry, @point2 geometry; SET @point1 = geometry::STPointFromText('POINT(-122.34900 47.65100)', 4326); SET @point2 = geometry::STGeomFromText('POINT(-122.35000 47.65000)', 4326); SELECT STDistance(@point1, @point2); +SELECT @point1.STDistance(@point2); +Go + +DECLARE @point geometry; +SET @point = geometry::STGeomFromText('POINT(-122.34900 47.65100)', 4326); +Insert INTO SPATIALPOINTGEOM_dt(location) VALUES(geometry::point(@point.STX, @point.STY,4326)) +go + +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 + +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 + +-- Null test for Geospatial functions +DECLARE @point1 geometry, @point2 geometry, @point3 geometry; +SET @point1 = geometry::STPointFromText(null, 4326); +SET @point2 = geometry::STGeomFromText(null, 4326); +SET @point3 = geometry::POINT(22.34900, -47.65100, 4326); +SELECT @point1.STX; +SELECT @point1.STY; +SELECT @point1.STAsText(); +SELECT @point1.STAsBinary(); +SELECT @point1.STDistance(@point2); +SELECT @point3.STDistance(@point2); +SELECT @point1.STDistance(@point3); Go +-- Negative test for Geospatial functions +DECLARE @point1 geometry, @point2 varchar(50), @point3 int; +SET @point1 = geometry::POINT(22.34900, -47.65100, 4326);; +SET @point2 = 'Test_String'; +SELECT @point1.STDistance(@point2); +Go + +SELECT location.LAT from SPATIALPOINTGEOM_dt; +GO + +SELECT * FROM GeomView; +GO + +SELECT * FROM ValFromGeom; +GO + +EXEC dbo.p_getcoordinates; +GO + SELECT * FROM TextFromGeom; GO @@ -41,9 +106,406 @@ GO SELECT * FROM point_distances_geom; GO +SELECT location.STX from SPATIALPOINTGEOM_dt; +GO + +SELECT SPATIALPOINTGEOM_dt.location.STY from SPATIALPOINTGEOM_dt; +GO + +SELECT location.STAsText() from SPATIALPOINTGEOM_dt; +GO + +SELECT location.STAsBinary() from SPATIALPOINTGEOM_dt; +GO + +SELECT location.STDistance(geometry::STGeomFromText('POINT(-122.34900 47.65100)', 4326)) from SPATIALPOINTGEOM_dt; +GO + +SELECT [SPATIALPOINTGEOM_dt].[location].[STX] from [SPATIALPOINTGEOM_dt]; +GO + +SELECT [location].[STY] from [SPATIALPOINTGEOM_dt]; +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; @@ -139,31 +601,123 @@ GO DECLARE @point geography; SET @point = geography::STGeomFromText('POINT(-122.34900 47.65100)', 4326); SELECT STAsText(@point); +SELECT @point.STAsText(); Go DECLARE @point geography; SET @point = geography::POINT(22.34900, -47.65100, 4326); SELECT STAsText(@point); +SELECT @point.STAsText(); Go DECLARE @point geography; SET @point = geography::STPointFromText('POINT(-122.34900 47.65100)', 4326); -SELECT long(@point); -SELECT lat(@point); +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 LONG(@point); +SELECT LAT(@point); +SELECT @point.LONG; +SELECT @point.LAT; Go DECLARE @point1 geography, @point2 geography; SET @point1 = geography::STPointFromText('POINT(-122.34900 47.65100)', 4326); SET @point2 = geography::STGeomFromText('POINT(-122.35000 47.65000)', 4326); SELECT STDistance(@point1, @point2); +SELECT @point1.STDistance(@point2); Go +DECLARE @point geography; +SET @point = geography::STGeomFromText('POINT(-22.34900 47.65100)', 4326); +Insert INTO SPATIALPOINTGEOG_dt(location) VALUES(geography::point(@point.LONG, @point.LAT, 4326)) +go + +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 + +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 + +SELECT + SpatialData.ID, + SPATIALPOINTGEOG_dt.location.LAT, + SpatialLocation.STDistance(SPATIALPOINTGEOG_dt.location) +FROM + SpatialData +JOIN + SPATIALPOINTGEOG_dt ON SPATIALPOINTGEOG_dt.location.LONG - SpatialData.SpatialLocation.LAT <= 10; +GO + +WITH RegionLocations AS ( + SELECT + SpatialData.ID, + SPATIALPOINTGEOG_dt.location.LAT + FROM + SpatialData + JOIN + SPATIALPOINTGEOG_dt ON SPATIALPOINTGEOG_dt.location.LONG - SpatialData.SpatialLocation.LAT <= 10 +) +SELECT + LAT, + COUNT(ID) AS LocationCount +FROM + RegionLocations +GROUP BY + 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; +go + +-- Test with tvf +select f.STAsText() + from testspatial_tvf(1) f inner join SPATIALPOINTGEOG_dt t on f.location.LAT >= t.location.LONG; +go + +-- Null test for Geospatial functions +DECLARE @point1 geography, @point2 geography, @point3 geography; +SET @point1 = geography::STPointFromText(null, 4326); +SET @point2 = geography::STGeomFromText(null, 4326); +SET @point3 = geography::POINT(22.34900, -47.65100, 4326); +SELECT @point1.LONG; +SELECT @point1.LAT; +SELECT @point1.STAsText(); +SELECT @point1.STAsBinary(); +SELECT @point1.STDistance(@point2); +SELECT @point3.STDistance(@point2); +SELECT @point1.STDistance(@point3); +Go + +-- Negative test for Geospatial functions +DECLARE @point1 geography, @point2 varchar(50), @point3 int; +SET @point1 = geography::POINT(22.34900, -47.65100, 4326); +SET @point2 = 'Test_String'; +SELECT @point2.STDistance(@point1); +Go + +SELECT location.STY from SPATIALPOINTGEOG_dt; +GO + +SELECT * FROM GeogView; +GO + +EXEC dbo.proc_getdata; +GO + SELECT * FROM TextFromGeog; GO @@ -182,6 +736,27 @@ GO SELECT * FROM point_distances_geog; GO +SELECT location.LAT from SPATIALPOINTGEOG_dt; +GO + +SELECT SPATIALPOINTGEOG_dt.location.LONG from SPATIALPOINTGEOG_dt; +GO + +SELECT location.STAsText() from SPATIALPOINTGEOG_dt; +GO + +SELECT location.STAsBinary() from SPATIALPOINTGEOG_dt; +GO + +SELECT location.STDistance(geography::STGeomFromText('POINT(-122.34900 47.65100)', 4326)) from SPATIALPOINTGEOG_dt; +GO + +SELECT [SPATIALPOINTGEOG_dt].[location].[LONG] from [SPATIALPOINTGEOG_dt]; +GO + +SELECT [location].[LAT] from [SPATIALPOINTGEOG_dt]; +GO + SELECT location FROM SPATIALPOINTGEOG_dt; GO @@ -268,5 +843,111 @@ GO Select CAST(CAST (0xE6100000010C17D9CEF753D34740D34D6210585936C0 AS image) as geography) GO +SELECT + GeomColumn.STX AS XCoordinate, + GeomColumn.STY AS YCoordinate, + PrimaryKey, + GeogColumn.STDistance(geography::Point(7, 8, 4326)) AS DistanceToFixedPoint +FROM + SPATIALPOINT_dt; +GO + +DECLARE @sql NVARCHAR(MAX); +SET @sql = + N'SELECT ' + + N'GeomColumn.STX AS XCoordinate, ' + + N'GeomColumn.STY AS YCoordinate, ' + + N'PrimaryKey, ' + + N'GeogColumn.STDistance(geography::Point(7, 8, 4326)) AS DistanceToFixedPoint ' + + N'FROM SPATIALPOINT_dt'; + +-- Execute the dynamic SQL +EXEC sp_executesql @sql; +GO + SELECT * FROM SPATIALPOINT_dt; GO + +INSERT INTO babelfish_migration_mode_table SELECT current_setting('babelfishpg_tsql.migration_mode') +GO + +-- test multi-db mode +SELECT set_config('role', 'jdbc_user', false); +GO +SELECT set_config('babelfishpg_tsql.migration_mode', 'multi-db', false); +GO + +CREATE DATABASE db1; +GO + +CREATE DATABASE db2; +GO + +USE db1; +GO + +CREATE TABLE SpatialData +( + SpatialPoint GEOMETRY, + PrimaryKey INT +); +GO + +INSERT INTO SpatialData (SpatialPoint, PrimaryKey) +VALUES + (geometry::Point(1, 2, 0), 1), + (geometry::Point(3, 4, 0), 2), + (geometry::Point(5, 6, 0), 3); +GO + +USE db2; +GO + +CREATE TABLE SpatialData +( + SpatialPoint GEOMETRY, + PrimaryKey INT +); +GO + +INSERT INTO SpatialData (SpatialPoint, PrimaryKey) +VALUES + (geometry::Point(7, 8, 0), 4), + (geometry::Point(9, 10, 0), 5), + (geometry::Point(11, 12, 0), 6); +GO + +DECLARE @sql NVARCHAR(MAX); +SET @sql = + N'SELECT ' + + N'[SpatialPoint].[STX] AS XCoordinate, ' + + N'[SpatialPoint].[STY] AS YCoordinate, ' + + N'[PrimaryKey] ' + + N'FROM [db1].[dbo].[SpatialData] ' + + N'UNION ALL ' + + N'SELECT ' + + N'[SpatialPoint].[STX] AS XCoordinate, ' + + N'[SpatialPoint].[STY] AS YCoordinate, ' + + N'[PrimaryKey] ' + + N'FROM [db2].[dbo].[SpatialData]'; +-- Execute the dynamic SQL +EXEC sp_executesql @sql; +GO + +USE master +GO + +DROP DATABASE db1; +GO + +DROP DATABASE db2; +GO + +SELECT set_config('role', 'jdbc_user', false); +GO + +-- Reset migration mode to default +DECLARE @mig_mode VARCHAR(10) +SET @mig_mode = (SELECT mig_mode FROM babelfish_migration_mode_table WHERE id_num = 1) +SELECT CASE WHEN (SELECT set_config('babelfishpg_tsql.migration_mode', @mig_mode, false)) IS NOT NULL THEN 1 ELSE 0 END +GO diff --git a/test/JDBC/upgrade/15_5/schedule b/test/JDBC/upgrade/15_5/schedule index bca9049fa1..256a6ca05f 100644 --- a/test/JDBC/upgrade/15_5/schedule +++ b/test/JDBC/upgrade/15_5/schedule @@ -420,7 +420,6 @@ TestRowVersion TestSmallDatetime TestSmallInt TestSmallMoney -TestSpatialPoint Test-sp_addrole Test-sp_addrolemember Test-sp_babelfish_volatility diff --git a/test/dotnet/ExpectedOutput/TestPoint.out b/test/dotnet/ExpectedOutput/TestPoint.out index 402c335bfc..c7e7391911 100644 --- a/test/dotnet/ExpectedOutput/TestPoint.out +++ b/test/dotnet/ExpectedOutput/TestPoint.out @@ -24,7 +24,7 @@ #Q#INSERT INTO POINTGEOG_dt(location) values(geography::STGeomFromText('Point(47.65100 -22.34900)', 4326)) #Q#INSERT INTO POINTGEOG_dt(location) values(geography::STPointFromText('Point(47.65100 -22.34900)', 4326)) #Q#INSERT INTO POINTGEOG_dt(location) values(geography::Point(47.65100, -22.34900, 4326)) -#Q#SELECT STAsText(location) FROM POINTGEOM_dt; +#Q#SELECT location.STAsText() FROM POINTGEOM_dt; #D#text POINT(47.651 -22.349) POINT(1 2) @@ -33,14 +33,14 @@ POINT(47.651 -22.349) POINT(47.651 -22.349) POINT(47.651 -22.349) POINT(47.651 -22.349) -#Q#SELECT STAsText(location) FROM POINTGEOG_dt; +#Q#SELECT location.STAsText() FROM POINTGEOG_dt; #D#text POINT(47.651 -22.349) POINT(1 2) POINT(47.651 -22.349) POINT(47.651 -22.349) POINT(-22.349 47.651) -#Q#SELECT STAsText(geom), STAsText(geog) FROM POINT_dt; +#Q#SELECT geom.STAsText(), geog.STAsText() FROM POINT_dt; #D#text#!#text POINT(47.651 -22.349)#!# #!#POINT(47.651 -22.349) diff --git a/test/dotnet/input/Datatypes/TestPoint.txt b/test/dotnet/input/Datatypes/TestPoint.txt index 78d9906534..d5e6b3f7bf 100644 --- a/test/dotnet/input/Datatypes/TestPoint.txt +++ b/test/dotnet/input/Datatypes/TestPoint.txt @@ -40,9 +40,9 @@ INSERT INTO POINTGEOG_dt(location) values(geography::STGeomFromText('Point(47.65 INSERT INTO POINTGEOG_dt(location) values(geography::STPointFromText('Point(47.65100 -22.34900)', 4326)) INSERT INTO POINTGEOG_dt(location) values(geography::Point(47.65100, -22.34900, 4326)) -SELECT STAsText(location) FROM POINTGEOM_dt; -SELECT STAsText(location) FROM POINTGEOG_dt; -SELECT STAsText(geom), STAsText(geog) FROM POINT_dt; +SELECT location.STAsText() FROM POINTGEOM_dt; +SELECT location.STAsText() FROM POINTGEOG_dt; +SELECT geom.STAsText(), geog.STAsText() FROM POINT_dt; DROP TABLE IF EXISTS POINTGEOM_dt; DROP TABLE IF EXISTS POINTGEOG_dt;