Merge branch '3.0' of https://github.com/taosdata/TDengine into enh/tsdb_optimize
This commit is contained in:
commit
3c2a54ab4b
|
@ -60,7 +60,7 @@ sudo apt-get install -y gcc cmake build-essential git libssl-dev libgflags2.2 li
|
|||
为了在 Ubuntu/Debian 系统上编译 [taos-tools](https://github.com/taosdata/taos-tools) 需要安装如下软件:
|
||||
|
||||
```bash
|
||||
sudo apt install build-essential libjansson-dev libsnappy-dev liblzma-dev libz-dev zlib1g pkg-config
|
||||
sudo apt install build-essential libjansson-dev libsnappy-dev liblzma-dev libz-dev zlib1g pkg-config libgeos-dev
|
||||
```
|
||||
|
||||
### CentOS 7.9
|
||||
|
@ -85,7 +85,7 @@ sudo dnf install -y gcc gcc-c++ make cmake epel-release git openssl-devel
|
|||
|
||||
|
||||
```
|
||||
sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libatomic-static libstdc++-static openssl-devel
|
||||
sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libatomic-static libstdc++-static openssl-devel geos geos-devel
|
||||
```
|
||||
|
||||
#### CentOS 8/Rocky Linux
|
||||
|
@ -94,7 +94,7 @@ sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson
|
|||
sudo yum install -y epel-release
|
||||
sudo yum install -y dnf-plugins-core
|
||||
sudo yum config-manager --set-enabled powertools
|
||||
sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libatomic-static libstdc++-static openssl-devel
|
||||
sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libatomic-static libstdc++-static openssl-devel geos geos-devel
|
||||
```
|
||||
|
||||
注意:由于 snappy 缺乏 pkg-config 支持(参考 [链接](https://github.com/google/snappy/pull/86)),会导致 cmake 提示无法发现 libsnappy,实际上工作正常。
|
||||
|
@ -117,7 +117,7 @@ scl enable devtoolset-9 -- bash
|
|||
### macOS
|
||||
|
||||
```
|
||||
brew install argp-standalone pkgconfig
|
||||
brew install argp-standalone pkgconfig geos
|
||||
```
|
||||
|
||||
### 设置 golang 开发环境
|
||||
|
|
|
@ -68,7 +68,7 @@ sudo apt-get install -y gcc cmake build-essential git libssl-dev libgflags2.2 li
|
|||
To build the [taosTools](https://github.com/taosdata/taos-tools) on Ubuntu/Debian, the following packages need to be installed.
|
||||
|
||||
```bash
|
||||
sudo apt install build-essential libjansson-dev libsnappy-dev liblzma-dev libz-dev zlib1g pkg-config
|
||||
sudo apt install build-essential libjansson-dev libsnappy-dev liblzma-dev libz-dev zlib1g pkg-config libgeos-dev
|
||||
```
|
||||
|
||||
### CentOS 7.9
|
||||
|
@ -91,7 +91,7 @@ sudo dnf install -y gcc gcc-c++ make cmake epel-release git openssl-devel
|
|||
#### CentOS 7.9
|
||||
|
||||
```
|
||||
sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libatomic-static libstdc++-static openssl-devel
|
||||
sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libatomic-static libstdc++-static openssl-devel geos geos-devel
|
||||
```
|
||||
|
||||
#### CentOS 8/Rocky Linux
|
||||
|
@ -100,7 +100,7 @@ sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson
|
|||
sudo yum install -y epel-release
|
||||
sudo yum install -y dnf-plugins-core
|
||||
sudo yum config-manager --set-enabled powertools
|
||||
sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libatomic-static libstdc++-static openssl-devel
|
||||
sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson-devel pkgconfig libatomic libatomic-static libstdc++-static openssl-devel geos geos-devel
|
||||
```
|
||||
|
||||
Note: Since snappy lacks pkg-config support (refer to [link](https://github.com/google/snappy/pull/86)), it leads a cmake prompt libsnappy not found. But snappy still works well.
|
||||
|
@ -124,7 +124,7 @@ scl enable devtoolset-9 -- bash
|
|||
### macOS
|
||||
|
||||
```
|
||||
brew install argp-standalone pkgconfig
|
||||
brew install argp-standalone pkgconfig geos
|
||||
```
|
||||
|
||||
### Setup golang environment
|
||||
|
|
|
@ -64,6 +64,13 @@ IF(${TD_WINDOWS})
|
|||
ON
|
||||
)
|
||||
|
||||
MESSAGE("build geos Win32")
|
||||
option(
|
||||
BUILD_GEOS
|
||||
"If build geos on Windows"
|
||||
ON
|
||||
)
|
||||
|
||||
ELSEIF (TD_DARWIN_64)
|
||||
IF(${BUILD_TEST})
|
||||
add_definitions(-DCOMPILER_SUPPORTS_CXX13)
|
||||
|
|
|
@ -57,6 +57,8 @@ IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin
|
|||
SET(TD_DARWIN TRUE)
|
||||
SET(OSTYPE "macOS")
|
||||
ADD_DEFINITIONS("-DDARWIN -Wno-tautological-pointer-compare")
|
||||
INCLUDE_DIRECTORIES(/usr/local/include)
|
||||
LINK_DIRECTORIES(/usr/local/lib)
|
||||
|
||||
IF (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64")
|
||||
MESSAGE("Current system arch is arm64")
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
# geos
|
||||
ExternalProject_Add(geos
|
||||
GIT_REPOSITORY https://github.com/libgeos/geos.git
|
||||
GIT_TAG 3.11.2
|
||||
SOURCE_DIR "${TD_CONTRIB_DIR}/geos"
|
||||
BINARY_DIR ""
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
|
@ -2,6 +2,7 @@
|
|||
# stub
|
||||
ExternalProject_Add(stub
|
||||
GIT_REPOSITORY https://github.com/coolxv/cpp-stub.git
|
||||
GIT_TAG 5e903b8e
|
||||
GIT_SUBMODULES "src"
|
||||
SOURCE_DIR "${TD_CONTRIB_DIR}/cpp-stub"
|
||||
BINARY_DIR "${TD_CONTRIB_DIR}/cpp-stub/src"
|
||||
|
|
|
@ -134,6 +134,11 @@ if(${BUILD_ADDR2LINE})
|
|||
endif(NOT ${TD_WINDOWS})
|
||||
endif(${BUILD_ADDR2LINE})
|
||||
|
||||
# geos
|
||||
if(${BUILD_GEOS})
|
||||
cat("${TD_SUPPORT_DIR}/geos_CMakeLists.txt.in" ${CONTRIB_TMP_FILE})
|
||||
endif()
|
||||
|
||||
# download dependencies
|
||||
configure_file(${CONTRIB_TMP_FILE} "${TD_CONTRIB_DIR}/deps-download/CMakeLists.txt")
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
|
||||
|
@ -470,6 +475,15 @@ if(${BUILD_ADDR2LINE})
|
|||
endif(NOT ${TD_WINDOWS})
|
||||
endif(${BUILD_ADDR2LINE})
|
||||
|
||||
# geos
|
||||
if(${BUILD_GEOS})
|
||||
option(BUILD_SHARED_LIBS "Build GEOS with shared libraries" OFF)
|
||||
add_subdirectory(geos EXCLUDE_FROM_ALL)
|
||||
target_include_directories(
|
||||
geos_c
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/geos/include>
|
||||
)
|
||||
endif(${BUILD_GEOS})
|
||||
|
||||
# ================================================================================================
|
||||
# Build test
|
||||
|
|
|
@ -4,7 +4,7 @@ if(${BUILD_DOCS})
|
|||
find_package(Doxygen)
|
||||
if (DOXYGEN_FOUND)
|
||||
# Build the doc
|
||||
set(DOXYGEN_IN ${TD_SOURCE_DIR}/docs/Doxyfile.in)
|
||||
set(DOXYGEN_IN ${TD_SOURCE_DIR}/docs/doxgen/Doxyfile.in)
|
||||
set(DOXYGEN_OUT ${CMAKE_BINARY_DIR}/Doxyfile)
|
||||
|
||||
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
|
||||
|
|
|
@ -42,7 +42,6 @@ In TDengine, the data types below can be used when specifying a column or tag.
|
|||
| 14 | NCHAR | User Defined | Multi-byte string that can include multi byte characters like Chinese characters. Each character of NCHAR type consumes 4 bytes storage. The string value should be quoted with single quotes. Literal single quote inside the string must be preceded with backslash, like `\'`. The length must be specified when defining a column or tag of NCHAR type, for example nchar(10) means it can store at most 10 characters of nchar type and will consume fixed storage of 40 bytes. An error will be reported if the string value exceeds the length defined. |
|
||||
| 15 | JSON | | JSON type can only be used on tags. A tag of json type is excluded with any other tags of any other type. |
|
||||
| 16 | VARCHAR | User-defined | Alias of BINARY |
|
||||
|
||||
:::note
|
||||
|
||||
- Only ASCII visible characters are suggested to be used in a column or tag of BINARY type. Multi-byte characters must be stored in NCHAR type.
|
||||
|
|
|
@ -78,7 +78,8 @@ int printRow(char *str, TAOS_ROW row, TAOS_FIELD *fields, int numFields) {
|
|||
} break;
|
||||
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
|
||||
memcpy(str + len, row[i], charLen);
|
||||
len += charLen;
|
||||
|
|
|
@ -76,7 +76,8 @@ int printRow(char *str, TAOS_ROW row, TAOS_FIELD *fields, int numFields) {
|
|||
} break;
|
||||
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
|
||||
memcpy(str + len, row[i], charLen);
|
||||
len += charLen;
|
||||
|
|
|
@ -6,39 +6,32 @@ import java.sql.Connection;
|
|||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class StmtInsertExample {
|
||||
private static ArrayList<Long> tsToLongArray(String ts) {
|
||||
ArrayList<Long> result = new ArrayList<>();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(ts, formatter);
|
||||
result.add(localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli());
|
||||
return result;
|
||||
}
|
||||
private static String datePattern = "yyyy-MM-dd HH:mm:ss.SSS";
|
||||
private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern(datePattern);
|
||||
|
||||
private static <T> ArrayList<T> toArray(T v) {
|
||||
ArrayList<T> result = new ArrayList<>();
|
||||
result.add(v);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static List<String> getRawData() {
|
||||
return Arrays.asList(
|
||||
"d1001,2018-10-03 14:38:05.000,10.30000,219,0.31000,California.SanFrancisco,2",
|
||||
"d1001,2018-10-03 14:38:15.000,12.60000,218,0.33000,California.SanFrancisco,2",
|
||||
"d1001,2018-10-03 14:38:16.800,12.30000,221,0.31000,California.SanFrancisco,2",
|
||||
"d1002,2018-10-03 14:38:16.650,10.30000,218,0.25000,California.SanFrancisco,3",
|
||||
"d1003,2018-10-03 14:38:05.500,11.80000,221,0.28000,California.LosAngeles,2",
|
||||
"d1003,2018-10-03 14:38:16.600,13.40000,223,0.29000,California.LosAngeles,2",
|
||||
"d1004,2018-10-03 14:38:05.000,10.80000,223,0.29000,California.LosAngeles,3",
|
||||
"d1004,2018-10-03 14:38:06.500,11.50000,221,0.35000,California.LosAngeles,3"
|
||||
);
|
||||
private static List<String> getRawData(int size) {
|
||||
SimpleDateFormat format = new SimpleDateFormat(datePattern);
|
||||
List<String> result = new ArrayList<>();
|
||||
long current = System.currentTimeMillis();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < size; i++) {
|
||||
String time = format.format(current + i);
|
||||
int id = random.nextInt(10);
|
||||
result.add("d" + id + "," + time + ",10.30000,219,0.31000,California.SanFrancisco,2");
|
||||
}
|
||||
return result.stream()
|
||||
.sorted(Comparator.comparing(s -> s.split(",")[0])).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static Connection getConnection() throws SQLException {
|
||||
|
@ -48,9 +41,9 @@ public class StmtInsertExample {
|
|||
|
||||
private static void createTable(Connection conn) throws SQLException {
|
||||
try (Statement stmt = conn.createStatement()) {
|
||||
stmt.execute("CREATE DATABASE power KEEP 3650");
|
||||
stmt.executeUpdate("USE power");
|
||||
stmt.execute("CREATE STABLE meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) " +
|
||||
stmt.execute("CREATE DATABASE if not exists power KEEP 3650");
|
||||
stmt.executeUpdate("use power");
|
||||
stmt.execute("CREATE STABLE if not exists meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) " +
|
||||
"TAGS (location BINARY(64), groupId INT)");
|
||||
}
|
||||
}
|
||||
|
@ -58,21 +51,54 @@ public class StmtInsertExample {
|
|||
private static void insertData() throws SQLException {
|
||||
try (Connection conn = getConnection()) {
|
||||
createTable(conn);
|
||||
String psql = "INSERT INTO ? USING meters TAGS(?, ?) VALUES(?, ?, ?, ?)";
|
||||
String psql = "INSERT INTO ? USING power.meters TAGS(?, ?) VALUES(?, ?, ?, ?)";
|
||||
try (TSDBPreparedStatement pst = (TSDBPreparedStatement) conn.prepareStatement(psql)) {
|
||||
for (String line : getRawData()) {
|
||||
String tableName = null;
|
||||
ArrayList<Long> ts = new ArrayList<>();
|
||||
ArrayList<Float> current = new ArrayList<>();
|
||||
ArrayList<Integer> voltage = new ArrayList<>();
|
||||
ArrayList<Float> phase = new ArrayList<>();
|
||||
for (String line : getRawData(100000)) {
|
||||
String[] ps = line.split(",");
|
||||
// bind table name and tags
|
||||
pst.setTableName(ps[0]);
|
||||
pst.setTagString(0, ps[5]);
|
||||
pst.setTagInt(1, Integer.valueOf(ps[6]));
|
||||
if (tableName == null) {
|
||||
// bind table name and tags
|
||||
tableName = "power." + ps[0];
|
||||
pst.setTableName(ps[0]);
|
||||
pst.setTagString(0, ps[5]);
|
||||
pst.setTagInt(1, Integer.valueOf(ps[6]));
|
||||
} else {
|
||||
if (!tableName.equals(ps[0])) {
|
||||
pst.setTimestamp(0, ts);
|
||||
pst.setFloat(1, current);
|
||||
pst.setInt(2, voltage);
|
||||
pst.setFloat(3, phase);
|
||||
pst.columnDataAddBatch();
|
||||
pst.columnDataExecuteBatch();
|
||||
|
||||
// bind table name and tags
|
||||
tableName = ps[0];
|
||||
pst.setTableName(ps[0]);
|
||||
pst.setTagString(0, ps[5]);
|
||||
pst.setTagInt(1, Integer.valueOf(ps[6]));
|
||||
ts.clear();
|
||||
current.clear();
|
||||
voltage.clear();
|
||||
phase.clear();
|
||||
}
|
||||
}
|
||||
// bind values
|
||||
pst.setTimestamp(0, tsToLongArray(ps[1])); //ps[1] looks like: 2018-10-03 14:38:05.000
|
||||
pst.setFloat(1, toArray(Float.valueOf(ps[2])));
|
||||
pst.setInt(2, toArray(Integer.valueOf(ps[3])));
|
||||
pst.setFloat(3, toArray(Float.valueOf(ps[4])));
|
||||
pst.columnDataAddBatch();
|
||||
// ps[1] looks like: 2018-10-03 14:38:05.000
|
||||
LocalDateTime localDateTime = LocalDateTime.parse(ps[1], formatter);
|
||||
ts.add(localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli());
|
||||
current.add(Float.valueOf(ps[2]));
|
||||
voltage.add(Integer.valueOf(ps[3]));
|
||||
phase.add(Float.valueOf(ps[4]));
|
||||
}
|
||||
pst.setTimestamp(0, ts);
|
||||
pst.setFloat(1, current);
|
||||
pst.setInt(2, voltage);
|
||||
pst.setFloat(3, phase);
|
||||
pst.columnDataAddBatch();
|
||||
pst.columnDataExecuteBatch();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,6 +162,7 @@ static int l_query(lua_State *L){
|
|||
case TSDB_DATA_TYPE_JSON:
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
//printf("type:%d, max len:%d, current len:%d\n",fields[i].type, fields[i].bytes, length[i]);
|
||||
lua_pushlstring(L,(char *)row[i], length[i]);
|
||||
break;
|
||||
|
|
|
@ -161,6 +161,7 @@ static int l_query(lua_State *L){
|
|||
case TSDB_DATA_TYPE_JSON:
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
//printf("type:%d, max len:%d, current len:%d\n",fields[i].type, fields[i].bytes, length[i]);
|
||||
lua_pushlstring(L,(char *)row[i], length[i]);
|
||||
break;
|
||||
|
|
|
@ -51,7 +51,8 @@ typedef void TAOS_SUB;
|
|||
#define TSDB_DATA_TYPE_BLOB 18 // binary
|
||||
#define TSDB_DATA_TYPE_MEDIUMBLOB 19
|
||||
#define TSDB_DATA_TYPE_BINARY TSDB_DATA_TYPE_VARCHAR // string
|
||||
#define TSDB_DATA_TYPE_MAX 20
|
||||
#define TSDB_DATA_TYPE_GEOMETRY 20 // geometry
|
||||
#define TSDB_DATA_TYPE_MAX 21
|
||||
|
||||
typedef enum {
|
||||
TSDB_OPTION_LOCALE,
|
||||
|
|
|
@ -146,212 +146,212 @@
|
|||
#define TK_MEDIUMBLOB 128
|
||||
#define TK_BLOB 129
|
||||
#define TK_VARBINARY 130
|
||||
#define TK_DECIMAL 131
|
||||
#define TK_COMMENT 132
|
||||
#define TK_MAX_DELAY 133
|
||||
#define TK_WATERMARK 134
|
||||
#define TK_ROLLUP 135
|
||||
#define TK_TTL 136
|
||||
#define TK_SMA 137
|
||||
#define TK_DELETE_MARK 138
|
||||
#define TK_FIRST 139
|
||||
#define TK_LAST 140
|
||||
#define TK_SHOW 141
|
||||
#define TK_PRIVILEGES 142
|
||||
#define TK_DATABASES 143
|
||||
#define TK_TABLES 144
|
||||
#define TK_STABLES 145
|
||||
#define TK_MNODES 146
|
||||
#define TK_QNODES 147
|
||||
#define TK_FUNCTIONS 148
|
||||
#define TK_INDEXES 149
|
||||
#define TK_ACCOUNTS 150
|
||||
#define TK_APPS 151
|
||||
#define TK_CONNECTIONS 152
|
||||
#define TK_LICENCES 153
|
||||
#define TK_GRANTS 154
|
||||
#define TK_QUERIES 155
|
||||
#define TK_SCORES 156
|
||||
#define TK_TOPICS 157
|
||||
#define TK_VARIABLES 158
|
||||
#define TK_CLUSTER 159
|
||||
#define TK_BNODES 160
|
||||
#define TK_SNODES 161
|
||||
#define TK_TRANSACTIONS 162
|
||||
#define TK_DISTRIBUTED 163
|
||||
#define TK_CONSUMERS 164
|
||||
#define TK_SUBSCRIPTIONS 165
|
||||
#define TK_VNODES 166
|
||||
#define TK_ALIVE 167
|
||||
#define TK_LIKE 168
|
||||
#define TK_TBNAME 169
|
||||
#define TK_QTAGS 170
|
||||
#define TK_AS 171
|
||||
#define TK_INDEX 172
|
||||
#define TK_FUNCTION 173
|
||||
#define TK_INTERVAL 174
|
||||
#define TK_COUNT 175
|
||||
#define TK_LAST_ROW 176
|
||||
#define TK_TOPIC 177
|
||||
#define TK_META 178
|
||||
#define TK_CONSUMER 179
|
||||
#define TK_GROUP 180
|
||||
#define TK_DESC 181
|
||||
#define TK_DESCRIBE 182
|
||||
#define TK_RESET 183
|
||||
#define TK_QUERY 184
|
||||
#define TK_CACHE 185
|
||||
#define TK_EXPLAIN 186
|
||||
#define TK_ANALYZE 187
|
||||
#define TK_VERBOSE 188
|
||||
#define TK_NK_BOOL 189
|
||||
#define TK_RATIO 190
|
||||
#define TK_NK_FLOAT 191
|
||||
#define TK_OUTPUTTYPE 192
|
||||
#define TK_AGGREGATE 193
|
||||
#define TK_BUFSIZE 194
|
||||
#define TK_LANGUAGE 195
|
||||
#define TK_REPLACE 196
|
||||
#define TK_STREAM 197
|
||||
#define TK_INTO 198
|
||||
#define TK_PAUSE 199
|
||||
#define TK_RESUME 200
|
||||
#define TK_TRIGGER 201
|
||||
#define TK_AT_ONCE 202
|
||||
#define TK_WINDOW_CLOSE 203
|
||||
#define TK_IGNORE 204
|
||||
#define TK_EXPIRED 205
|
||||
#define TK_FILL_HISTORY 206
|
||||
#define TK_UPDATE 207
|
||||
#define TK_SUBTABLE 208
|
||||
#define TK_UNTREATED 209
|
||||
#define TK_KILL 210
|
||||
#define TK_CONNECTION 211
|
||||
#define TK_TRANSACTION 212
|
||||
#define TK_BALANCE 213
|
||||
#define TK_VGROUP 214
|
||||
#define TK_LEADER 215
|
||||
#define TK_MERGE 216
|
||||
#define TK_REDISTRIBUTE 217
|
||||
#define TK_SPLIT 218
|
||||
#define TK_DELETE 219
|
||||
#define TK_INSERT 220
|
||||
#define TK_NULL 221
|
||||
#define TK_NK_QUESTION 222
|
||||
#define TK_NK_ARROW 223
|
||||
#define TK_ROWTS 224
|
||||
#define TK_QSTART 225
|
||||
#define TK_QEND 226
|
||||
#define TK_QDURATION 227
|
||||
#define TK_WSTART 228
|
||||
#define TK_WEND 229
|
||||
#define TK_WDURATION 230
|
||||
#define TK_IROWTS 231
|
||||
#define TK_ISFILLED 232
|
||||
#define TK_CAST 233
|
||||
#define TK_NOW 234
|
||||
#define TK_TODAY 235
|
||||
#define TK_TIMEZONE 236
|
||||
#define TK_CLIENT_VERSION 237
|
||||
#define TK_SERVER_VERSION 238
|
||||
#define TK_SERVER_STATUS 239
|
||||
#define TK_CURRENT_USER 240
|
||||
#define TK_CASE 241
|
||||
#define TK_WHEN 242
|
||||
#define TK_THEN 243
|
||||
#define TK_ELSE 244
|
||||
#define TK_BETWEEN 245
|
||||
#define TK_IS 246
|
||||
#define TK_NK_LT 247
|
||||
#define TK_NK_GT 248
|
||||
#define TK_NK_LE 249
|
||||
#define TK_NK_GE 250
|
||||
#define TK_NK_NE 251
|
||||
#define TK_MATCH 252
|
||||
#define TK_NMATCH 253
|
||||
#define TK_CONTAINS 254
|
||||
#define TK_IN 255
|
||||
#define TK_JOIN 256
|
||||
#define TK_INNER 257
|
||||
#define TK_SELECT 258
|
||||
#define TK_DISTINCT 259
|
||||
#define TK_WHERE 260
|
||||
#define TK_PARTITION 261
|
||||
#define TK_BY 262
|
||||
#define TK_SESSION 263
|
||||
#define TK_STATE_WINDOW 264
|
||||
#define TK_EVENT_WINDOW 265
|
||||
#define TK_SLIDING 266
|
||||
#define TK_FILL 267
|
||||
#define TK_VALUE 268
|
||||
#define TK_VALUE_F 269
|
||||
#define TK_NONE 270
|
||||
#define TK_PREV 271
|
||||
#define TK_NULL_F 272
|
||||
#define TK_LINEAR 273
|
||||
#define TK_NEXT 274
|
||||
#define TK_HAVING 275
|
||||
#define TK_RANGE 276
|
||||
#define TK_EVERY 277
|
||||
#define TK_ORDER 278
|
||||
#define TK_SLIMIT 279
|
||||
#define TK_SOFFSET 280
|
||||
#define TK_LIMIT 281
|
||||
#define TK_OFFSET 282
|
||||
#define TK_ASC 283
|
||||
#define TK_NULLS 284
|
||||
#define TK_ABORT 285
|
||||
#define TK_AFTER 286
|
||||
#define TK_ATTACH 287
|
||||
#define TK_BEFORE 288
|
||||
#define TK_BEGIN 289
|
||||
#define TK_BITAND 290
|
||||
#define TK_BITNOT 291
|
||||
#define TK_BITOR 292
|
||||
#define TK_BLOCKS 293
|
||||
#define TK_CHANGE 294
|
||||
#define TK_COMMA 295
|
||||
#define TK_CONCAT 296
|
||||
#define TK_CONFLICT 297
|
||||
#define TK_COPY 298
|
||||
#define TK_DEFERRED 299
|
||||
#define TK_DELIMITERS 300
|
||||
#define TK_DETACH 301
|
||||
#define TK_DIVIDE 302
|
||||
#define TK_DOT 303
|
||||
#define TK_EACH 304
|
||||
#define TK_FAIL 305
|
||||
#define TK_FILE 306
|
||||
#define TK_FOR 307
|
||||
#define TK_GLOB 308
|
||||
#define TK_ID 309
|
||||
#define TK_IMMEDIATE 310
|
||||
#define TK_IMPORT 311
|
||||
#define TK_INITIALLY 312
|
||||
#define TK_INSTEAD 313
|
||||
#define TK_ISNULL 314
|
||||
#define TK_KEY 315
|
||||
#define TK_MODULES 316
|
||||
#define TK_NK_BITNOT 317
|
||||
#define TK_NK_SEMI 318
|
||||
#define TK_NOTNULL 319
|
||||
#define TK_OF 320
|
||||
#define TK_PLUS 321
|
||||
#define TK_PRIVILEGE 322
|
||||
#define TK_RAISE 323
|
||||
#define TK_RESTRICT 324
|
||||
#define TK_ROW 325
|
||||
#define TK_SEMI 326
|
||||
#define TK_STAR 327
|
||||
#define TK_STATEMENT 328
|
||||
#define TK_STRICT 329
|
||||
#define TK_STRING 330
|
||||
#define TK_TIMES 331
|
||||
#define TK_VALUES 332
|
||||
#define TK_VARIABLE 333
|
||||
#define TK_VIEW 334
|
||||
#define TK_WAL 335
|
||||
|
||||
#define TK_GEOMETRY 131
|
||||
#define TK_DECIMAL 132
|
||||
#define TK_COMMENT 133
|
||||
#define TK_MAX_DELAY 134
|
||||
#define TK_WATERMARK 135
|
||||
#define TK_ROLLUP 136
|
||||
#define TK_TTL 137
|
||||
#define TK_SMA 138
|
||||
#define TK_DELETE_MARK 139
|
||||
#define TK_FIRST 140
|
||||
#define TK_LAST 141
|
||||
#define TK_SHOW 142
|
||||
#define TK_PRIVILEGES 143
|
||||
#define TK_DATABASES 144
|
||||
#define TK_TABLES 145
|
||||
#define TK_STABLES 146
|
||||
#define TK_MNODES 147
|
||||
#define TK_QNODES 148
|
||||
#define TK_FUNCTIONS 149
|
||||
#define TK_INDEXES 150
|
||||
#define TK_ACCOUNTS 151
|
||||
#define TK_APPS 152
|
||||
#define TK_CONNECTIONS 153
|
||||
#define TK_LICENCES 154
|
||||
#define TK_GRANTS 155
|
||||
#define TK_QUERIES 156
|
||||
#define TK_SCORES 157
|
||||
#define TK_TOPICS 158
|
||||
#define TK_VARIABLES 159
|
||||
#define TK_CLUSTER 160
|
||||
#define TK_BNODES 161
|
||||
#define TK_SNODES 162
|
||||
#define TK_TRANSACTIONS 163
|
||||
#define TK_DISTRIBUTED 164
|
||||
#define TK_CONSUMERS 165
|
||||
#define TK_SUBSCRIPTIONS 166
|
||||
#define TK_VNODES 167
|
||||
#define TK_ALIVE 168
|
||||
#define TK_LIKE 169
|
||||
#define TK_TBNAME 170
|
||||
#define TK_QTAGS 171
|
||||
#define TK_AS 172
|
||||
#define TK_INDEX 173
|
||||
#define TK_FUNCTION 174
|
||||
#define TK_INTERVAL 175
|
||||
#define TK_COUNT 176
|
||||
#define TK_LAST_ROW 177
|
||||
#define TK_TOPIC 178
|
||||
#define TK_META 179
|
||||
#define TK_CONSUMER 180
|
||||
#define TK_GROUP 181
|
||||
#define TK_DESC 182
|
||||
#define TK_DESCRIBE 183
|
||||
#define TK_RESET 184
|
||||
#define TK_QUERY 185
|
||||
#define TK_CACHE 186
|
||||
#define TK_EXPLAIN 187
|
||||
#define TK_ANALYZE 188
|
||||
#define TK_VERBOSE 189
|
||||
#define TK_NK_BOOL 190
|
||||
#define TK_RATIO 191
|
||||
#define TK_NK_FLOAT 192
|
||||
#define TK_OUTPUTTYPE 193
|
||||
#define TK_AGGREGATE 194
|
||||
#define TK_BUFSIZE 195
|
||||
#define TK_LANGUAGE 196
|
||||
#define TK_REPLACE 197
|
||||
#define TK_STREAM 198
|
||||
#define TK_INTO 199
|
||||
#define TK_PAUSE 200
|
||||
#define TK_RESUME 201
|
||||
#define TK_TRIGGER 202
|
||||
#define TK_AT_ONCE 203
|
||||
#define TK_WINDOW_CLOSE 204
|
||||
#define TK_IGNORE 205
|
||||
#define TK_EXPIRED 206
|
||||
#define TK_FILL_HISTORY 207
|
||||
#define TK_UPDATE 208
|
||||
#define TK_SUBTABLE 209
|
||||
#define TK_UNTREATED 210
|
||||
#define TK_KILL 211
|
||||
#define TK_CONNECTION 212
|
||||
#define TK_TRANSACTION 213
|
||||
#define TK_BALANCE 214
|
||||
#define TK_VGROUP 215
|
||||
#define TK_LEADER 216
|
||||
#define TK_MERGE 217
|
||||
#define TK_REDISTRIBUTE 218
|
||||
#define TK_SPLIT 219
|
||||
#define TK_DELETE 220
|
||||
#define TK_INSERT 221
|
||||
#define TK_NULL 222
|
||||
#define TK_NK_QUESTION 223
|
||||
#define TK_NK_ARROW 224
|
||||
#define TK_ROWTS 225
|
||||
#define TK_QSTART 226
|
||||
#define TK_QEND 227
|
||||
#define TK_QDURATION 228
|
||||
#define TK_WSTART 229
|
||||
#define TK_WEND 230
|
||||
#define TK_WDURATION 231
|
||||
#define TK_IROWTS 232
|
||||
#define TK_ISFILLED 233
|
||||
#define TK_CAST 234
|
||||
#define TK_NOW 235
|
||||
#define TK_TODAY 236
|
||||
#define TK_TIMEZONE 237
|
||||
#define TK_CLIENT_VERSION 238
|
||||
#define TK_SERVER_VERSION 239
|
||||
#define TK_SERVER_STATUS 240
|
||||
#define TK_CURRENT_USER 241
|
||||
#define TK_CASE 242
|
||||
#define TK_WHEN 243
|
||||
#define TK_THEN 244
|
||||
#define TK_ELSE 245
|
||||
#define TK_BETWEEN 246
|
||||
#define TK_IS 247
|
||||
#define TK_NK_LT 248
|
||||
#define TK_NK_GT 249
|
||||
#define TK_NK_LE 250
|
||||
#define TK_NK_GE 251
|
||||
#define TK_NK_NE 252
|
||||
#define TK_MATCH 253
|
||||
#define TK_NMATCH 254
|
||||
#define TK_CONTAINS 255
|
||||
#define TK_IN 256
|
||||
#define TK_JOIN 257
|
||||
#define TK_INNER 258
|
||||
#define TK_SELECT 259
|
||||
#define TK_DISTINCT 260
|
||||
#define TK_WHERE 261
|
||||
#define TK_PARTITION 262
|
||||
#define TK_BY 263
|
||||
#define TK_SESSION 264
|
||||
#define TK_STATE_WINDOW 265
|
||||
#define TK_EVENT_WINDOW 266
|
||||
#define TK_SLIDING 267
|
||||
#define TK_FILL 268
|
||||
#define TK_VALUE 269
|
||||
#define TK_VALUE_F 270
|
||||
#define TK_NONE 271
|
||||
#define TK_PREV 272
|
||||
#define TK_NULL_F 273
|
||||
#define TK_LINEAR 274
|
||||
#define TK_NEXT 275
|
||||
#define TK_HAVING 276
|
||||
#define TK_RANGE 277
|
||||
#define TK_EVERY 278
|
||||
#define TK_ORDER 279
|
||||
#define TK_SLIMIT 280
|
||||
#define TK_SOFFSET 281
|
||||
#define TK_LIMIT 282
|
||||
#define TK_OFFSET 283
|
||||
#define TK_ASC 284
|
||||
#define TK_NULLS 285
|
||||
#define TK_ABORT 286
|
||||
#define TK_AFTER 287
|
||||
#define TK_ATTACH 288
|
||||
#define TK_BEFORE 289
|
||||
#define TK_BEGIN 290
|
||||
#define TK_BITAND 291
|
||||
#define TK_BITNOT 292
|
||||
#define TK_BITOR 293
|
||||
#define TK_BLOCKS 294
|
||||
#define TK_CHANGE 295
|
||||
#define TK_COMMA 296
|
||||
#define TK_CONCAT 297
|
||||
#define TK_CONFLICT 298
|
||||
#define TK_COPY 299
|
||||
#define TK_DEFERRED 300
|
||||
#define TK_DELIMITERS 301
|
||||
#define TK_DETACH 302
|
||||
#define TK_DIVIDE 303
|
||||
#define TK_DOT 304
|
||||
#define TK_EACH 305
|
||||
#define TK_FAIL 306
|
||||
#define TK_FILE 307
|
||||
#define TK_FOR 308
|
||||
#define TK_GLOB 309
|
||||
#define TK_ID 310
|
||||
#define TK_IMMEDIATE 311
|
||||
#define TK_IMPORT 312
|
||||
#define TK_INITIALLY 313
|
||||
#define TK_INSTEAD 314
|
||||
#define TK_ISNULL 315
|
||||
#define TK_KEY 316
|
||||
#define TK_MODULES 317
|
||||
#define TK_NK_BITNOT 318
|
||||
#define TK_NK_SEMI 319
|
||||
#define TK_NOTNULL 320
|
||||
#define TK_OF 321
|
||||
#define TK_PLUS 322
|
||||
#define TK_PRIVILEGE 323
|
||||
#define TK_RAISE 324
|
||||
#define TK_RESTRICT 325
|
||||
#define TK_ROW 326
|
||||
#define TK_SEMI 327
|
||||
#define TK_STAR 328
|
||||
#define TK_STATEMENT 329
|
||||
#define TK_STRICT 330
|
||||
#define TK_STRING 331
|
||||
#define TK_TIMES 332
|
||||
#define TK_VALUES 333
|
||||
#define TK_VARIABLE 334
|
||||
#define TK_VIEW 335
|
||||
#define TK_WAL 336
|
||||
|
||||
|
||||
#define TK_NK_SPACE 600
|
||||
|
|
|
@ -269,7 +269,7 @@ typedef struct {
|
|||
(IS_NUMERIC_TYPE(_t) || (_t) == (TSDB_DATA_TYPE_BOOL) || (_t) == (TSDB_DATA_TYPE_TIMESTAMP))
|
||||
|
||||
#define IS_VAR_DATA_TYPE(t) \
|
||||
(((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR) || ((t) == TSDB_DATA_TYPE_JSON))
|
||||
(((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR) || ((t) == TSDB_DATA_TYPE_JSON) || ((t) == TSDB_DATA_TYPE_GEOMETRY))
|
||||
#define IS_STR_DATA_TYPE(t) (((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR))
|
||||
|
||||
#define IS_VALID_TINYINT(_t) ((_t) >= INT8_MIN && (_t) <= INT8_MAX)
|
||||
|
@ -316,6 +316,8 @@ static FORCE_INLINE bool isNull(const void *val, int32_t type) {
|
|||
return *(uint32_t *)val == TSDB_DATA_UINT_NULL;
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
return *(uint64_t *)val == TSDB_DATA_UBIGINT_NULL;
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
return varDataLen(val) == sizeof(int8_t) && *(uint8_t *)varDataVal(val) == TSDB_DATA_GEOMETRY_NULL;
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
|
|
@ -158,6 +158,17 @@ typedef enum EFunctionType {
|
|||
FUNCTION_TYPE_STDDEV_PARTIAL,
|
||||
FUNCTION_TYPE_STDDEV_MERGE,
|
||||
|
||||
// geometry functions
|
||||
FUNCTION_TYPE_GEOM_FROM_TEXT = 4250,
|
||||
FUNCTION_TYPE_AS_TEXT,
|
||||
FUNCTION_TYPE_MAKE_POINT,
|
||||
FUNCTION_TYPE_INTERSECTS,
|
||||
FUNCTION_TYPE_EQUALS,
|
||||
FUNCTION_TYPE_TOUCHES,
|
||||
FUNCTION_TYPE_COVERS,
|
||||
FUNCTION_TYPE_CONTAINS,
|
||||
FUNCTION_TYPE_CONTAINS_PROPERLY,
|
||||
|
||||
// user defined funcion
|
||||
FUNCTION_TYPE_UDF = 10000
|
||||
} EFunctionType;
|
||||
|
|
|
@ -109,7 +109,7 @@ typedef uint16_t VarDataLenT; // maxVarDataLen: 65535
|
|||
#define varDataLenByData(v) (*(VarDataLenT *)(((char *)(v)) - VARSTR_HEADER_SIZE))
|
||||
#define varDataSetLen(v, _len) (((VarDataLenT *)(v))[0] = (VarDataLenT)(_len))
|
||||
#define IS_VAR_DATA_TYPE(t) \
|
||||
(((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR) || ((t) == TSDB_DATA_TYPE_JSON))
|
||||
(((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR) || ((t) == TSDB_DATA_TYPE_JSON) || ((t) == TSDB_DATA_TYPE_GEOMETRY))
|
||||
#define IS_STR_DATA_TYPE(t) (((t) == TSDB_DATA_TYPE_VARCHAR) || ((t) == TSDB_DATA_TYPE_NCHAR))
|
||||
|
||||
static FORCE_INLINE char *udfColDataGetData(const SUdfColumn *pColumn, int32_t row) {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_GEOM_FUNC_H
|
||||
#define TDENGINE_GEOM_FUNC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "function.h"
|
||||
|
||||
int32_t makePointFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
|
||||
int32_t geomFromTextFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t asTextFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
|
||||
int32_t intersectsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t equalsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t touchesFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t coversFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t containsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t containsProperlyFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TDENGINE_GEOM_FUNC_H
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TDENGINE_GEOS_WRAPPER_H
|
||||
#define TDENGINE_GEOS_WRAPPER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "os.h"
|
||||
|
||||
#include "tgeosctx.h"
|
||||
|
||||
void geosFreeBuffer(void *buffer);
|
||||
|
||||
int32_t initCtxMakePoint();
|
||||
int32_t doMakePoint(double x, double y, unsigned char **outputGeom, size_t *size);
|
||||
|
||||
int32_t initCtxGeomFromText();
|
||||
int32_t doGeomFromText(const char *inputWKT, unsigned char **outputGeom, size_t *size);
|
||||
|
||||
int32_t initCtxAsText();
|
||||
int32_t doAsText(const unsigned char *inputGeom, size_t size, char **outputWKT);
|
||||
|
||||
int32_t initCtxRelationFunc();
|
||||
int32_t doIntersects(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res);
|
||||
int32_t doEquals(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res);
|
||||
int32_t doTouches(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res);
|
||||
int32_t doCovers(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res);
|
||||
int32_t doContains(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res);
|
||||
int32_t doContainsProperly(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res);
|
||||
|
||||
int32_t readGeometry(const unsigned char *input, GEOSGeometry **outputGeom, const GEOSPreparedGeometry **outputPreparedGeom);
|
||||
void destroyGeometry(GEOSGeometry **geom, const GEOSPreparedGeometry **preparedGeom);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*TDENGINE_GEOS_WRAPPER_H*/
|
|
@ -32,7 +32,7 @@ extern "C" {
|
|||
#define TD_VER_MAX UINT64_MAX // TODO: use the real max version from query handle
|
||||
|
||||
// Bytes for each type.
|
||||
extern const int32_t TYPE_BYTES[16];
|
||||
extern const int32_t TYPE_BYTES[17];
|
||||
|
||||
// TODO: replace and remove code below
|
||||
#define CHAR_BYTES sizeof(char)
|
||||
|
@ -53,10 +53,11 @@ extern const int32_t TYPE_BYTES[16];
|
|||
#define TSDB_DATA_BIGINT_NULL 0x8000000000000000LL
|
||||
#define TSDB_DATA_TIMESTAMP_NULL TSDB_DATA_BIGINT_NULL
|
||||
|
||||
#define TSDB_DATA_FLOAT_NULL 0x7FF00000 // it is an NAN
|
||||
#define TSDB_DATA_DOUBLE_NULL 0x7FFFFF0000000000LL // an NAN
|
||||
#define TSDB_DATA_NCHAR_NULL 0xFFFFFFFF
|
||||
#define TSDB_DATA_BINARY_NULL 0xFF
|
||||
#define TSDB_DATA_FLOAT_NULL 0x7FF00000 // it is an NAN
|
||||
#define TSDB_DATA_DOUBLE_NULL 0x7FFFFF0000000000LL // an NAN
|
||||
#define TSDB_DATA_NCHAR_NULL 0xFFFFFFFF
|
||||
#define TSDB_DATA_BINARY_NULL 0xFF
|
||||
#define TSDB_DATA_GEOMETRY_NULL 0xFF
|
||||
|
||||
#define TSDB_DATA_UTINYINT_NULL 0xFF
|
||||
#define TSDB_DATA_USMALLINT_NULL 0xFFFF
|
||||
|
@ -253,6 +254,7 @@ typedef enum ELogicConditionType {
|
|||
#define TSDB_IPv4ADDR_LEN 16
|
||||
#define TSDB_FILENAME_LEN 128
|
||||
#define TSDB_SHOW_SQL_LEN 2048
|
||||
#define TSDB_SHOW_SCHEMA_JSON_LEN TSDB_MAX_COLUMNS * 256
|
||||
#define TSDB_SLOW_QUERY_SQL_LEN 512
|
||||
#define TSDB_SHOW_SUBQUERY_LEN 1000
|
||||
|
||||
|
@ -410,6 +412,8 @@ typedef enum ELogicConditionType {
|
|||
#define TSDB_MAX_FIELD_LEN 65519 // 16384:65519
|
||||
#define TSDB_MAX_BINARY_LEN TSDB_MAX_FIELD_LEN // 16384-8:65519
|
||||
#define TSDB_MAX_NCHAR_LEN TSDB_MAX_FIELD_LEN // 16384-8:65519
|
||||
#define TSDB_MAX_GEOMETRY_LEN TSDB_MAX_FIELD_LEN // 16384-8:65519
|
||||
|
||||
#define PRIMARYKEY_TIMESTAMP_COL_ID 1
|
||||
#define COL_REACH_END(colId, maxColId) ((colId) > (maxColId))
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TD_UTIL_GEOS_CTX_H_
|
||||
#define _TD_UTIL_GEOS_CTX_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <geos_c.h>
|
||||
|
||||
typedef struct SGeosContext {
|
||||
GEOSContextHandle_t handle;
|
||||
|
||||
GEOSWKTReader *WKTReader;
|
||||
GEOSWKTWriter *WKTWriter;
|
||||
|
||||
GEOSWKBReader *WKBReader;
|
||||
GEOSWKBWriter *WKBWriter;
|
||||
|
||||
char errMsg[512];
|
||||
} SGeosContext;
|
||||
|
||||
SGeosContext* getThreadLocalGeosCtx();
|
||||
void destroyThreadLocalGeosCtx();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_TD_UTIL_GEOS_CTX_H_*/
|
|
@ -491,7 +491,8 @@ void setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t
|
|||
pResInfo->userFields[i].bytes = pSchema[i].bytes;
|
||||
pResInfo->userFields[i].type = pSchema[i].type;
|
||||
|
||||
if (pSchema[i].type == TSDB_DATA_TYPE_VARCHAR) {
|
||||
if (pSchema[i].type == TSDB_DATA_TYPE_VARCHAR ||
|
||||
pSchema[i].type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
pResInfo->userFields[i].bytes -= VARSTR_HEADER_SIZE;
|
||||
} else if (pSchema[i].type == TSDB_DATA_TYPE_NCHAR || pSchema[i].type == TSDB_DATA_TYPE_JSON) {
|
||||
pResInfo->userFields[i].bytes = (pResInfo->userFields[i].bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
|
|
|
@ -579,7 +579,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn
|
|||
dv = GET_DOUBLE_VAL(row[i]);
|
||||
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetDoubleFp, i, (jdouble)dv);
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
memcpy(tmp, row[i], length[i]); // handle the case that terminated does not exist
|
||||
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetStringFp, i, (*env)->NewStringUTF(env, tmp));
|
||||
|
||||
|
|
|
@ -393,9 +393,10 @@ int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields)
|
|||
} break;
|
||||
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
|
||||
if (fields[i].type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (fields[i].type == TSDB_DATA_TYPE_BINARY || fields[i].type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
if (ASSERT(charLen <= fields[i].bytes && charLen >= 0)) {
|
||||
tscError("taos_print_row error binary. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes);
|
||||
}
|
||||
|
@ -475,6 +476,8 @@ const char *taos_data_type(int type) {
|
|||
return "TSDB_DATA_TYPE_NCHAR";
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
return "TSDB_DATA_TYPE_JSON";
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
return "TSDB_DATA_TYPE_GEOMETRY";
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
return "TSDB_DATA_TYPE_UTINYINT";
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
|
|
|
@ -56,7 +56,7 @@ static char* buildCreateTableJson(SSchemaWrapper* schemaRow, SSchemaWrapper* sch
|
|||
cJSON_AddItemToObject(column, "name", cname);
|
||||
cJSON* ctype = cJSON_CreateNumber(s->type);
|
||||
cJSON_AddItemToObject(column, "type", ctype);
|
||||
if (s->type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (s->type == TSDB_DATA_TYPE_BINARY || s->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t length = s->bytes - VARSTR_HEADER_SIZE;
|
||||
cJSON* cbytes = cJSON_CreateNumber(length);
|
||||
cJSON_AddItemToObject(column, "length", cbytes);
|
||||
|
@ -77,7 +77,7 @@ static char* buildCreateTableJson(SSchemaWrapper* schemaRow, SSchemaWrapper* sch
|
|||
cJSON_AddItemToObject(tag, "name", tname);
|
||||
cJSON* ttype = cJSON_CreateNumber(s->type);
|
||||
cJSON_AddItemToObject(tag, "type", ttype);
|
||||
if (s->type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (s->type == TSDB_DATA_TYPE_BINARY || s->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t length = s->bytes - VARSTR_HEADER_SIZE;
|
||||
cJSON* cbytes = cJSON_CreateNumber(length);
|
||||
cJSON_AddItemToObject(tag, "length", cbytes);
|
||||
|
@ -130,7 +130,7 @@ static char* buildAlterSTableJson(void* alterData, int32_t alterDataLen) {
|
|||
cJSON* colType = cJSON_CreateNumber(field->type);
|
||||
cJSON_AddItemToObject(json, "colType", colType);
|
||||
|
||||
if (field->type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (field->type == TSDB_DATA_TYPE_BINARY || field->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t length = field->bytes - VARSTR_HEADER_SIZE;
|
||||
cJSON* cbytes = cJSON_CreateNumber(length);
|
||||
cJSON_AddItemToObject(json, "colLength", cbytes);
|
||||
|
@ -155,7 +155,7 @@ static char* buildAlterSTableJson(void* alterData, int32_t alterDataLen) {
|
|||
cJSON_AddItemToObject(json, "colName", colName);
|
||||
cJSON* colType = cJSON_CreateNumber(field->type);
|
||||
cJSON_AddItemToObject(json, "colType", colType);
|
||||
if (field->type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (field->type == TSDB_DATA_TYPE_BINARY || field->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t length = field->bytes - VARSTR_HEADER_SIZE;
|
||||
cJSON* cbytes = cJSON_CreateNumber(length);
|
||||
cJSON_AddItemToObject(json, "colLength", cbytes);
|
||||
|
@ -457,7 +457,7 @@ static char* processAlterTable(SMqMetaRsp* metaRsp) {
|
|||
cJSON* colType = cJSON_CreateNumber(vAlterTbReq.type);
|
||||
cJSON_AddItemToObject(json, "colType", colType);
|
||||
|
||||
if (vAlterTbReq.type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (vAlterTbReq.type == TSDB_DATA_TYPE_BINARY || vAlterTbReq.type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t length = vAlterTbReq.bytes - VARSTR_HEADER_SIZE;
|
||||
cJSON* cbytes = cJSON_CreateNumber(length);
|
||||
cJSON_AddItemToObject(json, "colLength", cbytes);
|
||||
|
@ -478,7 +478,7 @@ static char* processAlterTable(SMqMetaRsp* metaRsp) {
|
|||
cJSON_AddItemToObject(json, "colName", colName);
|
||||
cJSON* colType = cJSON_CreateNumber(vAlterTbReq.colModType);
|
||||
cJSON_AddItemToObject(json, "colType", colType);
|
||||
if (vAlterTbReq.colModType == TSDB_DATA_TYPE_BINARY) {
|
||||
if (vAlterTbReq.colModType == TSDB_DATA_TYPE_BINARY || vAlterTbReq.colModType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t length = vAlterTbReq.colModBytes - VARSTR_HEADER_SIZE;
|
||||
cJSON* cbytes = cJSON_CreateNumber(length);
|
||||
cJSON_AddItemToObject(json, "colLength", cbytes);
|
||||
|
|
|
@ -555,7 +555,7 @@ static int32_t smlGenerateSchemaAction(SSchema *colField, SHashObj *colHash, SSm
|
|||
return TSDB_CODE_SML_INVALID_DATA;
|
||||
}
|
||||
|
||||
if ((colField[*index].type == TSDB_DATA_TYPE_VARCHAR &&
|
||||
if (((colField[*index].type == TSDB_DATA_TYPE_VARCHAR || colField[*index].type == TSDB_DATA_TYPE_GEOMETRY) &&
|
||||
(colField[*index].bytes - VARSTR_HEADER_SIZE) < kv->length) ||
|
||||
(colField[*index].type == TSDB_DATA_TYPE_NCHAR &&
|
||||
((colField[*index].bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE < kv->length))) {
|
||||
|
@ -586,7 +586,7 @@ static int32_t smlFindNearestPowerOf2(int32_t length, uint8_t type) {
|
|||
}
|
||||
}
|
||||
|
||||
if (type == TSDB_DATA_TYPE_BINARY && result > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) {
|
||||
if ((type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_GEOMETRY) && result > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) {
|
||||
result = TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE;
|
||||
} else if (type == TSDB_DATA_TYPE_NCHAR && result > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) {
|
||||
result = (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
|
@ -594,7 +594,7 @@ static int32_t smlFindNearestPowerOf2(int32_t length, uint8_t type) {
|
|||
|
||||
if (type == TSDB_DATA_TYPE_NCHAR) {
|
||||
result = result * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE;
|
||||
} else if (type == TSDB_DATA_TYPE_BINARY) {
|
||||
} else if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
result = result + VARSTR_HEADER_SIZE;
|
||||
}
|
||||
return result;
|
||||
|
@ -638,7 +638,7 @@ static int32_t smlCheckMeta(SSchema *schema, int32_t length, SArray *cols, bool
|
|||
}
|
||||
|
||||
static int32_t getBytes(uint8_t type, int32_t length) {
|
||||
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
|
||||
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return smlFindNearestPowerOf2(length, type);
|
||||
} else {
|
||||
return tDataTypes[type].bytes;
|
||||
|
|
|
@ -280,7 +280,9 @@ static const SSysDbTableSchema topicSchema[] = {
|
|||
{.name = "db_name", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
{.name = "create_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = false},
|
||||
{.name = "sql", .bytes = TSDB_SHOW_SQL_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
// TODO config
|
||||
{.name = "schema", .bytes = TSDB_SHOW_SCHEMA_JSON_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
{.name = "meta", .bytes = 4 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
{.name = "type", .bytes = 8 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY, .sysInfo = false},
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1927,7 +1927,8 @@ void blockDebugShowDataBlocks(const SArray* dataBlocks, const char* flag) {
|
|||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
printf(" %15lf |", *(double*)var);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_VARCHAR: {
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
char* pData = colDataGetVarData(pColInfoData, j);
|
||||
int32_t dataSize = TMIN(sizeof(pBuf) - 1, varDataLen(pData));
|
||||
memset(pBuf, 0, dataSize + 1);
|
||||
|
@ -2032,7 +2033,8 @@ char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf)
|
|||
len += snprintf(dumpBuf + len, size - len, " %15d |", *(bool*)var);
|
||||
if (len >= size - 1) return dumpBuf;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_VARCHAR: {
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
memset(pBuf, 0, sizeof(pBuf));
|
||||
char* pData = colDataGetVarData(pColInfoData, j);
|
||||
int32_t dataSize = TMIN(sizeof(pBuf), varDataLen(pData));
|
||||
|
@ -2138,7 +2140,8 @@ int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SSDataBlock* pDataB
|
|||
}
|
||||
break;
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_VARCHAR: { // TSDB_DATA_TYPE_BINARY
|
||||
case TSDB_DATA_TYPE_VARCHAR: // TSDB_DATA_TYPE_BINARY
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
if (colDataIsNull_s(pColInfoData, j)) {
|
||||
tdAppendColValToRow(&rb, PRIMARYKEY_TIMESTAMP_COL_ID + k, pColInfoData->info.type, TD_VTYPE_NULL, NULL,
|
||||
false, offset, k);
|
||||
|
|
|
@ -1148,7 +1148,8 @@ static void debugPrintTagVal(int8_t type, const void *val, int32_t vlen, const c
|
|||
switch (type) {
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
char tmpVal[32] = {0};
|
||||
strncpy(tmpVal, val, vlen > 31 ? 31 : vlen);
|
||||
printf("%s:%d type:%d vlen:%d, val:\"%s\"\n", tag, ln, (int32_t)type, vlen, tmpVal);
|
||||
|
@ -3542,5 +3543,6 @@ void (*tColDataCalcSMA[])(SColData *pColData, int64_t *sum, int64_t *max, int64_
|
|||
NULL, // TSDB_DATA_TYPE_VARBINARY
|
||||
NULL, // TSDB_DATA_TYPE_DECIMAL
|
||||
NULL, // TSDB_DATA_TYPE_BLOB
|
||||
NULL // TSDB_DATA_TYPE_MEDIUMBLOB
|
||||
NULL, // TSDB_DATA_TYPE_MEDIUMBLOB
|
||||
NULL // TSDB_DATA_TYPE_GEOMETRY
|
||||
};
|
||||
|
|
|
@ -126,6 +126,9 @@ void tdSCellValPrint(SCellVal *pVal, int8_t colType) {
|
|||
case TSDB_DATA_TYPE_JSON:
|
||||
printf("JSON ");
|
||||
break;
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
printf("GEOMETRY ");
|
||||
break;
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
printf("VARBIN ");
|
||||
break;
|
||||
|
@ -353,7 +356,7 @@ int32_t tdSTSRowNew(SArray *pArray, STSchema *pTSchema, STSRow **ppRow) {
|
|||
}
|
||||
} else {
|
||||
varDataLen += sizeof(VarDataLenT);
|
||||
if (pTColumn->type == TSDB_DATA_TYPE_VARCHAR) {
|
||||
if (pTColumn->type == TSDB_DATA_TYPE_VARCHAR || pTColumn->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
varDataLen += CHAR_BYTES;
|
||||
if (maxVarDataLen < CHAR_BYTES + sizeof(VarDataLenT)) {
|
||||
maxVarDataLen = CHAR_BYTES + sizeof(VarDataLenT);
|
||||
|
|
|
@ -296,7 +296,7 @@ static void writeDataToDisk(STSBuf* pTSBuf) {
|
|||
metaLen += (int32_t)taosWriteFile(pTSBuf->pFile, &pBlock->tag.nType, sizeof(pBlock->tag.nType));
|
||||
|
||||
int32_t trueLen = pBlock->tag.nLen;
|
||||
if (pBlock->tag.nType == TSDB_DATA_TYPE_BINARY || pBlock->tag.nType == TSDB_DATA_TYPE_NCHAR) {
|
||||
if (pBlock->tag.nType == TSDB_DATA_TYPE_BINARY || pBlock->tag.nType == TSDB_DATA_TYPE_NCHAR || pBlock->tag.nType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
metaLen += (int32_t)taosWriteFile(pTSBuf->pFile, &pBlock->tag.nLen, sizeof(pBlock->tag.nLen));
|
||||
metaLen += (int32_t)taosWriteFile(pTSBuf->pFile, pBlock->tag.pz, (size_t)pBlock->tag.nLen);
|
||||
} else if (pBlock->tag.nType == TSDB_DATA_TYPE_FLOAT) {
|
||||
|
@ -378,7 +378,7 @@ STSBlock* readDataFromDisk(STSBuf* pTSBuf, int32_t order, bool decomp) {
|
|||
|
||||
// NOTE: mix types tags are not supported
|
||||
size_t sz = 0;
|
||||
if (pBlock->tag.nType == TSDB_DATA_TYPE_BINARY || pBlock->tag.nType == TSDB_DATA_TYPE_NCHAR) {
|
||||
if (pBlock->tag.nType == TSDB_DATA_TYPE_BINARY || pBlock->tag.nType == TSDB_DATA_TYPE_NCHAR || pBlock->tag.nType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
char* tp = taosMemoryRealloc(pBlock->tag.pz, pBlock->tag.nLen + 1);
|
||||
ASSERT(tp != NULL);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "ttypes.h"
|
||||
#include "tcompression.h"
|
||||
|
||||
const int32_t TYPE_BYTES[16] = {
|
||||
const int32_t TYPE_BYTES[17] = {
|
||||
-1, // TSDB_DATA_TYPE_NULL
|
||||
CHAR_BYTES, // TSDB_DATA_TYPE_BOOL
|
||||
CHAR_BYTES, // TSDB_DATA_TYPE_TINYINT
|
||||
|
@ -34,6 +34,7 @@ const int32_t TYPE_BYTES[16] = {
|
|||
INT_BYTES, // TSDB_DATA_TYPE_UINT
|
||||
sizeof(uint64_t), // TSDB_DATA_TYPE_UBIGINT
|
||||
TSDB_MAX_JSON_TAG_LEN, // TSDB_DATA_TYPE_JSON
|
||||
sizeof(VarDataOffsetT), // TSDB_DATA_TYPE_GEOMETRY
|
||||
};
|
||||
|
||||
tDataTypeDescriptor tDataTypes[TSDB_DATA_TYPE_MAX] = {
|
||||
|
@ -56,6 +57,7 @@ tDataTypeDescriptor tDataTypes[TSDB_DATA_TYPE_MAX] = {
|
|||
{TSDB_DATA_TYPE_UINT, 12, INT_BYTES, "INT UNSIGNED", 0, UINT32_MAX, tsCompressInt, tsDecompressInt},
|
||||
{TSDB_DATA_TYPE_UBIGINT, 15, LONG_BYTES, "BIGINT UNSIGNED", 0, UINT64_MAX, tsCompressBigint, tsDecompressBigint},
|
||||
{TSDB_DATA_TYPE_JSON, 4, TSDB_MAX_JSON_TAG_LEN, "JSON", 0, 0, tsCompressString, tsDecompressString},
|
||||
{TSDB_DATA_TYPE_GEOMETRY, 8, 1, "GEOMETRY", 0, 0, tsCompressString, tsDecompressString},
|
||||
};
|
||||
|
||||
static float floatMin = -FLT_MAX, floatMax = FLT_MAX;
|
||||
|
@ -125,6 +127,7 @@ void assignVal(char *val, const char *src, int32_t len, int32_t type) {
|
|||
*((int64_t *)val) = GET_INT64_VAL(src);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
varDataCopy(val, src);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
|
|
|
@ -121,7 +121,8 @@ void taosVariantCreateFromBinary(SVariant *pVar, const char *pz, size_t len, uin
|
|||
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_BINARY: { // todo refactor, extract a method
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: { // todo refactor, extract a method
|
||||
pVar->pz = taosMemoryCalloc(len + 1, sizeof(char));
|
||||
memcpy(pVar->pz, pz, len);
|
||||
pVar->nLen = (int32_t)len;
|
||||
|
@ -140,7 +141,7 @@ void taosVariantDestroy(SVariant *pVar) {
|
|||
if (pVar == NULL) return;
|
||||
|
||||
if (pVar->nType == TSDB_DATA_TYPE_BINARY || pVar->nType == TSDB_DATA_TYPE_NCHAR ||
|
||||
pVar->nType == TSDB_DATA_TYPE_JSON) {
|
||||
pVar->nType == TSDB_DATA_TYPE_JSON || pVar->nType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
taosMemoryFreeClear(pVar->pz);
|
||||
pVar->nLen = 0;
|
||||
}
|
||||
|
@ -152,7 +153,7 @@ void taosVariantAssign(SVariant *pDst, const SVariant *pSrc) {
|
|||
|
||||
pDst->nType = pSrc->nType;
|
||||
if (pSrc->nType == TSDB_DATA_TYPE_BINARY || pSrc->nType == TSDB_DATA_TYPE_NCHAR ||
|
||||
pSrc->nType == TSDB_DATA_TYPE_JSON) {
|
||||
pSrc->nType == TSDB_DATA_TYPE_JSON || pSrc->nType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t len = pSrc->nLen + TSDB_NCHAR_SIZE;
|
||||
char *p = taosMemoryRealloc(pDst->pz, len);
|
||||
ASSERT(p);
|
||||
|
@ -184,7 +185,7 @@ int32_t taosVariantCompare(const SVariant *p1, const SVariant *p2) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (p1->nType == TSDB_DATA_TYPE_BINARY || p1->nType == TSDB_DATA_TYPE_NCHAR) {
|
||||
if (p1->nType == TSDB_DATA_TYPE_BINARY || p1->nType == TSDB_DATA_TYPE_NCHAR || p1->nType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
if (p1->nLen == p2->nLen) {
|
||||
return memcmp(p1->pz, p2->pz, p1->nLen);
|
||||
} else {
|
||||
|
@ -237,6 +238,7 @@ char *taosVariantGet(SVariant *pVar, int32_t type) {
|
|||
return (char *)&pVar->f;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
return (char *)pVar->pz;
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
return (char *)pVar->ucs4;
|
||||
|
|
|
@ -235,7 +235,8 @@ int32_t debugPrintSColVal(SColVal *cv, int8_t type) {
|
|||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
printf("%lf ", cv->value.d);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_VARCHAR: {
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
char tv[15] = {0};
|
||||
snprintf(tv, 15, "%s", cv->value.pData);
|
||||
printf("%s ", tv);
|
||||
|
@ -337,7 +338,8 @@ static int32_t checkSColVal(const char *rawVal, SColVal *cv, int8_t type) {
|
|||
sscanf(rawVal, "%lf", &rawSVal.d);
|
||||
EXPECT_DOUBLE_EQ(cv->value.d, rawSVal.d);
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_VARCHAR: {
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
EXPECT_STRCASEEQ(rawVal, (const char *)cv->value.pData);
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||
|
|
|
@ -32,6 +32,7 @@ bool mndIsDbReady(SMnode *pMnode, SDbObj *pDb);
|
|||
|
||||
SSdbRaw *mndDbActionEncode(SDbObj *pDb);
|
||||
const char *mndGetDbStr(const char *src);
|
||||
const char *mndGetStableStr(const char *src);
|
||||
|
||||
int32_t mndProcessCompactDbReq(SRpcMsg *pReq);
|
||||
|
||||
|
|
|
@ -521,6 +521,7 @@ typedef struct {
|
|||
char* physicalPlan;
|
||||
SSchemaWrapper schema;
|
||||
int64_t stbUid;
|
||||
char stbName[TSDB_TABLE_FNAME_LEN];
|
||||
// forbid condition
|
||||
int64_t ntbUid;
|
||||
SArray* ntbColIds;
|
||||
|
|
|
@ -1543,6 +1543,13 @@ const char *mndGetDbStr(const char *src) {
|
|||
return pos;
|
||||
}
|
||||
|
||||
const char *mndGetStableStr(const char *src) {
|
||||
char *pos = strstr(src, TS_PATH_DELIMITER);
|
||||
if (pos != NULL) ++pos;
|
||||
if (pos == NULL) return src;
|
||||
return mndGetDbStr(pos);
|
||||
}
|
||||
|
||||
static int64_t getValOfDiffPrecision(int8_t unit, int64_t val) {
|
||||
int64_t v = 0;
|
||||
switch (unit) {
|
||||
|
|
|
@ -285,6 +285,7 @@ void dumpTopic(SSdb *pSdb, SJson *json) {
|
|||
tjsonAddStringToObject(item, "subType", i642str(pObj->subType));
|
||||
tjsonAddStringToObject(item, "withMeta", i642str(pObj->withMeta));
|
||||
tjsonAddStringToObject(item, "stbUid", i642str(pObj->stbUid));
|
||||
tjsonAddStringToObject(item, "stbName", mndGetStableStr(pObj->stbName));
|
||||
tjsonAddStringToObject(item, "sqlLen", i642str(pObj->sqlLen));
|
||||
tjsonAddStringToObject(item, "astLen", i642str(pObj->astLen));
|
||||
tjsonAddStringToObject(item, "sqlLen", i642str(pObj->sqlLen));
|
||||
|
|
|
@ -562,7 +562,7 @@ static void *mnodeGenTypeStr(char *buf, int32_t buflen, uint8_t type, int32_t le
|
|||
return msg;
|
||||
}
|
||||
|
||||
if (type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t bytes = len > 0 ? (int32_t)(len - VARSTR_HEADER_SIZE) : len;
|
||||
|
||||
snprintf(buf, buflen - 1, "%s(%d)", tDataTypes[type].name, type == TSDB_DATA_TYPE_NCHAR ? bytes / 4 : bytes);
|
||||
|
|
|
@ -1473,7 +1473,7 @@ static int32_t mndAlterStbTagBytes(SMnode *pMnode, const SStbObj *pOld, SStbObj
|
|||
|
||||
SSchema *pTag = pNew->pTags + tag;
|
||||
|
||||
if (!(pTag->type == TSDB_DATA_TYPE_BINARY || pTag->type == TSDB_DATA_TYPE_NCHAR)) {
|
||||
if (!(pTag->type == TSDB_DATA_TYPE_BINARY || pTag->type == TSDB_DATA_TYPE_NCHAR || pTag->type == TSDB_DATA_TYPE_GEOMETRY)) {
|
||||
terrno = TSDB_CODE_MND_INVALID_STB_OPTION;
|
||||
return -1;
|
||||
}
|
||||
|
@ -1593,7 +1593,7 @@ static int32_t mndAlterStbColumnBytes(SMnode *pMnode, const SStbObj *pOld, SStbO
|
|||
}
|
||||
|
||||
SSchema *pCol = pNew->pColumns + col;
|
||||
if (!(pCol->type == TSDB_DATA_TYPE_BINARY || pCol->type == TSDB_DATA_TYPE_NCHAR)) {
|
||||
if (!(pCol->type == TSDB_DATA_TYPE_BINARY || pCol->type == TSDB_DATA_TYPE_NCHAR || pCol->type == TSDB_DATA_TYPE_GEOMETRY)) {
|
||||
terrno = TSDB_CODE_MND_INVALID_STB_OPTION;
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -109,6 +109,7 @@ SSdbRaw *mndTopicActionEncode(SMqTopicObj *pTopic) {
|
|||
SDB_SET_INT8(pRaw, dataPos, pTopic->withMeta, TOPIC_ENCODE_OVER);
|
||||
|
||||
SDB_SET_INT64(pRaw, dataPos, pTopic->stbUid, TOPIC_ENCODE_OVER);
|
||||
SDB_SET_BINARY(pRaw, dataPos, pTopic->stbName, TSDB_TABLE_FNAME_LEN, TOPIC_ENCODE_OVER);
|
||||
SDB_SET_INT32(pRaw, dataPos, pTopic->sqlLen, TOPIC_ENCODE_OVER);
|
||||
SDB_SET_BINARY(pRaw, dataPos, pTopic->sql, pTopic->sqlLen, TOPIC_ENCODE_OVER);
|
||||
SDB_SET_INT32(pRaw, dataPos, pTopic->astLen, TOPIC_ENCODE_OVER);
|
||||
|
@ -196,6 +197,7 @@ SSdbRow *mndTopicActionDecode(SSdbRaw *pRaw) {
|
|||
SDB_GET_INT8(pRaw, dataPos, &pTopic->withMeta, TOPIC_DECODE_OVER);
|
||||
|
||||
SDB_GET_INT64(pRaw, dataPos, &pTopic->stbUid, TOPIC_DECODE_OVER);
|
||||
SDB_GET_BINARY(pRaw, dataPos, pTopic->stbName, TSDB_TABLE_FNAME_LEN, TOPIC_DECODE_OVER);
|
||||
SDB_GET_INT32(pRaw, dataPos, &pTopic->sqlLen, TOPIC_DECODE_OVER);
|
||||
pTopic->sql = taosMemoryCalloc(pTopic->sqlLen, sizeof(char));
|
||||
if (pTopic->sql == NULL) {
|
||||
|
@ -460,6 +462,7 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq *
|
|||
return -1;
|
||||
}
|
||||
|
||||
strcpy(topicObj.stbName, pCreate->subStbName);
|
||||
topicObj.stbUid = pStb->uid;
|
||||
mndReleaseStb(pMnode, pStb);
|
||||
}
|
||||
|
@ -830,6 +833,43 @@ int32_t mndGetNumOfTopics(SMnode *pMnode, char *dbName, int32_t *pNumOfTopics) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void schemaToJson(SSchema *schema, int32_t nCols, char *schemaJson){
|
||||
char* string = NULL;
|
||||
cJSON* columns = cJSON_CreateArray();
|
||||
if (columns == NULL) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < nCols; i++) {
|
||||
cJSON* column = cJSON_CreateObject();
|
||||
SSchema* s = schema + i;
|
||||
cJSON* cname = cJSON_CreateString(s->name);
|
||||
cJSON_AddItemToObject(column, "name", cname);
|
||||
cJSON* ctype = cJSON_CreateString(tDataTypes[s->type].name);
|
||||
cJSON_AddItemToObject(column, "type", ctype);
|
||||
int32_t length = 0;
|
||||
if (s->type == TSDB_DATA_TYPE_BINARY) {
|
||||
length = s->bytes - VARSTR_HEADER_SIZE;
|
||||
} else if (s->type == TSDB_DATA_TYPE_NCHAR || s->type == TSDB_DATA_TYPE_JSON) {
|
||||
length = (s->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
|
||||
} else{
|
||||
length = s->bytes;
|
||||
}
|
||||
cJSON* cbytes = cJSON_CreateNumber(length);
|
||||
cJSON_AddItemToObject(column, "length", cbytes);
|
||||
cJSON_AddItemToArray(columns, column);
|
||||
}
|
||||
string = cJSON_PrintUnformatted(columns);
|
||||
cJSON_Delete(columns);
|
||||
|
||||
size_t len = strlen(string);
|
||||
if(string && len <= TSDB_SHOW_SCHEMA_JSON_LEN){
|
||||
STR_TO_VARSTR(schemaJson, string);
|
||||
}else{
|
||||
mError("mndRetrieveTopic build schema error json:%p, json len:%zu", string, len);
|
||||
}
|
||||
taosMemoryFree(string);
|
||||
}
|
||||
|
||||
static int32_t mndRetrieveTopic(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rowsCapacity) {
|
||||
SMnode *pMnode = pReq->info.node;
|
||||
SSdb *pSdb = pMnode->pSdb;
|
||||
|
@ -868,6 +908,49 @@ static int32_t mndRetrieveTopic(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl
|
|||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)sql, false);
|
||||
|
||||
char *schemaJson = taosMemoryMalloc(TSDB_SHOW_SCHEMA_JSON_LEN + VARSTR_HEADER_SIZE);
|
||||
if(pTopic->subType == TOPIC_SUB_TYPE__COLUMN){
|
||||
schemaToJson(pTopic->schema.pSchema, pTopic->schema.nCols, schemaJson);
|
||||
}else if(pTopic->subType == TOPIC_SUB_TYPE__TABLE){
|
||||
SStbObj *pStb = mndAcquireStb(pMnode, pTopic->stbName);
|
||||
if (pStb == NULL) {
|
||||
terrno = TSDB_CODE_MND_STB_NOT_EXIST;
|
||||
taosMemoryFree(schemaJson);
|
||||
return -1;
|
||||
}
|
||||
schemaToJson(pStb->pColumns, pStb->numOfColumns, schemaJson);
|
||||
|
||||
mndReleaseStb(pMnode, pStb);
|
||||
}else{
|
||||
STR_TO_VARSTR(schemaJson, "NULL");
|
||||
}
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)schemaJson, false);
|
||||
taosMemoryFree(schemaJson);
|
||||
|
||||
char mete[4 + VARSTR_HEADER_SIZE] = {0};
|
||||
if(pTopic->withMeta){
|
||||
STR_TO_VARSTR(mete, "yes");
|
||||
}else{
|
||||
STR_TO_VARSTR(mete, "no");
|
||||
}
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)mete, false);
|
||||
|
||||
char type[8 + VARSTR_HEADER_SIZE] = {0};
|
||||
if(pTopic->subType == TOPIC_SUB_TYPE__COLUMN){
|
||||
STR_TO_VARSTR(type, "column");
|
||||
}else if(pTopic->subType == TOPIC_SUB_TYPE__TABLE){
|
||||
STR_TO_VARSTR(type, "stable");
|
||||
}else{
|
||||
STR_TO_VARSTR(type, "db");
|
||||
}
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
colDataSetVal(pColInfo, numOfRows, (const char *)type, false);
|
||||
|
||||
numOfRows++;
|
||||
sdbRelease(pSdb, pTopic);
|
||||
}
|
||||
|
|
|
@ -2117,27 +2117,32 @@ int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb
|
|||
mInfo("db:%s, vgId:%d, will add 2 vnodes, vn:0 dnode:%d", pVgroup->dbName, pVgroup->vgId,
|
||||
pVgroup->vnodeGid[0].dnodeId);
|
||||
|
||||
//add first
|
||||
//add second
|
||||
if (mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray) != 0) return -1;
|
||||
|
||||
//learner stage
|
||||
newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
|
||||
newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_LEARNER;
|
||||
if (mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[0].dnodeId) != 0)
|
||||
return -1;
|
||||
|
||||
if (mndAddCreateVnodeAction(pMnode, pTrans, pNewDb, &newVgroup, &newVgroup.vnodeGid[1]) != 0) return -1;
|
||||
|
||||
//follower stage
|
||||
newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
|
||||
if (mndAddAlterVnodeTypeAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[1].dnodeId) != 0)
|
||||
return -1;
|
||||
if (mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[0].dnodeId) != 0)
|
||||
return -1;
|
||||
|
||||
if (mndAddAlterVnodeConfirmAction(pMnode, pTrans, pNewDb, &newVgroup) != 0) return -1;
|
||||
|
||||
//add second
|
||||
//add third
|
||||
if (mndAddVnodeToVgroup(pMnode, pTrans, &newVgroup, pArray) != 0) return -1;
|
||||
|
||||
newVgroup.vnodeGid[0].nodeRole = TAOS_SYNC_ROLE_VOTER;
|
||||
newVgroup.vnodeGid[1].nodeRole = TAOS_SYNC_ROLE_VOTER;
|
||||
newVgroup.vnodeGid[2].nodeRole = TAOS_SYNC_ROLE_VOTER;
|
||||
|
||||
if (mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[0].dnodeId) != 0)
|
||||
return -1;
|
||||
if (mndAddAlterVnodeReplicaAction(pMnode, pTrans, pNewDb, &newVgroup, newVgroup.vnodeGid[1].dnodeId) != 0)
|
||||
|
|
|
@ -1767,6 +1767,9 @@ static bool overlapWithDelSkyline(STableBlockScanInfo* pBlockScanInfo, const SDa
|
|||
if (p->ts > pBlock->minKey.ts && index > 0) {
|
||||
index -= 1;
|
||||
} else { // find the first point that is smaller than the minKey.ts of dataBlock.
|
||||
if (p->ts == pBlock->minKey.ts && p->version < pBlock->maxVer && index > 0) {
|
||||
index -= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,4 +17,5 @@ add_subdirectory(executor)
|
|||
add_subdirectory(stream)
|
||||
add_subdirectory(planner)
|
||||
add_subdirectory(qworker)
|
||||
add_subdirectory(geometry)
|
||||
add_subdirectory(command)
|
|
@ -48,6 +48,7 @@ static int32_t buildRetrieveTableRsp(SSDataBlock* pBlock, int32_t numOfCols, SRe
|
|||
static int32_t getSchemaBytes(const SSchema* pSchema) {
|
||||
switch (pSchema->type) {
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
return (pSchema->bytes - VARSTR_HEADER_SIZE);
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
|
@ -448,7 +449,7 @@ void appendColumnFields(char* buf, int32_t* len, STableCfg* pCfg) {
|
|||
SSchema* pSchema = pCfg->pSchemas + i;
|
||||
char type[32];
|
||||
sprintf(type, "%s", tDataTypes[pSchema->type].name);
|
||||
if (TSDB_DATA_TYPE_VARCHAR == pSchema->type) {
|
||||
if (TSDB_DATA_TYPE_VARCHAR == pSchema->type || TSDB_DATA_TYPE_GEOMETRY == pSchema->type) {
|
||||
sprintf(type + strlen(type), "(%d)", (int32_t)(pSchema->bytes - VARSTR_HEADER_SIZE));
|
||||
} else if (TSDB_DATA_TYPE_NCHAR == pSchema->type) {
|
||||
sprintf(type + strlen(type), "(%d)", (int32_t)((pSchema->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE));
|
||||
|
@ -463,7 +464,7 @@ void appendTagFields(char* buf, int32_t* len, STableCfg* pCfg) {
|
|||
SSchema* pSchema = pCfg->pSchemas + pCfg->numOfColumns + i;
|
||||
char type[32];
|
||||
sprintf(type, "%s", tDataTypes[pSchema->type].name);
|
||||
if (TSDB_DATA_TYPE_VARCHAR == pSchema->type) {
|
||||
if (TSDB_DATA_TYPE_VARCHAR == pSchema->type || TSDB_DATA_TYPE_GEOMETRY == pSchema->type) {
|
||||
sprintf(type + strlen(type), "(%d)", (int32_t)(pSchema->bytes - VARSTR_HEADER_SIZE));
|
||||
} else if (TSDB_DATA_TYPE_NCHAR == pSchema->type) {
|
||||
sprintf(type + strlen(type), "(%d)", (int32_t)((pSchema->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE));
|
||||
|
@ -539,7 +540,7 @@ int32_t appendTagValues(char* buf, int32_t* len, STableCfg* pCfg) {
|
|||
}
|
||||
|
||||
/*
|
||||
if (type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
if (pTagVal->nData > 0) {
|
||||
if (num) {
|
||||
*len += sprintf(buf + VARSTR_HEADER_SIZE + *len, ", ");
|
||||
|
|
|
@ -275,7 +275,7 @@ static int32_t doCreateConstantValColumnInfo(SInputColumnInfoData* pInput, SFunc
|
|||
for (int32_t i = 0; i < numOfRows; ++i) {
|
||||
colDataSetDouble(pColInfo, i, &v);
|
||||
}
|
||||
} else if (type == TSDB_DATA_TYPE_VARCHAR) {
|
||||
} else if (type == TSDB_DATA_TYPE_VARCHAR || type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
char* tmp = taosMemoryMalloc(pFuncParam->param.nLen + VARSTR_HEADER_SIZE);
|
||||
STR_WITH_SIZE_TO_VARSTR(tmp, pFuncParam->param.pz, pFuncParam->param.nLen);
|
||||
for (int32_t i = 0; i < numOfRows; ++i) {
|
||||
|
|
|
@ -343,7 +343,8 @@ void doTimeWindowInterpolation(SArray* pPrevValues, SArray* pDataBlock, TSKEY pr
|
|||
pCtx[k].end.key = curTs;
|
||||
pCtx[k].end.val = v2;
|
||||
|
||||
if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) {
|
||||
if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR ||
|
||||
pColInfo->info.type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
if (prevRowIndex == -1) {
|
||||
// pCtx[k].start.ptr = (char*)pRuntimeEnv->prevRow[index];
|
||||
} else {
|
||||
|
|
|
@ -66,7 +66,7 @@ SSDataBlock* getSingleColDummyBlock(void* param) {
|
|||
colInfo.info.type = pInfo->type;
|
||||
if (pInfo->type == TSDB_DATA_TYPE_NCHAR) {
|
||||
colInfo.info.bytes = TSDB_NCHAR_SIZE * VARCOUNT + VARSTR_HEADER_SIZE;
|
||||
} else if (pInfo->type == TSDB_DATA_TYPE_BINARY) {
|
||||
} else if (pInfo->type == TSDB_DATA_TYPE_BINARY || pInfo->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
colInfo.info.bytes = VARCOUNT + VARSTR_HEADER_SIZE;
|
||||
} else {
|
||||
colInfo.info.bytes = tDataTypes[pInfo->type].bytes;
|
||||
|
@ -94,7 +94,7 @@ SSDataBlock* getSingleColDummyBlock(void* param) {
|
|||
colDataSetVal(pColInfo, i, reinterpret_cast<const char*>(str), false);
|
||||
pBlock->info.hasVarCol = true;
|
||||
printf("nchar: %s\n", strOri);
|
||||
} else if (pInfo->type == TSDB_DATA_TYPE_BINARY) {
|
||||
} else if (pInfo->type == TSDB_DATA_TYPE_BINARY || pInfo->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t size = taosRand() % VARCOUNT;
|
||||
char str[64] = {0};
|
||||
taosRandStr(varDataVal(str), size);
|
||||
|
@ -317,7 +317,7 @@ TEST(testCase, external_mem_sort_Test) {
|
|||
char buf[128] = {0};
|
||||
int32_t len = taosUcs4ToMbs((TdUcs4 *)varDataVal(v), varDataLen(v), buf);
|
||||
printf("%d: %s\n", row++, buf);
|
||||
}else if(pInfo[i].type == TSDB_DATA_TYPE_BINARY){
|
||||
}else if(pInfo[i].type == TSDB_DATA_TYPE_BINARY || pInfo[i]->type == TSDB_DATA_TYPE_GEOMETRY){
|
||||
char buf[128] = {0};
|
||||
memcpy(buf, varDataVal(v), varDataLen(v));
|
||||
printf("%d: %s\n", row++, buf);
|
||||
|
|
|
@ -32,6 +32,7 @@ target_link_libraries(
|
|||
PRIVATE nodes
|
||||
PRIVATE qcom
|
||||
PRIVATE scalar
|
||||
PRIVATE geometry
|
||||
PRIVATE transport
|
||||
PRIVATE stream ${LINK_JEMALLOC}
|
||||
PUBLIC uv_a
|
||||
|
|
|
@ -50,6 +50,7 @@ extern "C" {
|
|||
#define FUNC_MGT_KEEP_ORDER_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(21)
|
||||
#define FUNC_MGT_CUMULATIVE_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(22)
|
||||
#define FUNC_MGT_INTERP_PC_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(23)
|
||||
#define FUNC_MGT_GEOMETRY_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(24)
|
||||
|
||||
#define FUNC_MGT_TEST_MASK(val, mask) (((val) & (mask)) != 0)
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "cJSON.h"
|
||||
#include "querynodes.h"
|
||||
#include "scalar.h"
|
||||
#include "geomFunc.h"
|
||||
#include "taoserror.h"
|
||||
#include "ttime.h"
|
||||
|
||||
|
@ -2107,6 +2108,70 @@ static int32_t translateToJson(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateInStrOutGeom(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||
if (!IS_STR_DATA_TYPE(para1Type) && !IS_NULL_TYPE(para1Type)) {
|
||||
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_GEOMETRY].bytes, .type = TSDB_DATA_TYPE_GEOMETRY};
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateInGeomOutStr(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||
if (para1Type != TSDB_DATA_TYPE_GEOMETRY && !IS_NULL_TYPE(para1Type)) {
|
||||
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_VARCHAR].bytes, .type = TSDB_DATA_TYPE_VARCHAR};
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateIn2NumOutGeom(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
if (2 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||
uint8_t para2Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
|
||||
if ((!IS_NUMERIC_TYPE(para1Type) && !IS_NULL_TYPE(para1Type)) ||
|
||||
(!IS_NUMERIC_TYPE(para2Type) && !IS_NULL_TYPE(para2Type))) {
|
||||
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_GEOMETRY].bytes, .type = TSDB_DATA_TYPE_GEOMETRY};
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateIn2GeomOutBool(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
if (2 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||
uint8_t para2Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
|
||||
if ((para1Type != TSDB_DATA_TYPE_GEOMETRY && !IS_NULL_TYPE(para1Type)) ||
|
||||
(para2Type != TSDB_DATA_TYPE_GEOMETRY && !IS_NULL_TYPE(para2Type))) {
|
||||
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||
}
|
||||
|
||||
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes, .type = TSDB_DATA_TYPE_BOOL};
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateSelectValue(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
pFunc->node.resType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -3362,6 +3427,96 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.sprocessFunc = NULL,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "st_geomfromtext",
|
||||
.type = FUNCTION_TYPE_GEOM_FROM_TEXT,
|
||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_GEOMETRY_FUNC,
|
||||
.translateFunc = translateInStrOutGeom,
|
||||
.getEnvFunc = NULL,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = geomFromTextFunction,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "st_astext",
|
||||
.type = FUNCTION_TYPE_AS_TEXT,
|
||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_GEOMETRY_FUNC,
|
||||
.translateFunc = translateInGeomOutStr,
|
||||
.getEnvFunc = NULL,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = asTextFunction,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "st_makepoint",
|
||||
.type = FUNCTION_TYPE_MAKE_POINT,
|
||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_GEOMETRY_FUNC,
|
||||
.translateFunc = translateIn2NumOutGeom,
|
||||
.getEnvFunc = NULL,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = makePointFunction,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "st_intersects",
|
||||
.type = FUNCTION_TYPE_INTERSECTS,
|
||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_GEOMETRY_FUNC,
|
||||
.translateFunc = translateIn2GeomOutBool,
|
||||
.getEnvFunc = NULL,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = intersectsFunction,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "st_equals",
|
||||
.type = FUNCTION_TYPE_EQUALS,
|
||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_GEOMETRY_FUNC,
|
||||
.translateFunc = translateIn2GeomOutBool,
|
||||
.getEnvFunc = NULL,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = equalsFunction,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "st_touches",
|
||||
.type = FUNCTION_TYPE_TOUCHES,
|
||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_GEOMETRY_FUNC,
|
||||
.translateFunc = translateIn2GeomOutBool,
|
||||
.getEnvFunc = NULL,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = touchesFunction,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "st_covers",
|
||||
.type = FUNCTION_TYPE_COVERS,
|
||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_GEOMETRY_FUNC,
|
||||
.translateFunc = translateIn2GeomOutBool,
|
||||
.getEnvFunc = NULL,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = coversFunction,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "st_contains",
|
||||
.type = FUNCTION_TYPE_CONTAINS,
|
||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_GEOMETRY_FUNC,
|
||||
.translateFunc = translateIn2GeomOutBool,
|
||||
.getEnvFunc = NULL,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = containsFunction,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "st_containsproperly",
|
||||
.type = FUNCTION_TYPE_CONTAINS_PROPERLY,
|
||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_GEOMETRY_FUNC,
|
||||
.translateFunc = translateIn2GeomOutBool,
|
||||
.getEnvFunc = NULL,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = containsProperlyFunction,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
aux_source_directory(src GEOMETRY_SRC)
|
||||
|
||||
add_library(geometry STATIC ${GEOMETRY_SRC})
|
||||
target_include_directories(
|
||||
geometry
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/libs/geometry"
|
||||
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../scalar/inc"
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
geometry
|
||||
PRIVATE os util nodes function scalar qcom
|
||||
)
|
||||
|
||||
if(${BUILD_TEST})
|
||||
ADD_SUBDIRECTORY(test)
|
||||
endif(${BUILD_TEST})
|
|
@ -0,0 +1,444 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <geos_c.h>
|
||||
#include "geosWrapper.h"
|
||||
#include "geomFunc.h"
|
||||
#include "querynodes.h"
|
||||
#include "tdatablock.h"
|
||||
#include "sclInt.h"
|
||||
#include "sclvector.h"
|
||||
|
||||
typedef int32_t (*_geomDoRelationFunc_t)(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res);
|
||||
|
||||
typedef int32_t (*_geomInitCtxFunc_t)();
|
||||
typedef int32_t (*_geomExecuteOneParamFunc_t)(SColumnInfoData *pInputData, int32_t i, SColumnInfoData *pOutputData);
|
||||
typedef int32_t (*_geomExecuteTwoParamsFunc_t)(SColumnInfoData *pInputData[], int32_t iLeft, int32_t iRight,
|
||||
SColumnInfoData *pOutputData);
|
||||
|
||||
// output is with VARSTR format
|
||||
// need to call taosMemoryFree(*output) later
|
||||
int32_t doMakePointFunc(double x, double y, unsigned char **output) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
|
||||
unsigned char *outputGeom = NULL;
|
||||
size_t size = 0;
|
||||
code = doMakePoint(x, y, &outputGeom, &size);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
*output = taosMemoryCalloc(1, size + VARSTR_HEADER_SIZE);
|
||||
if (*output == NULL) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
memcpy(varDataVal(*output), outputGeom, size);
|
||||
varDataSetLen(*output, size);
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
|
||||
_exit:
|
||||
geosFreeBuffer(outputGeom);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
// both input and output are with VARSTR format
|
||||
// need to call taosMemoryFree(*output) later
|
||||
int32_t doGeomFromTextFunc(const char *input, unsigned char **output) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
|
||||
if ((varDataLen(input)) == 0) { //empty value
|
||||
*output = NULL;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// make input as a zero ending string
|
||||
char *end = varDataVal(input) + varDataLen(input);
|
||||
char endValue = *end;
|
||||
*end = 0;
|
||||
|
||||
unsigned char *outputGeom = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
code = doGeomFromText(varDataVal(input), &outputGeom, &size);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
*output = taosMemoryCalloc(1, size + VARSTR_HEADER_SIZE);
|
||||
if (*output == NULL) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
memcpy(varDataVal(*output), outputGeom, size);
|
||||
varDataSetLen(*output, size);
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
|
||||
_exit:
|
||||
geosFreeBuffer(outputGeom);
|
||||
|
||||
*end = endValue; //recover the input string
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
// both input and output are with VARSTR format
|
||||
// need to call taosMemoryFree(*output) later
|
||||
int32_t doAsTextFunc(unsigned char *input, char **output) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
|
||||
if ((varDataLen(input)) == 0) { //empty value
|
||||
*output = NULL;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
char *outputWKT = NULL;
|
||||
code = doAsText(varDataVal(input), varDataLen(input), &outputWKT);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
size_t size = strlen(outputWKT);
|
||||
*output = taosMemoryCalloc(1, size + VARSTR_HEADER_SIZE);
|
||||
if (*output == NULL) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
memcpy(varDataVal(*output), outputWKT, size);
|
||||
varDataSetLen(*output, size);
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
|
||||
_exit:
|
||||
geosFreeBuffer(outputWKT);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t executeMakePointFunc(SColumnInfoData *pInputData[], int32_t iLeft, int32_t iRight,
|
||||
SColumnInfoData *pOutputData) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
|
||||
_getDoubleValue_fn_t getDoubleValueFn[2];
|
||||
getDoubleValueFn[0]= getVectorDoubleValueFn(pInputData[0]->info.type);
|
||||
getDoubleValueFn[1]= getVectorDoubleValueFn(pInputData[1]->info.type);
|
||||
|
||||
unsigned char *output = NULL;
|
||||
code = doMakePointFunc(getDoubleValueFn[0](pInputData[0]->pData, iLeft), getDoubleValueFn[1](pInputData[1]->pData, iRight), &output);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
colDataAppend(pOutputData, TMAX(iLeft, iRight), output, (output == NULL));
|
||||
|
||||
_exit:
|
||||
if (output) {
|
||||
taosMemoryFree(output);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t executeGeomFromTextFunc(SColumnInfoData *pInputData, int32_t i, SColumnInfoData *pOutputData) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
|
||||
char *input = colDataGetData(pInputData, i);
|
||||
unsigned char *output = NULL;
|
||||
code = doGeomFromTextFunc(input, &output);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
colDataAppend(pOutputData, i, output, (output == NULL));
|
||||
|
||||
_exit:
|
||||
if (output) {
|
||||
taosMemoryFree(output);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t executeAsTextFunc(SColumnInfoData *pInputData, int32_t i, SColumnInfoData *pOutputData) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
|
||||
unsigned char *input = colDataGetData(pInputData, i);
|
||||
char *output = NULL;
|
||||
code = doAsTextFunc(input, &output);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
colDataAppend(pOutputData, i, output, (output == NULL));
|
||||
|
||||
_exit:
|
||||
if (output) {
|
||||
taosMemoryFree(output);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t executeRelationFunc(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1,
|
||||
const GEOSGeometry *geom2, int32_t i,
|
||||
bool swapped, SColumnInfoData *pOutputData,
|
||||
_geomDoRelationFunc_t doRelationFn) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
char res = 0;
|
||||
|
||||
if (!geom1 || !geom2) { //if empty input value
|
||||
res = -1;
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
}
|
||||
else {
|
||||
code = doRelationFn(geom1, preparedGeom1, geom2, swapped, &res);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
colDataAppend(pOutputData, i, &res, (res==-1));
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t geomOneParamFunction(SScalarParam *pInput, SScalarParam *pOutput,
|
||||
_geomInitCtxFunc_t initCtxFn, _geomExecuteOneParamFunc_t executeOneParamFn) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
|
||||
code = initCtxFn();
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
SColumnInfoData *pInputData = pInput->columnData;
|
||||
SColumnInfoData *pOutputData = pOutput->columnData;
|
||||
pOutput->numOfRows = pInput->numOfRows;
|
||||
|
||||
if (IS_NULL_TYPE(GET_PARAM_TYPE(pInput))) {
|
||||
colDataSetNNULL(pOutputData, 0, pInput->numOfRows);
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
}
|
||||
else {
|
||||
for (int32_t i = 0; i < pInput->numOfRows; ++i) {
|
||||
if (colDataIsNull_s(pInputData, i)) {
|
||||
colDataSetNULL(pOutputData, i);
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
continue;
|
||||
}
|
||||
|
||||
code = executeOneParamFn(pInputData, i, pOutputData);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t geomTwoParamsFunction(SScalarParam *pInput, SScalarParam *pOutput,
|
||||
_geomInitCtxFunc_t initCtxFn, _geomExecuteTwoParamsFunc_t executeTwoParamsFn) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
|
||||
code = initCtxFn();
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
SColumnInfoData *pInputData[2];
|
||||
SColumnInfoData *pOutputData = pOutput->columnData;
|
||||
pInputData[0] = pInput[0].columnData;
|
||||
pInputData[1] = pInput[1].columnData;
|
||||
|
||||
bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) ||
|
||||
IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])));
|
||||
bool isConstantLeft = (pInput[0].numOfRows == 1);
|
||||
bool isConstantRight = (pInput[1].numOfRows == 1);
|
||||
int32_t numOfRows = TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
|
||||
pOutput->numOfRows = numOfRows;
|
||||
|
||||
if (hasNullType || // one of operant is NULL type
|
||||
(isConstantLeft && colDataIsNull_s(pInputData[0], 0)) || // left operand is constant NULL
|
||||
(isConstantRight && colDataIsNull_s(pInputData[1], 0))) { // right operand is constant NULL
|
||||
colDataSetNNULL(pOutputData, 0, numOfRows);
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
}
|
||||
else {
|
||||
int32_t iLeft = 0;
|
||||
int32_t iRight = 0;
|
||||
for (int32_t i = 0; i < numOfRows; ++i) {
|
||||
iLeft = isConstantLeft ? 0 : i;
|
||||
iRight = isConstantRight ? 0 : i;
|
||||
|
||||
if ((!isConstantLeft && colDataIsNull_s(pInputData[0], iLeft)) ||
|
||||
(!isConstantRight && colDataIsNull_s(pInputData[1], iRight))) {
|
||||
colDataSetNULL(pOutputData, i);
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
continue;
|
||||
}
|
||||
|
||||
code = executeTwoParamsFn(pInputData, iLeft, iRight, pOutputData);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t geomRelationFunction(SScalarParam *pInput, SScalarParam *pOutput,
|
||||
bool swapAllowed, _geomDoRelationFunc_t doRelationFn) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
|
||||
code = initCtxRelationFunc();
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
// handle with all NULL output
|
||||
bool hasNullType = (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0])) ||
|
||||
IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[1])));
|
||||
bool isConstant1 = (pInput[0].numOfRows == 1);
|
||||
bool isConstant2 = (pInput[1].numOfRows == 1);
|
||||
int32_t numOfRows = TMAX(pInput[0].numOfRows, pInput[1].numOfRows);
|
||||
pOutput->numOfRows = numOfRows;
|
||||
SColumnInfoData *pOutputData = pOutput->columnData;
|
||||
|
||||
if (hasNullType || // at least one of operant is NULL type
|
||||
(isConstant1 && colDataIsNull_s(pInput[0].columnData, 0)) || // left operand is constant NULL
|
||||
(isConstant2 && colDataIsNull_s(pInput[1].columnData, 0))) { // right operand is constant NULL
|
||||
colDataSetNNULL(pOutputData, 0, numOfRows);
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
return code;
|
||||
}
|
||||
|
||||
bool swapped = false;
|
||||
SColumnInfoData *pInputData[2];
|
||||
|
||||
// swap two input data to make sure input data 0 is constant if swapAllowed and only isConstant2 is true
|
||||
if (swapAllowed &&
|
||||
!isConstant1 && isConstant2) {
|
||||
pInputData[0] = pInput[1].columnData;
|
||||
pInputData[1] = pInput[0].columnData;
|
||||
|
||||
isConstant1 = true;
|
||||
isConstant2 = false;
|
||||
swapped = true;
|
||||
}
|
||||
else {
|
||||
pInputData[0] = pInput[0].columnData;
|
||||
pInputData[1] = pInput[1].columnData;
|
||||
}
|
||||
|
||||
GEOSGeometry *geom1 = NULL;
|
||||
GEOSGeometry *geom2 = NULL;
|
||||
const GEOSPreparedGeometry *preparedGeom1 = NULL;
|
||||
|
||||
// if there is constant, make PreparedGeometry from pInputData 0
|
||||
if (isConstant1) {
|
||||
code = readGeometry(colDataGetData(pInputData[0], 0), &geom1, &preparedGeom1);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
}
|
||||
if (isConstant2) {
|
||||
code = readGeometry(colDataGetData(pInputData[1], 0), &geom2, NULL);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < numOfRows; ++i) {
|
||||
if ((!isConstant1 && colDataIsNull_s(pInputData[0], i)) ||
|
||||
(!isConstant2 && colDataIsNull_s(pInputData[1], i))) {
|
||||
colDataSetNULL(pOutputData, i);
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isConstant1) {
|
||||
code = readGeometry(colDataGetData(pInputData[0], i), &geom1, &preparedGeom1);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
}
|
||||
if (!isConstant2) {
|
||||
code = readGeometry(colDataGetData(pInputData[1], i), &geom2, NULL);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
}
|
||||
|
||||
code = executeRelationFunc(geom1, preparedGeom1, geom2, i, swapped, pOutputData, doRelationFn);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
if (!isConstant1) {
|
||||
destroyGeometry(&geom1, &preparedGeom1);
|
||||
}
|
||||
if (!isConstant2) {
|
||||
destroyGeometry(&geom2, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
_exit:
|
||||
destroyGeometry(&geom1, &preparedGeom1);
|
||||
destroyGeometry(&geom2, NULL);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t makePointFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
|
||||
return geomTwoParamsFunction(pInput, pOutput, initCtxMakePoint, executeMakePointFunc);
|
||||
}
|
||||
|
||||
int32_t geomFromTextFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
|
||||
return geomOneParamFunction(pInput, pOutput, initCtxGeomFromText, executeGeomFromTextFunc);
|
||||
}
|
||||
|
||||
int32_t asTextFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
|
||||
return geomOneParamFunction(pInput, pOutput, initCtxAsText, executeAsTextFunc);
|
||||
}
|
||||
|
||||
int32_t intersectsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
|
||||
return geomRelationFunction(pInput, pOutput, true, doIntersects);
|
||||
}
|
||||
|
||||
int32_t equalsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
|
||||
return geomRelationFunction(pInput, pOutput, true, doEquals);
|
||||
}
|
||||
|
||||
int32_t touchesFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
|
||||
return geomRelationFunction(pInput, pOutput, true, doTouches);
|
||||
}
|
||||
|
||||
int32_t coversFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
|
||||
return geomRelationFunction(pInput, pOutput, true, doCovers);
|
||||
}
|
||||
|
||||
int32_t containsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
|
||||
return geomRelationFunction(pInput, pOutput, true, doContains);
|
||||
}
|
||||
|
||||
int32_t containsProperlyFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
|
||||
return geomRelationFunction(pInput, pOutput, false, doContainsProperly);
|
||||
}
|
|
@ -0,0 +1,352 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "geosWrapper.h"
|
||||
#include "tdef.h"
|
||||
#include "types.h"
|
||||
|
||||
typedef char (*_geosRelationFunc_t)(GEOSContextHandle_t handle, const GEOSGeometry *g1, const GEOSGeometry *g2);
|
||||
typedef char (*_geosPreparedRelationFunc_t)(GEOSContextHandle_t handle, const GEOSPreparedGeometry *pg1, const GEOSGeometry *g2);
|
||||
|
||||
void geosFreeBuffer(void *buffer) {
|
||||
if (buffer) {
|
||||
GEOSFree_r(getThreadLocalGeosCtx()->handle, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void geosErrMsgeHandler(const char *errMsg, void *userData) {
|
||||
char* targetErrMsg = userData;
|
||||
snprintf(targetErrMsg, 512, "%s", errMsg);
|
||||
}
|
||||
|
||||
int32_t initCtxMakePoint() {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
SGeosContext* geosCtx = getThreadLocalGeosCtx();
|
||||
|
||||
if (geosCtx->handle == NULL) {
|
||||
geosCtx->handle = GEOS_init_r();
|
||||
if (geosCtx->handle == NULL) {
|
||||
return code;
|
||||
}
|
||||
|
||||
GEOSContext_setErrorMessageHandler_r(geosCtx->handle, geosErrMsgeHandler, geosCtx->errMsg);
|
||||
}
|
||||
|
||||
if (geosCtx->WKBWriter == NULL) {
|
||||
geosCtx->WKBWriter = GEOSWKBWriter_create_r(geosCtx->handle);
|
||||
if (geosCtx->WKBWriter == NULL) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// outputWKT is a zero ending string
|
||||
// need to call geosFreeBuffer(*outputGeom) later
|
||||
int32_t doMakePoint(double x, double y, unsigned char **outputGeom, size_t *size) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
SGeosContext* geosCtx = getThreadLocalGeosCtx();
|
||||
|
||||
GEOSGeometry *geom = NULL;
|
||||
unsigned char *wkb = NULL;
|
||||
|
||||
geom = GEOSGeom_createPointFromXY_r(geosCtx->handle, x, y);
|
||||
if (geom == NULL) {
|
||||
code = TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
wkb = GEOSWKBWriter_write_r(geosCtx->handle, geosCtx->WKBWriter, geom, size);
|
||||
if (wkb == NULL) {
|
||||
goto _exit;
|
||||
}
|
||||
*outputGeom = wkb;
|
||||
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
|
||||
_exit:
|
||||
if (geom) {
|
||||
GEOSGeom_destroy_r(geosCtx->handle, geom);
|
||||
geom = NULL;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t initCtxGeomFromText() {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
SGeosContext* geosCtx = getThreadLocalGeosCtx();
|
||||
|
||||
if (geosCtx->handle == NULL) {
|
||||
geosCtx->handle = GEOS_init_r();
|
||||
if (geosCtx->handle == NULL) {
|
||||
return code;
|
||||
}
|
||||
|
||||
GEOSContext_setErrorMessageHandler_r(geosCtx->handle, geosErrMsgeHandler, geosCtx->errMsg);
|
||||
}
|
||||
|
||||
if (geosCtx->WKTReader == NULL) {
|
||||
geosCtx->WKTReader = GEOSWKTReader_create_r(geosCtx->handle);
|
||||
if (geosCtx->WKTReader == NULL) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
if (geosCtx->WKBWriter == NULL) {
|
||||
geosCtx->WKBWriter = GEOSWKBWriter_create_r(geosCtx->handle);
|
||||
if (geosCtx->WKBWriter == NULL) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// inputWKT is a zero ending string
|
||||
// need to call geosFreeBuffer(*outputGeom) later
|
||||
int32_t doGeomFromText(const char *inputWKT, unsigned char **outputGeom, size_t *size) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
SGeosContext* geosCtx = getThreadLocalGeosCtx();
|
||||
|
||||
GEOSGeometry *geom = NULL;
|
||||
unsigned char *wkb = NULL;
|
||||
|
||||
geom = GEOSWKTReader_read_r(geosCtx->handle, geosCtx->WKTReader, inputWKT);
|
||||
if (geom == NULL) {
|
||||
code = TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
wkb = GEOSWKBWriter_write_r(geosCtx->handle, geosCtx->WKBWriter, geom, size);
|
||||
if (wkb == NULL) {
|
||||
goto _exit;
|
||||
}
|
||||
*outputGeom = wkb;
|
||||
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
|
||||
_exit:
|
||||
if (geom) {
|
||||
GEOSGeom_destroy_r(geosCtx->handle, geom);
|
||||
geom = NULL;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t initCtxAsText() {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
SGeosContext* geosCtx = getThreadLocalGeosCtx();
|
||||
|
||||
if (geosCtx->handle == NULL) {
|
||||
geosCtx->handle = GEOS_init_r();
|
||||
if (geosCtx->handle == NULL) {
|
||||
return code;
|
||||
}
|
||||
|
||||
GEOSContext_setErrorMessageHandler_r(geosCtx->handle, geosErrMsgeHandler, geosCtx->errMsg);
|
||||
}
|
||||
|
||||
if (geosCtx->WKBReader == NULL) {
|
||||
geosCtx->WKBReader = GEOSWKBReader_create_r(geosCtx->handle);
|
||||
if (geosCtx->WKBReader == NULL) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
if (geosCtx->WKTWriter == NULL) {
|
||||
geosCtx->WKTWriter = GEOSWKTWriter_create_r(geosCtx->handle);
|
||||
|
||||
if (geosCtx->WKTWriter) {
|
||||
GEOSWKTWriter_setRoundingPrecision_r(geosCtx->handle, geosCtx->WKTWriter, 6);
|
||||
} else {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// outputWKT is a zero ending string
|
||||
// need to call geosFreeBuffer(*outputWKT) later
|
||||
int32_t doAsText(const unsigned char *inputGeom, size_t size, char **outputWKT) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
SGeosContext* geosCtx = getThreadLocalGeosCtx();
|
||||
|
||||
GEOSGeometry *geom = NULL;
|
||||
unsigned char *wkt = NULL;
|
||||
|
||||
geom = GEOSWKBReader_read_r(geosCtx->handle, geosCtx->WKBReader, inputGeom, size);
|
||||
if (geom == NULL) {
|
||||
code = TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
wkt = GEOSWKTWriter_write_r(geosCtx->handle, geosCtx->WKTWriter, geom);
|
||||
if (wkt == NULL) {
|
||||
goto _exit;
|
||||
}
|
||||
*outputWKT = wkt;
|
||||
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
|
||||
_exit:
|
||||
if (geom) {
|
||||
GEOSGeom_destroy_r(geosCtx->handle, geom);
|
||||
geom = NULL;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t initCtxRelationFunc() {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
SGeosContext* geosCtx = getThreadLocalGeosCtx();
|
||||
|
||||
if (geosCtx->handle == NULL) {
|
||||
geosCtx->handle = GEOS_init_r();
|
||||
if (geosCtx->handle == NULL) {
|
||||
return code;
|
||||
}
|
||||
|
||||
GEOSContext_setErrorMessageHandler_r(geosCtx->handle, geosErrMsgeHandler, geosCtx->errMsg);
|
||||
}
|
||||
|
||||
if (geosCtx->WKBReader == NULL) {
|
||||
geosCtx->WKBReader = GEOSWKBReader_create_r(geosCtx->handle);
|
||||
if (geosCtx->WKBReader == NULL) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t doGeosRelation(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res,
|
||||
_geosRelationFunc_t relationFn,
|
||||
_geosRelationFunc_t swappedRelationFn,
|
||||
_geosPreparedRelationFunc_t preparedRelationFn,
|
||||
_geosPreparedRelationFunc_t swappedPreparedRelationFn) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
SGeosContext* geosCtx = getThreadLocalGeosCtx();
|
||||
|
||||
if (!preparedGeom1) {
|
||||
if (!swapped) {
|
||||
ASSERT(relationFn);
|
||||
*res = relationFn(geosCtx->handle, geom1, geom2);
|
||||
}
|
||||
else {
|
||||
ASSERT(swappedRelationFn);
|
||||
*res = swappedRelationFn(geosCtx->handle, geom1, geom2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!swapped) {
|
||||
ASSERT(preparedRelationFn);
|
||||
*res = preparedRelationFn(geosCtx->handle, preparedGeom1, geom2);
|
||||
}
|
||||
else {
|
||||
ASSERT(swappedPreparedRelationFn);
|
||||
*res = swappedPreparedRelationFn(geosCtx->handle, preparedGeom1, geom2);
|
||||
}
|
||||
}
|
||||
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t doIntersects(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res) {
|
||||
return doGeosRelation(geom1, preparedGeom1, geom2, swapped, res,
|
||||
GEOSIntersects_r, GEOSIntersects_r, GEOSPreparedIntersects_r, GEOSPreparedIntersects_r);
|
||||
}
|
||||
|
||||
int32_t doEquals(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res) {
|
||||
return doGeosRelation(geom1, NULL, geom2, swapped, res,
|
||||
GEOSEquals_r, GEOSEquals_r, NULL, NULL); // no prepared version for eguals()
|
||||
}
|
||||
|
||||
int32_t doTouches(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res) {
|
||||
return doGeosRelation(geom1, preparedGeom1, geom2, swapped, res,
|
||||
GEOSTouches_r, GEOSTouches_r, GEOSPreparedTouches_r, GEOSPreparedTouches_r);
|
||||
}
|
||||
|
||||
int32_t doCovers(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res) {
|
||||
return doGeosRelation(geom1, preparedGeom1, geom2, swapped, res,
|
||||
GEOSCovers_r, GEOSCoveredBy_r, GEOSPreparedCovers_r, GEOSPreparedCoveredBy_r);
|
||||
}
|
||||
|
||||
int32_t doContains(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res) {
|
||||
return doGeosRelation(geom1, preparedGeom1, geom2, swapped, res,
|
||||
GEOSContains_r, GEOSWithin_r, GEOSPreparedContains_r, GEOSPreparedWithin_r);
|
||||
}
|
||||
|
||||
int32_t doContainsProperly(const GEOSGeometry *geom1, const GEOSPreparedGeometry *preparedGeom1, const GEOSGeometry *geom2,
|
||||
bool swapped, char *res) {
|
||||
return doGeosRelation(geom1, preparedGeom1, geom2, swapped, res,
|
||||
NULL, NULL, GEOSPreparedContainsProperly_r, NULL);
|
||||
}
|
||||
|
||||
// input is with VARSTR format
|
||||
// need to call destroyGeometry(outputGeom, outputPreparedGeom) later
|
||||
int32_t readGeometry(const unsigned char *input, GEOSGeometry **outputGeom, const GEOSPreparedGeometry **outputPreparedGeom) {
|
||||
SGeosContext* geosCtx = getThreadLocalGeosCtx();
|
||||
|
||||
ASSERT(outputGeom); //it is not allowed if outputGeom is NULL
|
||||
*outputGeom = NULL;
|
||||
|
||||
if (outputPreparedGeom) { //it means not to generate PreparedGeometry if outputPreparedGeom is NULL
|
||||
*outputPreparedGeom = NULL;
|
||||
}
|
||||
|
||||
if (varDataLen(input) == 0) { //empty value
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
*outputGeom = GEOSWKBReader_read_r(geosCtx->handle, geosCtx->WKBReader, varDataVal(input), varDataLen(input));
|
||||
if (*outputGeom == NULL) {
|
||||
return TSDB_CODE_FUNC_FUNTION_PARA_VALUE;
|
||||
}
|
||||
|
||||
if (outputPreparedGeom) {
|
||||
*outputPreparedGeom = GEOSPrepare_r(geosCtx->handle, *outputGeom);
|
||||
if (*outputPreparedGeom == NULL) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void destroyGeometry(GEOSGeometry **geom, const GEOSPreparedGeometry **preparedGeom) {
|
||||
SGeosContext* geosCtx = getThreadLocalGeosCtx();
|
||||
|
||||
if (preparedGeom && *preparedGeom) {
|
||||
GEOSPreparedGeom_destroy_r(geosCtx->handle, *preparedGeom);
|
||||
*preparedGeom = NULL;
|
||||
}
|
||||
|
||||
if (geom && *geom) {
|
||||
GEOSGeom_destroy_r(geosCtx->handle, *geom);
|
||||
*geom = NULL;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
MESSAGE(STATUS "build geometry unit test")
|
||||
|
||||
IF(NOT TD_DARWIN)
|
||||
# GoogleTest requires at least C++11
|
||||
SET(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
|
||||
ADD_EXECUTABLE(geomTest ${SOURCE_LIST})
|
||||
|
||||
TARGET_LINK_LIBRARIES(
|
||||
geomTest
|
||||
PUBLIC os util gtest qcom nodes geometry scalar function scalar
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME geomTest
|
||||
COMMAND geomTest
|
||||
)
|
||||
ENDIF()
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "os.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
taosSeedRand(taosGetTimestampSec());
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "geomFuncTestUtil.h"
|
||||
|
||||
void setColumnInfo(SColumnInfo *info, int32_t colId, int32_t type, int32_t bytes) {
|
||||
memset(info, 0, sizeof(SColumnInfo));
|
||||
info->colId = colId;
|
||||
info->type = type;
|
||||
info->bytes = bytes;
|
||||
}
|
||||
|
||||
void setScalarParam(SScalarParam *sclParam, int32_t type, void *valueArray, TDRowValT valTypeArray[], int32_t rowNum) {
|
||||
int32_t bytes = 0;
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_NULL: {
|
||||
bytes = -1;
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_BOOL: {
|
||||
bytes = sizeof(int8_t);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
bytes = sizeof(int8_t);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
bytes = sizeof(int16_t);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
bytes = sizeof(int32_t);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
bytes = sizeof(int64_t);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
bytes = sizeof(float);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
bytes = sizeof(double);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_VARCHAR: {
|
||||
bytes = TSDB_MAX_BINARY_LEN;
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
bytes = TSDB_MAX_GEOMETRY_LEN;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sclParam->columnData = (SColumnInfoData *)taosMemoryCalloc(1, sizeof(SColumnInfoData));
|
||||
sclParam->numOfRows = rowNum;
|
||||
|
||||
setColumnInfo(&sclParam->columnData->info, 0, type, bytes);
|
||||
colInfoDataEnsureCapacity(sclParam->columnData, rowNum, false);
|
||||
|
||||
if (type != TSDB_DATA_TYPE_NULL && valueArray) {
|
||||
for (int32_t i = 0; i < rowNum; ++i) {
|
||||
if (tdValTypeIsNull(valTypeArray[i])) {
|
||||
colDataSetNULL(sclParam->columnData, i);
|
||||
}
|
||||
else {
|
||||
const char *val = (const char *)valueArray + (i * bytes);
|
||||
colDataAppend(sclParam->columnData, i, val, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void destroyScalarParam(SScalarParam *sclParam, int32_t colNum) {
|
||||
for (int32_t i = 0; i < colNum; ++i) {
|
||||
colDataDestroy((sclParam + i)->columnData);
|
||||
taosMemoryFree((sclParam + i)->columnData);
|
||||
}
|
||||
taosMemoryFree(sclParam);
|
||||
}
|
||||
|
||||
void makeOneScalarParam(SScalarParam **pSclParam, int32_t type, void *valueArray, TDRowValT valTypeArray[], int32_t rowNum) {
|
||||
*pSclParam = (SScalarParam *)taosMemoryCalloc(1, sizeof(SScalarParam));
|
||||
setScalarParam(*pSclParam, type, valueArray, valTypeArray, rowNum);
|
||||
}
|
||||
|
||||
bool compareVarData(unsigned char *varData1, unsigned char *varData2) {
|
||||
if (varDataLen(varData1) == 0 || varDataLen(varData2) == 0) {
|
||||
return false;
|
||||
}
|
||||
if(varDataLen(varData1) != varDataLen(varData2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (memcmp(varDataVal(varData1), varDataVal(varData2), varDataLen(varData1)) == 0);
|
||||
}
|
||||
|
||||
void compareVarDataColumn(SColumnInfoData *columnData1, SColumnInfoData *columnData2, int32_t rowNum) {
|
||||
for (int32_t i = 0; i < rowNum; ++i) {
|
||||
bool isNull1 = colDataIsNull_s(columnData1, i);
|
||||
bool isNull2 = colDataIsNull_s(columnData2, i);
|
||||
ASSERT_EQ((isNull1 == isNull2), true);
|
||||
|
||||
if (!isNull1) {
|
||||
bool res = compareVarData((unsigned char *)colDataGetData(columnData1, i),
|
||||
(unsigned char *)colDataGetData(columnData2, i));
|
||||
ASSERT_EQ(res, true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "tdatablock.h"
|
||||
#include "geomFunc.h"
|
||||
|
||||
void setScalarParam(SScalarParam *sclParam, int32_t type, void *valueArray, TDRowValT valTypeArray[], int32_t rowNum);
|
||||
void destroyScalarParam(SScalarParam *sclParam, int32_t colNum);
|
||||
|
||||
void makeOneScalarParam(SScalarParam **pSclParam, int32_t type, void *valueArray, TDRowValT valTypeArray[], int32_t rowNum);
|
||||
|
||||
void compareVarDataColumn(SColumnInfoData *columnData1, SColumnInfoData *columnData2, int32_t rowNum);
|
||||
|
||||
void callGeomFromTextWrapper5(void *strArray, TDRowValT valTypeArray[], int32_t rowNum, SScalarParam *pOutputGeomFromText);
|
|
@ -0,0 +1,321 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "geomFuncTestUtil.h"
|
||||
|
||||
void callGeomFromText(int32_t inputType, void *strArray, TDRowValT valTypeArray[], int32_t rowNum,
|
||||
SScalarParam **pInputGeomFromText, SScalarParam **pOutputGeomFromText,
|
||||
int32_t expectedCode) {
|
||||
makeOneScalarParam(pInputGeomFromText, inputType, strArray, valTypeArray, rowNum);
|
||||
makeOneScalarParam(pOutputGeomFromText, TSDB_DATA_TYPE_GEOMETRY, 0, 0, rowNum);
|
||||
|
||||
int32_t code = geomFromTextFunction(*pInputGeomFromText, 1, *pOutputGeomFromText);
|
||||
ASSERT_EQ(code, expectedCode);
|
||||
}
|
||||
|
||||
void callGeomFromTextWrapper1(int32_t inputType, void *strArray, TDRowValT valTypeArray[], int32_t rowNum, SScalarParam **pOutputGeomFromText) {
|
||||
SScalarParam *pInputGeomFromText;
|
||||
callGeomFromText(inputType, strArray, valTypeArray, rowNum, &pInputGeomFromText, pOutputGeomFromText, TSDB_CODE_SUCCESS);
|
||||
destroyScalarParam(pInputGeomFromText, 1);
|
||||
}
|
||||
|
||||
void callGeomFromTextWrapper2(void *strArray, TDRowValT valTypeArray[], int32_t rowNum, SScalarParam **pOutputGeomFromText) {
|
||||
callGeomFromTextWrapper1(TSDB_DATA_TYPE_VARCHAR, strArray, valTypeArray, rowNum, pOutputGeomFromText);
|
||||
}
|
||||
|
||||
void callGeomFromTextWrapper3(int32_t inputType, void *strArray, TDRowValT valTypeArray[], int32_t rowNum, int32_t expectedCode) {
|
||||
SScalarParam *pInputGeomFromText;
|
||||
SScalarParam *pOutputGeomFromText;
|
||||
|
||||
callGeomFromText(inputType, strArray, valTypeArray, rowNum, &pInputGeomFromText, &pOutputGeomFromText, expectedCode);
|
||||
|
||||
destroyScalarParam(pInputGeomFromText, 1);
|
||||
destroyScalarParam(pOutputGeomFromText, 1);
|
||||
}
|
||||
|
||||
void callGeomFromTextWrapper4(void *strArray, TDRowValT valTypeArray[], int32_t rowNum, int32_t expectedCode) {
|
||||
callGeomFromTextWrapper3(TSDB_DATA_TYPE_VARCHAR, strArray, valTypeArray, rowNum, expectedCode);
|
||||
}
|
||||
|
||||
void callGeomFromTextWrapper5(void *strArray, TDRowValT valTypeArray[], int32_t rowNum, SScalarParam *pOutputGeomFromText) {
|
||||
SScalarParam *pInputGeomFromText;
|
||||
makeOneScalarParam(&pInputGeomFromText, TSDB_DATA_TYPE_VARCHAR, strArray, valTypeArray, rowNum);
|
||||
|
||||
setScalarParam(pOutputGeomFromText, TSDB_DATA_TYPE_GEOMETRY, 0, 0, rowNum);
|
||||
|
||||
int32_t code = geomFromTextFunction(pInputGeomFromText, 1, pOutputGeomFromText);
|
||||
ASSERT_EQ(code, TSDB_CODE_SUCCESS);
|
||||
|
||||
destroyScalarParam(pInputGeomFromText, 1);
|
||||
}
|
||||
|
||||
void callAsText(int32_t inputType, void *strArray, TDRowValT valTypeArray[], int32_t rowNum,
|
||||
SScalarParam **pInputAsText, SScalarParam **pOutputAsText,
|
||||
int32_t expectedCode) {
|
||||
makeOneScalarParam(pInputAsText, inputType, strArray, valTypeArray, rowNum);
|
||||
makeOneScalarParam(pOutputAsText, TSDB_DATA_TYPE_VARCHAR, 0, 0, rowNum);
|
||||
|
||||
int32_t code = geomFromTextFunction(*pInputAsText, 1, *pOutputAsText);
|
||||
ASSERT_EQ(code, expectedCode);
|
||||
}
|
||||
|
||||
void callAsTextWrapper1(int32_t inputType, void *strArray, TDRowValT valTypeArray[], int32_t rowNum, SScalarParam **pOutputAsText) {
|
||||
SScalarParam *pInputAsText;
|
||||
callAsText(inputType, strArray, valTypeArray, rowNum, &pInputAsText, pOutputAsText, TSDB_CODE_SUCCESS);
|
||||
destroyScalarParam(pInputAsText, 1);
|
||||
}
|
||||
|
||||
void callAsTextWrapper2(int32_t inputType, void *strArray, TDRowValT valTypeArray[], int32_t rowNum, int32_t expectedCode) {
|
||||
SScalarParam *pInputAsText;
|
||||
SScalarParam *pOutputASText;
|
||||
|
||||
callAsText(inputType, strArray, valTypeArray, rowNum, &pInputAsText, &pOutputASText, expectedCode);
|
||||
|
||||
destroyScalarParam(pInputAsText, 1);
|
||||
destroyScalarParam(pOutputASText, 1);
|
||||
}
|
||||
|
||||
void callMakePointAndCompareResult(int32_t type1, void *valueArray1, TDRowValT valTypeArray1[], bool isConstant1,
|
||||
int32_t type2, void *valueArray2, TDRowValT valTypeArray2[], bool isConstant2,
|
||||
SScalarParam *pExpectedResult, int32_t rowNum) {
|
||||
int32_t rowNum1 = isConstant1 ? 1 : rowNum;
|
||||
int32_t rowNum2 = isConstant2 ? 1 : rowNum;
|
||||
|
||||
SScalarParam *pInputMakePoint = (SScalarParam *)taosMemoryCalloc(2, sizeof(SScalarParam));
|
||||
setScalarParam(pInputMakePoint, type1, valueArray1, valTypeArray1, rowNum1);
|
||||
setScalarParam(pInputMakePoint + 1, type2, valueArray2, valTypeArray2, rowNum2);
|
||||
|
||||
SScalarParam *pOutputMakePoint;
|
||||
makeOneScalarParam(&pOutputMakePoint, TSDB_DATA_TYPE_GEOMETRY, 0, 0, rowNum);
|
||||
|
||||
int32_t code = makePointFunction(pInputMakePoint, 2, pOutputMakePoint);
|
||||
ASSERT_EQ(code, TSDB_CODE_SUCCESS);
|
||||
|
||||
ASSERT_EQ(pOutputMakePoint->columnData->info.type, TSDB_DATA_TYPE_GEOMETRY);
|
||||
ASSERT_EQ(pExpectedResult->columnData->info.type, TSDB_DATA_TYPE_GEOMETRY);
|
||||
|
||||
compareVarDataColumn(pOutputMakePoint->columnData, pExpectedResult->columnData, rowNum);
|
||||
|
||||
destroyScalarParam(pInputMakePoint, 2);
|
||||
destroyScalarParam(pOutputMakePoint, 1);
|
||||
}
|
||||
|
||||
#define MAKE_POINT_FIRST_COLUMN_VALUES {2, 3, -4}
|
||||
#define MAKE_POINT_SECOND_COLUMN_VALUES {5, -6, -7}
|
||||
|
||||
TEST(GeomIoFuncTest, makePointFunctionTwoColumns) {
|
||||
const int32_t rowNum = 3;
|
||||
SScalarParam *pExpectedResult;
|
||||
TDRowValT valTypeArray[rowNum] = {TD_VTYPE_NORM, TD_VTYPE_NORM, TD_VTYPE_NORM};
|
||||
|
||||
// call GeomFromText(<POINT>) and generate pExpectedResult to compare later
|
||||
char strArray[rowNum][TSDB_MAX_BINARY_LEN];
|
||||
STR_TO_VARSTR(strArray[0], "POINT(2.0 5.0)");
|
||||
STR_TO_VARSTR(strArray[1], "POINT(3.0 -6.0)");
|
||||
STR_TO_VARSTR(strArray[2], "POINT(-4.0 -7.0)");
|
||||
callGeomFromTextWrapper2(strArray, valTypeArray, rowNum, &pExpectedResult);
|
||||
|
||||
// call MakePoint() with TINYINT and SMALLINT, and compare with result of GeomFromText(<POINT>)
|
||||
int8_t tinyIntArray1[rowNum] = MAKE_POINT_FIRST_COLUMN_VALUES;
|
||||
int16_t smallIntArray2[rowNum] = MAKE_POINT_SECOND_COLUMN_VALUES;
|
||||
callMakePointAndCompareResult(TSDB_DATA_TYPE_TINYINT, tinyIntArray1, valTypeArray, false,
|
||||
TSDB_DATA_TYPE_SMALLINT, smallIntArray2, valTypeArray, false,
|
||||
pExpectedResult, rowNum);
|
||||
|
||||
// call MakePoint() with INT and BIGINT, and compare with result of GeomFromText(<POINT>)
|
||||
int32_t intArray1[rowNum] = MAKE_POINT_FIRST_COLUMN_VALUES;
|
||||
int64_t bigIntArray2[rowNum] = MAKE_POINT_SECOND_COLUMN_VALUES;
|
||||
callMakePointAndCompareResult(TSDB_DATA_TYPE_INT, intArray1, valTypeArray, false,
|
||||
TSDB_DATA_TYPE_BIGINT, bigIntArray2, valTypeArray, false,
|
||||
pExpectedResult, rowNum);
|
||||
|
||||
// call MakePoint() with FLOAT and DOUBLE, and compare with result of GeomFromText(<POINT>)
|
||||
float floatArray1[rowNum] = MAKE_POINT_FIRST_COLUMN_VALUES;
|
||||
double doubleArray2[rowNum] = MAKE_POINT_SECOND_COLUMN_VALUES;
|
||||
callMakePointAndCompareResult(TSDB_DATA_TYPE_FLOAT, floatArray1, valTypeArray, false,
|
||||
TSDB_DATA_TYPE_DOUBLE, doubleArray2, valTypeArray, false,
|
||||
pExpectedResult, rowNum);
|
||||
|
||||
destroyScalarParam(pExpectedResult, 1);
|
||||
}
|
||||
|
||||
TEST(GeomIoFuncTest, makePointFunctionConstant) {
|
||||
const int32_t rowNum = 3;
|
||||
SScalarParam *pExpectedResult;
|
||||
TDRowValT valTypeArray[rowNum] = {TD_VTYPE_NORM, TD_VTYPE_NORM, TD_VTYPE_NORM};
|
||||
|
||||
// 1. call GeomFromText(<POINT>) and generate pExpectedResult with first constant
|
||||
char strArray[rowNum][TSDB_MAX_BINARY_LEN];
|
||||
STR_TO_VARSTR(strArray[0], "POINT(3.0 5.0)");
|
||||
STR_TO_VARSTR(strArray[1], "POINT(3.0 -6.0)");
|
||||
STR_TO_VARSTR(strArray[2], "POINT(3.0 -7.0)");
|
||||
callGeomFromTextWrapper2(strArray, valTypeArray, rowNum, &pExpectedResult);
|
||||
|
||||
// call MakePoint() with TINYINT constant and BIGINT column, and compare with result of GeomFromText(<POINT>)
|
||||
int8_t tinyIntConstant = 3;
|
||||
int64_t bigIntArray[rowNum] = MAKE_POINT_SECOND_COLUMN_VALUES;
|
||||
callMakePointAndCompareResult(TSDB_DATA_TYPE_TINYINT, &tinyIntConstant, valTypeArray, true,
|
||||
TSDB_DATA_TYPE_BIGINT, bigIntArray, valTypeArray, false,
|
||||
pExpectedResult, rowNum);
|
||||
|
||||
destroyScalarParam(pExpectedResult, 1);
|
||||
|
||||
// 2. call GeomFromText(<POINT>) and generate pExpectedResult with second constant
|
||||
STR_TO_VARSTR(strArray[0], "POINT(2.0 3.0)");
|
||||
STR_TO_VARSTR(strArray[1], "POINT(3.0 3.0)");
|
||||
STR_TO_VARSTR(strArray[2], "POINT(-4.0 3.0)");
|
||||
callGeomFromTextWrapper2(strArray, valTypeArray, rowNum, &pExpectedResult);
|
||||
|
||||
// call MakePoint() with INT column and FLOAT constant, and compare with result of GeomFromText(<POINT>)
|
||||
int32_t intArray[rowNum] = MAKE_POINT_FIRST_COLUMN_VALUES;
|
||||
float floatConstant = 3;
|
||||
callMakePointAndCompareResult(TSDB_DATA_TYPE_INT, intArray, valTypeArray, false,
|
||||
TSDB_DATA_TYPE_FLOAT, &floatConstant, valTypeArray, true,
|
||||
pExpectedResult, rowNum);
|
||||
|
||||
destroyScalarParam(pExpectedResult, 1);
|
||||
}
|
||||
|
||||
TEST(GeomIoFuncTest, makePointFunctionWithNull) {
|
||||
const int32_t rowNum = 3;
|
||||
SScalarParam *pExpectedResult;
|
||||
TDRowValT valTypeNormArray[rowNum] = {TD_VTYPE_NORM, TD_VTYPE_NORM, TD_VTYPE_NORM};
|
||||
|
||||
// call GeomFromText(<POINT>) and generate pExpectedResult with all NULL values
|
||||
char strArray[rowNum][TSDB_MAX_BINARY_LEN];
|
||||
TDRowValT valTypeNullArray[rowNum] = {TD_VTYPE_NULL, TD_VTYPE_NULL, TD_VTYPE_NULL};
|
||||
callGeomFromTextWrapper2(strArray, valTypeNullArray, rowNum, &pExpectedResult);
|
||||
|
||||
// 1. call MakePoint() with NULL type and INT column, and compare all NULL results
|
||||
int64_t intArray[rowNum] = MAKE_POINT_SECOND_COLUMN_VALUES;
|
||||
callMakePointAndCompareResult(TSDB_DATA_TYPE_NULL, 0, 0, true,
|
||||
TSDB_DATA_TYPE_INT, intArray, valTypeNormArray, false,
|
||||
pExpectedResult, rowNum);
|
||||
// swap params and compare
|
||||
callMakePointAndCompareResult(TSDB_DATA_TYPE_INT, intArray, valTypeNormArray, false,
|
||||
TSDB_DATA_TYPE_NULL, 0, 0, true,
|
||||
pExpectedResult, rowNum);
|
||||
|
||||
// call MakePoint() with SMALLINT NULL constant and BIGINT column, and compare all NULL results
|
||||
int16_t smallIntConstant = 0;
|
||||
int64_t bigIntArray[rowNum] = MAKE_POINT_SECOND_COLUMN_VALUES;
|
||||
callMakePointAndCompareResult(TSDB_DATA_TYPE_SMALLINT, &smallIntConstant, valTypeNullArray, true,
|
||||
TSDB_DATA_TYPE_BIGINT, bigIntArray, valTypeNormArray, false,
|
||||
pExpectedResult, rowNum);
|
||||
// swap params and compare
|
||||
callMakePointAndCompareResult(TSDB_DATA_TYPE_BIGINT, bigIntArray, valTypeNormArray, false,
|
||||
TSDB_DATA_TYPE_SMALLINT, &smallIntConstant, valTypeNullArray, true,
|
||||
pExpectedResult, rowNum);
|
||||
|
||||
destroyScalarParam(pExpectedResult, 1);
|
||||
|
||||
// 2. call GeomFromText(<POINT>) and generate pExpectedResult with NULL value
|
||||
STR_TO_VARSTR(strArray[0], "POINT(2.0 5.0)");
|
||||
STR_TO_VARSTR(strArray[2], "POINT(-4.0 -7.0)");
|
||||
TDRowValT valTypeWithNullArray[rowNum] = {TD_VTYPE_NORM, TD_VTYPE_NULL, TD_VTYPE_NORM};
|
||||
callGeomFromTextWrapper2(strArray, valTypeWithNullArray, rowNum, &pExpectedResult);
|
||||
|
||||
// call MakePoint() with TINYINT column with NULL value and FLOAT column, and compare results with NULL value
|
||||
int8_t tinyIntArray[rowNum] = MAKE_POINT_FIRST_COLUMN_VALUES;
|
||||
float floatArray[rowNum] = MAKE_POINT_SECOND_COLUMN_VALUES;
|
||||
callMakePointAndCompareResult(TSDB_DATA_TYPE_TINYINT, tinyIntArray, valTypeWithNullArray, false,
|
||||
TSDB_DATA_TYPE_FLOAT, floatArray, valTypeNormArray, false,
|
||||
pExpectedResult, rowNum);
|
||||
|
||||
// call MakePoint() with SMALLINT column and DOUBLE column with NULL value, and compare results with NULL value
|
||||
int16_t smallIntArray[rowNum] = MAKE_POINT_FIRST_COLUMN_VALUES;
|
||||
double doubleArray[rowNum] = MAKE_POINT_SECOND_COLUMN_VALUES;
|
||||
callMakePointAndCompareResult(TSDB_DATA_TYPE_SMALLINT, smallIntArray, valTypeNormArray, false,
|
||||
TSDB_DATA_TYPE_DOUBLE, doubleArray, valTypeWithNullArray, false,
|
||||
pExpectedResult, rowNum);
|
||||
|
||||
destroyScalarParam(pExpectedResult, 1);
|
||||
}
|
||||
|
||||
TEST(GeomIoFuncTest, geomFromTextFunction) {
|
||||
const int32_t rowNum = 4;
|
||||
char strArray[rowNum][TSDB_MAX_BINARY_LEN];
|
||||
TDRowValT valTypeNormArray[rowNum] = {TD_VTYPE_NORM, TD_VTYPE_NORM, TD_VTYPE_NORM, TD_VTYPE_NORM};
|
||||
|
||||
// column input
|
||||
// input of GeomFromText (with NULL value) and output of AsText should be same after calling GeomFromText() and AsText()
|
||||
SScalarParam *pInputGeomFromText;
|
||||
SScalarParam *pOutputGeomFromText;
|
||||
SScalarParam *pOutputAsText;
|
||||
|
||||
STR_TO_VARSTR(strArray[0], "POINT (2.000000 5.000000)");
|
||||
STR_TO_VARSTR(strArray[2], "LINESTRING (3.000000 -6.000000, -71.160837 42.259113)");
|
||||
STR_TO_VARSTR(strArray[3], "POLYGON ((-71.177658 42.390290, -71.177682 42.390370, -71.177606 42.390382, -71.177582 42.390303, -71.177658 42.390290))");
|
||||
TDRowValT valTypeWithNullArray[rowNum] = {TD_VTYPE_NORM, TD_VTYPE_NULL, TD_VTYPE_NORM, TD_VTYPE_NORM};
|
||||
callGeomFromText(TSDB_DATA_TYPE_VARCHAR, strArray, valTypeWithNullArray, rowNum, &pInputGeomFromText, &pOutputGeomFromText, TSDB_CODE_SUCCESS);
|
||||
|
||||
makeOneScalarParam(&pOutputAsText, TSDB_DATA_TYPE_VARCHAR, 0, 0, rowNum);
|
||||
int32_t code = asTextFunction(pOutputGeomFromText, 1, pOutputAsText); // pOutputGeomFromText is input for AsText()
|
||||
ASSERT_EQ(code, TSDB_CODE_SUCCESS);
|
||||
|
||||
compareVarDataColumn(pInputGeomFromText->columnData, pOutputAsText->columnData, rowNum);
|
||||
|
||||
destroyScalarParam(pInputGeomFromText, 1);
|
||||
destroyScalarParam(pOutputGeomFromText, 1);
|
||||
destroyScalarParam(pOutputAsText, 1);
|
||||
|
||||
// empty input
|
||||
STR_TO_VARSTR(strArray[0], "");
|
||||
callGeomFromTextWrapper4(strArray, valTypeNormArray, 1, TSDB_CODE_SUCCESS);
|
||||
|
||||
// NULL type input
|
||||
callGeomFromTextWrapper1(TSDB_DATA_TYPE_NULL, 0, 0, 1, &pOutputGeomFromText);
|
||||
ASSERT_EQ(colDataIsNull_s(pOutputGeomFromText->columnData, 0), true);
|
||||
destroyScalarParam(pOutputGeomFromText, 1);
|
||||
|
||||
// wrong type input [ToDo] make sure it is handled in geomFunc
|
||||
int32_t intInput = 3;
|
||||
callGeomFromTextWrapper3(TSDB_DATA_TYPE_INT, &intInput, valTypeNormArray, 1, TSDB_CODE_FUNC_FUNTION_PARA_VALUE);
|
||||
|
||||
// wrong content input
|
||||
STR_TO_VARSTR(strArray[0], "POIN(2 5)"); // lack of the last letter of 'POINT'
|
||||
callGeomFromTextWrapper4(strArray, valTypeNormArray, 1, TSDB_CODE_FUNC_FUNTION_PARA_VALUE);
|
||||
STR_TO_VARSTR(strArray[0], "LINESTRING(3 -6.1,-7.1 4.2,)"); // redundant comma at the end
|
||||
callGeomFromTextWrapper4(strArray, valTypeNormArray, 1, TSDB_CODE_FUNC_FUNTION_PARA_VALUE);
|
||||
STR_TO_VARSTR(strArray[0], "POLYGON((-71.1 42.3,-71.2 42.4,-71.3 42.5,-71.1 42.8))"); // the first point and last one are not same
|
||||
callGeomFromTextWrapper4(strArray, valTypeNormArray, 1, TSDB_CODE_FUNC_FUNTION_PARA_VALUE);
|
||||
}
|
||||
|
||||
TEST(GeomIoFuncTest, asTextFunction) {
|
||||
// column input has been tested in geomFromTextFunction
|
||||
|
||||
TDRowValT valTypeArray[1] = {TD_VTYPE_NORM};
|
||||
|
||||
// empty input
|
||||
char strInput[TSDB_MAX_BINARY_LEN];
|
||||
STR_TO_VARSTR(strInput, "");
|
||||
SScalarParam *pOutputAsText;
|
||||
callAsTextWrapper1(TSDB_DATA_TYPE_GEOMETRY, strInput, valTypeArray, 1, &pOutputAsText);
|
||||
ASSERT_EQ(colDataIsNull_s(pOutputAsText->columnData, 0), true);
|
||||
destroyScalarParam(pOutputAsText, 1);
|
||||
|
||||
// NULL type input
|
||||
callAsTextWrapper1(TSDB_DATA_TYPE_NULL, 0, 0, 1, &pOutputAsText);
|
||||
ASSERT_EQ(colDataIsNull_s(pOutputAsText->columnData, 0), true);
|
||||
destroyScalarParam(pOutputAsText, 1);
|
||||
|
||||
// wrong type input [ToDo] make sure it is handled in geomFunc
|
||||
int32_t intInput = 3;
|
||||
callAsTextWrapper2(TSDB_DATA_TYPE_INT, &intInput, valTypeArray, 1, TSDB_CODE_FUNC_FUNTION_PARA_VALUE);
|
||||
|
||||
// wrong content input
|
||||
STR_TO_VARSTR(strInput, "XXX");
|
||||
callAsTextWrapper2(TSDB_DATA_TYPE_GEOMETRY, strInput, valTypeArray, 1, TSDB_CODE_FUNC_FUNTION_PARA_VALUE);
|
||||
}
|
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "geomFuncTestUtil.h"
|
||||
|
||||
void callGeomRelationFuncAndCompareResult(FScalarExecProcess geomRelationFunc,
|
||||
SScalarParam *pInput, int32_t rowNum,
|
||||
int32_t expectedCode, int8_t expectedResult[]) {
|
||||
SScalarParam *pOutput;
|
||||
makeOneScalarParam(&pOutput, TSDB_DATA_TYPE_BOOL, 0, 0, rowNum);
|
||||
int32_t code = geomRelationFunc(pInput, 2, pOutput);
|
||||
ASSERT_EQ(code, expectedCode);
|
||||
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
int8_t res = -1;
|
||||
for (int32_t i = 0; i < rowNum; ++i) {
|
||||
bool isNull1 = colDataIsNull_s(pOutput->columnData, i);
|
||||
if (isNull1) {
|
||||
res = -1;
|
||||
}
|
||||
else {
|
||||
res = *(bool*)colDataGetData(pOutput->columnData, i);
|
||||
}
|
||||
|
||||
ASSERT_EQ(res, expectedResult[i]);
|
||||
}
|
||||
}
|
||||
|
||||
destroyScalarParam(pOutput, 1);
|
||||
destroyScalarParam(pInput, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
-- Use the following SQL to get expected results for all relation functions in PostgreSQL with PostGIS
|
||||
WITH geom_str AS
|
||||
(SELECT 'POINT(3.5 7.0)' AS g1, 'POINT(3.5 7.0)' AS g2
|
||||
UNION ALL
|
||||
SELECT 'POINT(3.0 3.0)' AS g1, 'LINESTRING(1.0 1.0, 2.0 2.0, 5.0 6.0)' AS g2
|
||||
UNION ALL
|
||||
SELECT 'POINT(3.0 6.0)' AS g1, 'POLYGON((3.0 6.0, 5.0 6.0, 5.0 8.0, 3.0 8.0, 3.0 6.0))' AS g2
|
||||
UNION ALL
|
||||
SELECT 'LINESTRING(1.0 1.0, 2.0 2.0, 5.0 5.0)' AS g1, 'LINESTRING(1.0 4.0, 2.0 3.0, 5.0 0.0)' AS g2
|
||||
UNION ALL
|
||||
SELECT 'LINESTRING(3.0 7.0, 4.0 7.0, 5.0 7.0)' AS g1, 'POLYGON((3.0 6.0, 5.0 6.0, 5.0 8.0, 3.0 8.0, 3.0 6.0))' AS g2
|
||||
UNION ALL
|
||||
SELECT 'POLYGON((3.0 6.0, 5.0 6.0, 5.0 8.0, 3.0 8.0, 3.0 6.0))' AS g1, 'POLYGON((5.0 6.0, 7.0 6.0, 7.0 8.0, 5.0 8.0, 5.0 6.0))' AS g2
|
||||
)
|
||||
SELECT ST_Intersects(g1, g2), ST_Equals(g1, g2), ST_Touches(g1, g2), ST_Covers(g1, g2), ST_Contains(g1, g2), ST_ContainsProperly(g1, g2) FROM geom_str
|
||||
*/
|
||||
void geomRelationFuncTest(FScalarExecProcess geomRelationFunc, int8_t expectedResults[6][6]) {
|
||||
const int32_t rowNum = 6;
|
||||
|
||||
char strArray1[rowNum][TSDB_MAX_BINARY_LEN];
|
||||
STR_TO_VARSTR(strArray1[0], "POINT(3.5 7.0)");
|
||||
STR_TO_VARSTR(strArray1[1], "POINT(3.0 3.0)");
|
||||
STR_TO_VARSTR(strArray1[2], "POINT(3.0 6.0)");
|
||||
STR_TO_VARSTR(strArray1[3], "LINESTRING(1.0 1.0, 2.0 2.0, 5.0 5.0)");
|
||||
STR_TO_VARSTR(strArray1[4], "LINESTRING(3.0 7.0, 4.0 7.0, 5.0 7.0)");
|
||||
STR_TO_VARSTR(strArray1[5], "POLYGON((3.0 6.0, 5.0 6.0, 5.0 8.0, 3.0 8.0, 3.0 6.0))");
|
||||
TDRowValT valTypeArray1[rowNum] = {TD_VTYPE_NORM, TD_VTYPE_NORM, TD_VTYPE_NORM, TD_VTYPE_NORM, TD_VTYPE_NORM, TD_VTYPE_NORM};
|
||||
|
||||
char strArray2[rowNum][TSDB_MAX_BINARY_LEN];
|
||||
STR_TO_VARSTR(strArray2[0], "POINT(3.5 7.0)");
|
||||
STR_TO_VARSTR(strArray2[1], "LINESTRING(1.0 1.0, 2.0 2.0, 5.0 6.0)");
|
||||
STR_TO_VARSTR(strArray2[2], "POLYGON((3.0 6.0, 5.0 6.0, 5.0 8.0, 3.0 8.0, 3.0 6.0))");
|
||||
STR_TO_VARSTR(strArray2[3], "LINESTRING(1.0 4.0, 2.0 3.0, 5.0 0.0)");
|
||||
STR_TO_VARSTR(strArray2[4], "POLYGON((3.0 6.0, 5.0 6.0, 5.0 8.0, 3.0 8.0, 3.0 6.0))");
|
||||
STR_TO_VARSTR(strArray2[5], "POLYGON((5.0 6.0, 7.0 6.0, 7.0 8.0, 5.0 8.0, 5.0 6.0))");
|
||||
TDRowValT valTypeArray2[rowNum] = {TD_VTYPE_NORM, TD_VTYPE_NORM, TD_VTYPE_NORM, TD_VTYPE_NORM, TD_VTYPE_NORM, TD_VTYPE_NORM};
|
||||
|
||||
// two columns input
|
||||
SScalarParam *pInput = (SScalarParam *)taosMemoryCalloc(2, sizeof(SScalarParam));
|
||||
callGeomFromTextWrapper5(strArray1, valTypeArray1, rowNum, pInput); //pInput come from GeomFromText()
|
||||
callGeomFromTextWrapper5(strArray2, valTypeArray2, rowNum, pInput + 1);
|
||||
callGeomRelationFuncAndCompareResult(geomRelationFunc, pInput, rowNum, TSDB_CODE_SUCCESS, expectedResults[0]);
|
||||
|
||||
// swap two columns
|
||||
pInput = (SScalarParam *)taosMemoryCalloc(2, sizeof(SScalarParam));
|
||||
callGeomFromTextWrapper5(strArray2, valTypeArray2, rowNum, pInput);
|
||||
callGeomFromTextWrapper5(strArray1, valTypeArray1, rowNum, pInput + 1);
|
||||
callGeomRelationFuncAndCompareResult(geomRelationFunc, pInput, rowNum, TSDB_CODE_SUCCESS, expectedResults[1]);
|
||||
|
||||
// constant and column input
|
||||
pInput = (SScalarParam *)taosMemoryCalloc(2, sizeof(SScalarParam));
|
||||
callGeomFromTextWrapper5(strArray1, valTypeArray1, 1, pInput);
|
||||
callGeomFromTextWrapper5(strArray2, valTypeArray2, rowNum, pInput + 1);
|
||||
callGeomRelationFuncAndCompareResult(geomRelationFunc, pInput, rowNum, TSDB_CODE_SUCCESS, expectedResults[2]);
|
||||
|
||||
// column and constant input
|
||||
pInput = (SScalarParam *)taosMemoryCalloc(2, sizeof(SScalarParam));
|
||||
callGeomFromTextWrapper5(strArray1, valTypeArray1, rowNum, pInput);
|
||||
callGeomFromTextWrapper5(strArray2, valTypeArray2, 1, pInput + 1);
|
||||
callGeomRelationFuncAndCompareResult(geomRelationFunc, pInput, rowNum, TSDB_CODE_SUCCESS, expectedResults[3]);
|
||||
|
||||
// two constants input
|
||||
pInput = (SScalarParam *)taosMemoryCalloc(2, sizeof(SScalarParam));
|
||||
callGeomFromTextWrapper5(strArray1, valTypeArray1, 1, pInput);
|
||||
callGeomFromTextWrapper5(strArray2, valTypeArray2, 1, pInput + 1);
|
||||
callGeomRelationFuncAndCompareResult(geomRelationFunc, pInput, 1, TSDB_CODE_SUCCESS, expectedResults[4]);
|
||||
|
||||
// two columns with NULL value input
|
||||
pInput = (SScalarParam *)taosMemoryCalloc(2, sizeof(SScalarParam));
|
||||
valTypeArray1[2] = TD_VTYPE_NULL;
|
||||
valTypeArray2[4] = TD_VTYPE_NULL;
|
||||
callGeomFromTextWrapper5(strArray1, valTypeArray1, rowNum, pInput);
|
||||
callGeomFromTextWrapper5(strArray2, valTypeArray2, rowNum, pInput + 1);
|
||||
callGeomRelationFuncAndCompareResult(geomRelationFunc, pInput, rowNum, TSDB_CODE_SUCCESS, expectedResults[5]);
|
||||
|
||||
// first NULL type input
|
||||
pInput = (SScalarParam *)taosMemoryCalloc(2, sizeof(SScalarParam));
|
||||
setScalarParam(pInput, TSDB_DATA_TYPE_NULL, 0, 0, 1);
|
||||
callGeomFromTextWrapper5(strArray2, valTypeArray2, rowNum, pInput + 1);
|
||||
int8_t expectedResultNullType[rowNum] = {-1, -1, -1, -1, -1, -1};
|
||||
callGeomRelationFuncAndCompareResult(geomRelationFunc, pInput, rowNum, TSDB_CODE_SUCCESS, expectedResultNullType);
|
||||
|
||||
// second NULL type input
|
||||
pInput = (SScalarParam *)taosMemoryCalloc(2, sizeof(SScalarParam));
|
||||
callGeomFromTextWrapper5(strArray1, valTypeArray1, rowNum, pInput);
|
||||
setScalarParam(pInput + 1, TSDB_DATA_TYPE_NULL, 0, 0, 1);
|
||||
callGeomRelationFuncAndCompareResult(geomRelationFunc, pInput, rowNum, TSDB_CODE_SUCCESS, expectedResultNullType);
|
||||
|
||||
// first empty content input
|
||||
pInput = (SScalarParam *)taosMemoryCalloc(2, sizeof(SScalarParam));
|
||||
char strInput[TSDB_MAX_BINARY_LEN];
|
||||
STR_TO_VARSTR(strInput, "");
|
||||
setScalarParam(pInput, TSDB_DATA_TYPE_GEOMETRY, strInput, valTypeArray1, 1);
|
||||
callGeomFromTextWrapper5(strArray2, valTypeArray2, rowNum, pInput + 1);
|
||||
callGeomRelationFuncAndCompareResult(geomRelationFunc, pInput, rowNum, TSDB_CODE_SUCCESS, expectedResultNullType);
|
||||
|
||||
// first wrong type input
|
||||
pInput = (SScalarParam *)taosMemoryCalloc(2, sizeof(SScalarParam));
|
||||
int32_t intInput = 3;
|
||||
setScalarParam(pInput, TSDB_DATA_TYPE_INT, &intInput, valTypeArray1, 1);
|
||||
callGeomFromTextWrapper5(strArray2, valTypeArray2, rowNum, pInput + 1);
|
||||
callGeomRelationFuncAndCompareResult(geomRelationFunc, pInput, rowNum, TSDB_CODE_FUNC_FUNTION_PARA_VALUE, 0);
|
||||
|
||||
// second wrong content input
|
||||
pInput = (SScalarParam *)taosMemoryCalloc(2, sizeof(SScalarParam));
|
||||
STR_TO_VARSTR(strInput, "XXX");
|
||||
callGeomFromTextWrapper5(strArray1, valTypeArray1, rowNum, pInput);
|
||||
setScalarParam(pInput + 1, TSDB_DATA_TYPE_GEOMETRY, strInput, valTypeArray2, 1);
|
||||
callGeomRelationFuncAndCompareResult(geomRelationFunc, pInput, rowNum, TSDB_CODE_FUNC_FUNTION_PARA_VALUE, 0);
|
||||
}
|
||||
|
||||
TEST(GeomRelationFuncTest, intersectsFunction) {
|
||||
// 1: true, 0: false, -1: null
|
||||
int8_t expectedResults[6][6] = {
|
||||
{1, 0, 1, 1, 1, 1}, // two columns
|
||||
{1, 0, 1, 1, 1, 1}, // two columns swpped
|
||||
{1, 0, 1, 0, 1, 0}, // first constant
|
||||
{1, 0, 0, 0, 1, 1}, // second constant
|
||||
{1}, // two constant
|
||||
{1, 0, -1, 1, -1, 1} // with Null value
|
||||
};
|
||||
|
||||
geomRelationFuncTest(intersectsFunction, expectedResults);
|
||||
}
|
||||
|
||||
TEST(GeomRelationFuncTest, equalsFunction) {
|
||||
// 1: true, 0: false, -1: null
|
||||
int8_t expectedResults[6][6] = {
|
||||
{1, 0, 0, 0, 0, 0}, // two columns
|
||||
{1, 0, 0, 0, 0, 0}, // two columns swapped
|
||||
{1, 0, 0, 0, 0, 0}, // first constant
|
||||
{1, 0, 0, 0, 0, 0}, // second constant
|
||||
{1}, // two constant
|
||||
{1, 0, -1, 0, -1, 0} // with Null value
|
||||
};
|
||||
|
||||
geomRelationFuncTest(equalsFunction, expectedResults);
|
||||
}
|
||||
|
||||
TEST(GeomRelationFuncTest, touchesFunction) {
|
||||
// 1: true, 0: false, -1: null
|
||||
int8_t expectedResults[6][6] = {
|
||||
{0, 0, 1, 0, 0, 1}, // two columns
|
||||
{0, 0, 1, 0, 0, 1}, // two columns swapped
|
||||
{0, 0, 0, 0, 0, 0}, // first constant
|
||||
{0, 0, 0, 0, 0, 0}, // second constant
|
||||
{0}, // two constant
|
||||
{0, 0, -1, 0, -1, 1} // with Null value
|
||||
};
|
||||
|
||||
geomRelationFuncTest(touchesFunction, expectedResults);
|
||||
}
|
||||
|
||||
TEST(GeomRelationFuncTest, coversFunction) {
|
||||
// 1: true, 0: false, -1: null
|
||||
int8_t expectedResults[6][6] = {
|
||||
{1, 0, 0, 0, 0, 0}, // two columns
|
||||
{1, 0, 1, 0, 1, 0}, // two columns swapped
|
||||
{1, 0, 0, 0, 0, 0}, // first constant
|
||||
{1, 0, 0, 0, 1, 1}, // second constant
|
||||
{1}, // two constant
|
||||
{1, 0, -1, 0, -1, 0} // with Null value
|
||||
};
|
||||
|
||||
geomRelationFuncTest(coversFunction, expectedResults);
|
||||
}
|
||||
|
||||
TEST(GeomRelationFuncTest, containsFunction) {
|
||||
// 1: true, 0: false, -1: null
|
||||
int8_t expectedResults[6][6] = {
|
||||
{1, 0, 0, 0, 0, 0}, // two columns
|
||||
{1, 0, 0, 0, 1, 0}, // two columns swapped
|
||||
{1, 0, 0, 0, 0, 0}, // first constant
|
||||
{1, 0, 0, 0, 1, 1}, // second constant
|
||||
{1}, // two constant
|
||||
{1, 0, -1, 0, -1, 0} // with Null value
|
||||
};
|
||||
|
||||
geomRelationFuncTest(containsFunction, expectedResults);
|
||||
}
|
||||
|
||||
TEST(GeomRelationFuncTest, containsProperlyFunction) {
|
||||
// 1: true, 0: false, -1: null
|
||||
int8_t expectedResults[6][6] = {
|
||||
{1, 0, 0, 0, 0, 0}, // two columns
|
||||
{1, 0, 0, 0, 0, 0}, // two columns swapped
|
||||
{1, 0, 0, 0, 0, 0}, // first constant
|
||||
{1, 0, 0, 0, 1, 1}, // second constant
|
||||
{1}, // two constant
|
||||
{1, 0, -1, 0, -1, 0} // with Null value
|
||||
};
|
||||
|
||||
geomRelationFuncTest(containsProperlyFunction, expectedResults);
|
||||
}
|
|
@ -738,7 +738,7 @@ static MemTable* idxInternalCacheCreate(int8_t type) {
|
|||
|
||||
MemTable* tbl = taosMemoryCalloc(1, sizeof(MemTable));
|
||||
idxMemRef(tbl);
|
||||
// if (ttype == TSDB_DATA_TYPE_BINARY || ttype == TSDB_DATA_TYPE_NCHAR) {
|
||||
// if (ttype == TSDB_DATA_TYPE_BINARY || ttype == TSDB_DATA_TYPE_NCHAR || ttype == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
tbl->mem = tSkipListCreate(MAX_SKIP_LIST_LEVEL, ttype, MAX_INDEX_KEY_LEN, cmpFn, SL_ALLOW_DUP_KEY, idxCacheTermGet);
|
||||
//}
|
||||
return tbl;
|
||||
|
|
|
@ -76,7 +76,7 @@ char* idxInt2str(int64_t val, char* dst, int radix) {
|
|||
return dst - 1;
|
||||
}
|
||||
__compar_fn_t idxGetCompar(int8_t type) {
|
||||
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
|
||||
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return (__compar_fn_t)strcmp;
|
||||
}
|
||||
return getComparFunc(type, 0);
|
||||
|
@ -107,7 +107,8 @@ static FORCE_INLINE TExeCond tCompareEqual(void* a, void* b, int8_t type) {
|
|||
return tCompare(func, QUERY_TERM, a, b, type);
|
||||
}
|
||||
TExeCond tCompare(__compar_fn_t func, int8_t cmptype, void* a, void* b, int8_t dtype) {
|
||||
if (dtype == TSDB_DATA_TYPE_BINARY || dtype == TSDB_DATA_TYPE_NCHAR || dtype == TSDB_DATA_TYPE_VARBINARY) {
|
||||
if (dtype == TSDB_DATA_TYPE_BINARY || dtype == TSDB_DATA_TYPE_NCHAR ||
|
||||
dtype == TSDB_DATA_TYPE_VARBINARY || dtype == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return tDoCompare(func, cmptype, a, b);
|
||||
}
|
||||
#if 1
|
||||
|
@ -354,7 +355,8 @@ int32_t idxConvertData(void* src, int8_t type, void** dst) {
|
|||
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_VARCHAR: { // TSDB_DATA_TYPE_BINARY
|
||||
case TSDB_DATA_TYPE_VARCHAR: // TSDB_DATA_TYPE_BINARY
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
tlen = taosEncodeBinary(NULL, src, strlen(src));
|
||||
*dst = taosMemoryCalloc(1, tlen + 1);
|
||||
tlen = taosEncodeBinary(dst, src, strlen(src));
|
||||
|
@ -444,7 +446,8 @@ int32_t idxConvertDataToStr(void* src, int8_t type, void** dst) {
|
|||
*dst = (char*)*dst - tlen;
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_VARCHAR: { // TSDB_DATA_TYPE_BINARY
|
||||
case TSDB_DATA_TYPE_VARCHAR: // TSDB_DATA_TYPE_BINARY
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
tlen = taosEncodeBinary(NULL, varDataVal(src), varDataLen(src));
|
||||
*dst = taosMemoryCalloc(1, tlen + 1);
|
||||
tlen = taosEncodeBinary(dst, varDataVal(src), varDataLen(src));
|
||||
|
|
|
@ -25,7 +25,7 @@ int indexJsonPut(SIndexJson *index, SIndexJsonMultiTerm *terms, uint64_t uid) {
|
|||
if (p->colType == TSDB_DATA_TYPE_BOOL) {
|
||||
p->colType = TSDB_DATA_TYPE_INT;
|
||||
} else if (p->colType == TSDB_DATA_TYPE_VARCHAR || p->colType == TSDB_DATA_TYPE_NCHAR ||
|
||||
p->colType == TSDB_DATA_TYPE_BINARY) {
|
||||
p->colType == TSDB_DATA_TYPE_BINARY || p->colType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
// p->colType = TSDB_DATA_TYPE_NCHAR;
|
||||
} else {
|
||||
p->colType = TSDB_DATA_TYPE_DOUBLE;
|
||||
|
@ -43,7 +43,7 @@ int indexJsonSearch(SIndexJson *index, SIndexJsonMultiTermQuery *tq, SArray *res
|
|||
if (p->colType == TSDB_DATA_TYPE_BOOL) {
|
||||
p->colType = TSDB_DATA_TYPE_INT;
|
||||
} else if (p->colType == TSDB_DATA_TYPE_VARCHAR || p->colType == TSDB_DATA_TYPE_NCHAR ||
|
||||
p->colType == TSDB_DATA_TYPE_BINARY) {
|
||||
p->colType == TSDB_DATA_TYPE_BINARY || p->colType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
// p->colType = TSDB_DATA_TYPE_NCHAR;
|
||||
} else {
|
||||
p->colType = TSDB_DATA_TYPE_DOUBLE;
|
||||
|
|
|
@ -545,7 +545,8 @@ int tfileWriterPut(TFileWriter* tw, void* data, bool order) {
|
|||
|
||||
int8_t colType = tw->header.colType;
|
||||
colType = IDX_TYPE_GET_TYPE(colType);
|
||||
if (colType == TSDB_DATA_TYPE_BINARY || colType == TSDB_DATA_TYPE_NCHAR) {
|
||||
if (colType == TSDB_DATA_TYPE_BINARY || colType == TSDB_DATA_TYPE_NCHAR ||
|
||||
colType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
fn = tfileStrCompare;
|
||||
} else {
|
||||
fn = getComparFunc(colType, 0);
|
||||
|
|
|
@ -87,7 +87,7 @@ SIndexTerm *indexTermCreateT(int64_t suid, SIndexOperOnColumn oper, uint8_t colT
|
|||
int16_t sz = nColVal;
|
||||
memcpy(buf, (uint16_t *)&sz, 2);
|
||||
memcpy(buf + 2, colVal, nColVal);
|
||||
if (colType == TSDB_DATA_TYPE_BINARY) {
|
||||
if (colType == TSDB_DATA_TYPE_BINARY || colType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return indexTermCreate(suid, oper, colType, colName, nColName, buf, sizeof(buf));
|
||||
} else {
|
||||
return indexTermCreate(suid, oper, colType, colName, nColName, colVal, nColVal);
|
||||
|
|
|
@ -574,7 +574,7 @@ SIndexTerm* indexTermCreateT(int64_t suid, SIndexOperOnColumn oper, uint8_t colT
|
|||
int16_t sz = nColVal;
|
||||
memcpy(buf, (uint16_t*)&sz, 2);
|
||||
memcpy(buf + 2, colVal, nColVal);
|
||||
if (colType == TSDB_DATA_TYPE_BINARY) {
|
||||
if (colType == TSDB_DATA_TYPE_BINARY || colType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return indexTermCreate(suid, oper, colType, colName, nColName, buf, sizeof(buf));
|
||||
} else {
|
||||
return indexTermCreate(suid, oper, colType, colName, nColName, colVal, nColVal);
|
||||
|
|
|
@ -24,7 +24,7 @@ SIndexTerm* indexTermCreateT(int64_t suid, SIndexOperOnColumn oper, uint8_t colT
|
|||
int16_t sz = nColVal;
|
||||
memcpy(buf, (uint16_t*)&sz, 2);
|
||||
memcpy(buf + 2, colVal, nColVal);
|
||||
if (colType == TSDB_DATA_TYPE_BINARY) {
|
||||
if (colType == TSDB_DATA_TYPE_BINARY || colType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return indexTermCreate(suid, oper, colType, colName, nColName, buf, sizeof(buf));
|
||||
} else {
|
||||
return indexTermCreate(suid, oper, colType, colName, nColName, colVal, nColVal);
|
||||
|
|
|
@ -157,7 +157,8 @@ static int32_t valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
|
|||
break;
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY: {
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
int32_t len = pSrc->node.resType.bytes + 1;
|
||||
pDst->datum.p = taosMemoryCalloc(1, len);
|
||||
if (NULL == pDst->datum.p) {
|
||||
|
|
|
@ -3176,6 +3176,7 @@ static int32_t datumToJson(const void* pObj, SJson* pJson) {
|
|||
}
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
code = tjsonAddStringToObject(pJson, jkValueDatum, varDataVal(pNode->datum.p));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_JSON: {
|
||||
|
@ -3289,7 +3290,8 @@ static int32_t jsonToDatum(const SJson* pJson, void* pObj) {
|
|||
break;
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY: {
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
pNode->datum.p = taosMemoryCalloc(1, pNode->node.resType.bytes + 1);
|
||||
if (NULL == pNode->datum.p) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
|
|
@ -109,6 +109,7 @@ static bool valueNodeEqual(const SValueNode* a, const SValueNode* b) {
|
|||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
COMPARE_VARDATA_FIELD(datum.p);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
|
|
|
@ -825,6 +825,7 @@ static int32_t datumToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
|||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
code = tlvEncodeBinary(pEncoder, VALUE_CODE_DATUM, pNode->datum.p, varDataTLen(pNode->datum.p));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
|
@ -923,7 +924,8 @@ static int32_t msgToDatum(STlv* pTlv, void* pObj) {
|
|||
break;
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY: {
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
if (pTlv->len > pNode->node.resType.bytes + VARSTR_HEADER_SIZE) {
|
||||
code = TSDB_CODE_FAILED;
|
||||
break;
|
||||
|
|
|
@ -1575,6 +1575,7 @@ void* nodesGetValueFromNode(SValueNode* pNode) {
|
|||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
return (void*)pNode->datum.p;
|
||||
default:
|
||||
break;
|
||||
|
@ -1637,6 +1638,7 @@ int32_t nodesSetValueNodeValue(SValueNode* pNode, void* value) {
|
|||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
pNode->datum.p = (char*)value;
|
||||
break;
|
||||
default:
|
||||
|
@ -1694,7 +1696,8 @@ char* nodesGetStrValueFromNode(SValueNode* pNode) {
|
|||
}
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY: {
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
int32_t bufSize = varDataLen(pNode->datum.p) + 2 + 1;
|
||||
void* buf = taosMemoryMalloc(bufSize);
|
||||
if (NULL == buf) {
|
||||
|
@ -2130,6 +2133,7 @@ void nodesValueNodeToVariant(const SValueNode* pNode, SVariant* pVal) {
|
|||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
pVal->pz = taosMemoryMalloc(pVal->nLen + 1);
|
||||
memcpy(pVal->pz, pNode->datum.p, pVal->nLen);
|
||||
pVal->pz[pVal->nLen] = 0;
|
||||
|
|
|
@ -8,7 +8,7 @@ target_include_directories(
|
|||
|
||||
target_link_libraries(
|
||||
parser
|
||||
PRIVATE os util nodes catalog function scalar transport qcom
|
||||
PRIVATE os util nodes catalog function scalar geometry transport qcom
|
||||
)
|
||||
|
||||
if(${BUILD_TEST})
|
||||
|
|
|
@ -382,6 +382,7 @@ type_name(A) ::= VARCHAR NK_LP NK_INTEGER(B) NK_RP.
|
|||
type_name(A) ::= MEDIUMBLOB. { A = createDataType(TSDB_DATA_TYPE_MEDIUMBLOB); }
|
||||
type_name(A) ::= BLOB. { A = createDataType(TSDB_DATA_TYPE_BLOB); }
|
||||
type_name(A) ::= VARBINARY NK_LP NK_INTEGER(B) NK_RP. { A = createVarLenDataType(TSDB_DATA_TYPE_VARBINARY, &B); }
|
||||
type_name(A) ::= GEOMETRY NK_LP NK_INTEGER(B) NK_RP. { A = createVarLenDataType(TSDB_DATA_TYPE_GEOMETRY, &B); }
|
||||
type_name(A) ::= DECIMAL. { A = createDataType(TSDB_DATA_TYPE_DECIMAL); }
|
||||
type_name(A) ::= DECIMAL NK_LP NK_INTEGER NK_RP. { A = createDataType(TSDB_DATA_TYPE_DECIMAL); }
|
||||
type_name(A) ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP. { A = createDataType(TSDB_DATA_TYPE_DECIMAL); }
|
||||
|
|
|
@ -498,7 +498,7 @@ SNode* createCastFunctionNode(SAstCreateContext* pCxt, SNode* pExpr, SDataType d
|
|||
CHECK_OUT_OF_MEM(func);
|
||||
strcpy(func->functionName, "cast");
|
||||
func->node.resType = dt;
|
||||
if (TSDB_DATA_TYPE_VARCHAR == dt.type) {
|
||||
if (TSDB_DATA_TYPE_VARCHAR == dt.type || TSDB_DATA_TYPE_GEOMETRY == dt.type) {
|
||||
func->node.resType.bytes = func->node.resType.bytes + VARSTR_HEADER_SIZE;
|
||||
} else if (TSDB_DATA_TYPE_NCHAR == dt.type) {
|
||||
func->node.resType.bytes = func->node.resType.bytes * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE;
|
||||
|
|
|
@ -134,7 +134,8 @@ static int32_t smlBuildTagRow(SArray* cols, SBoundColInfo* tags, SSchema* pSchem
|
|||
taosArrayPush(*tagName, pTagSchema->name);
|
||||
STagVal val = {.cid = pTagSchema->colId, .type = pTagSchema->type};
|
||||
// strcpy(val.colName, pTagSchema->name);
|
||||
if (pTagSchema->type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (pTagSchema->type == TSDB_DATA_TYPE_BINARY ||
|
||||
pTagSchema->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
val.pData = (uint8_t*)kv->value;
|
||||
val.nData = kv->length;
|
||||
} else if (pTagSchema->type == TSDB_DATA_TYPE_NCHAR) {
|
||||
|
@ -236,7 +237,7 @@ int32_t smlBuildCol(STableDataCxt* pTableCxt, SSchema* schema, void* data, int32
|
|||
}
|
||||
pVal->value.pData = pUcs4;
|
||||
pVal->value.nData = len;
|
||||
} else if (kv->type == TSDB_DATA_TYPE_BINARY) {
|
||||
} else if (kv->type == TSDB_DATA_TYPE_BINARY || kv->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
pVal->value.nData = kv->length;
|
||||
pVal->value.pData = (uint8_t*)kv->value;
|
||||
} else {
|
||||
|
@ -363,7 +364,7 @@ int32_t smlBindData(SQuery* query, bool dataFormat, SArray* tags, SArray* colsSc
|
|||
}
|
||||
pVal->value.pData = pUcs4;
|
||||
pVal->value.nData = len;
|
||||
} else if (kv->type == TSDB_DATA_TYPE_BINARY) {
|
||||
} else if (kv->type == TSDB_DATA_TYPE_BINARY || kv->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
pVal->value.nData = kv->length;
|
||||
pVal->value.pData = (uint8_t*)kv->value;
|
||||
} else {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "scalar.h"
|
||||
#include "tglobal.h"
|
||||
#include "ttime.h"
|
||||
#include "geosWrapper.h"
|
||||
|
||||
#define NEXT_TOKEN_WITH_PREV(pSql, token) \
|
||||
do { \
|
||||
|
@ -305,6 +306,26 @@ static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// need to call geosFreeBuffer(*output) later
|
||||
static int parseGeometry(SToken *pToken, unsigned char **output, size_t *size) {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
|
||||
//[ToDo] support to parse WKB as well as WKT
|
||||
if (pToken->type == TK_NK_STRING) {
|
||||
code = initCtxGeomFromText();
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
code = doGeomFromText(pToken->z, output, size);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, STagVal* val,
|
||||
SMsgBuf* pMsgBuf) {
|
||||
int64_t iv;
|
||||
|
@ -446,7 +467,8 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema,
|
|||
break;
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
// Too long values will raise the invalid sql error message
|
||||
if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) {
|
||||
return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
|
||||
|
@ -1350,6 +1372,37 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql,
|
|||
pVal->value.nData = pToken->n;
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
int32_t code = TSDB_CODE_FAILED;
|
||||
unsigned char *output = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
code = parseGeometry(pToken, &output, &size);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
code = buildSyntaxErrMsg(&pCxt->msg, getThreadLocalGeosCtx()->errMsg, pToken->z);
|
||||
}
|
||||
// Too long values will raise the invalid sql error message
|
||||
else if (size > pSchema->bytes) {
|
||||
code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name);
|
||||
}
|
||||
else {
|
||||
pVal->value.pData = taosMemoryMalloc(size);
|
||||
if (NULL == pVal->value.pData) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
memcpy(pVal->value.pData, output, size);
|
||||
pVal->value.nData = size;
|
||||
}
|
||||
}
|
||||
|
||||
geosFreeBuffer(output);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||
if (parseTime(pSql, pToken, timePrec, &pVal->value.val, &pCxt->msg) != TSDB_CODE_SUCCESS) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "invalid timestamp", pToken->z);
|
||||
|
|
|
@ -128,7 +128,8 @@ int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, const ch
|
|||
} else {
|
||||
STagVal val = {.cid = pTagSchema->colId, .type = pTagSchema->type};
|
||||
// strcpy(val.colName, pTagSchema->name);
|
||||
if (pTagSchema->type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (pTagSchema->type == TSDB_DATA_TYPE_BINARY ||
|
||||
pTagSchema->type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
val.pData = (uint8_t*)bind[c].buffer;
|
||||
val.nData = colLen;
|
||||
} else if (pTagSchema->type == TSDB_DATA_TYPE_NCHAR) {
|
||||
|
|
|
@ -103,6 +103,7 @@ static SKeyword keywordTable[] = {
|
|||
{"FORCE", TK_FORCE},
|
||||
{"FUNCTION", TK_FUNCTION},
|
||||
{"FUNCTIONS", TK_FUNCTIONS},
|
||||
{"GEOMETRY", TK_GEOMETRY},
|
||||
{"GRANT", TK_GRANT},
|
||||
{"GRANTS", TK_GRANTS},
|
||||
{"GROUP", TK_GROUP},
|
||||
|
|
|
@ -1168,7 +1168,8 @@ static EDealRes translateNormalValue(STranslateContext* pCxt, SValueNode* pVal,
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY: {
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
if (strict && (pVal->node.resType.bytes > targetDt.bytes - VARSTR_HEADER_SIZE)) {
|
||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
|
||||
}
|
||||
|
@ -1241,7 +1242,7 @@ static EDealRes translateValueImpl(STranslateContext* pCxt, SValueNode* pVal, SD
|
|||
}
|
||||
|
||||
static int32_t calcTypeBytes(SDataType dt) {
|
||||
if (TSDB_DATA_TYPE_BINARY == dt.type) {
|
||||
if (TSDB_DATA_TYPE_BINARY == dt.type || TSDB_DATA_TYPE_GEOMETRY == dt.type) {
|
||||
return dt.bytes + VARSTR_HEADER_SIZE;
|
||||
} else if (TSDB_DATA_TYPE_NCHAR == dt.type) {
|
||||
return dt.bytes * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE;
|
||||
|
@ -2920,6 +2921,7 @@ static int32_t getPositionValue(const SValueNode* pVal) {
|
|||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_JSON:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
return -1;
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
return (pVal->datum.b ? 1 : 0);
|
||||
|
@ -4615,7 +4617,8 @@ static int32_t checkTableTagsSchema(STranslateContext* pCxt, SHashObj* pHash, SN
|
|||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
if ((TSDB_DATA_TYPE_VARCHAR == pTag->dataType.type && calcTypeBytes(pTag->dataType) > TSDB_MAX_TAGS_LEN) ||
|
||||
(TSDB_DATA_TYPE_NCHAR == pTag->dataType.type && calcTypeBytes(pTag->dataType) > TSDB_MAX_TAGS_LEN)) {
|
||||
(TSDB_DATA_TYPE_NCHAR == pTag->dataType.type && calcTypeBytes(pTag->dataType) > TSDB_MAX_TAGS_LEN) ||
|
||||
(TSDB_DATA_TYPE_GEOMETRY == pTag->dataType.type && calcTypeBytes(pTag->dataType) > TSDB_MAX_TAGS_LEN)) {
|
||||
code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN);
|
||||
}
|
||||
}
|
||||
|
@ -4666,7 +4669,8 @@ static int32_t checkTableColsSchema(STranslateContext* pCxt, SHashObj* pHash, in
|
|||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
if ((TSDB_DATA_TYPE_VARCHAR == pCol->dataType.type && calcTypeBytes(pCol->dataType) > TSDB_MAX_BINARY_LEN) ||
|
||||
(TSDB_DATA_TYPE_NCHAR == pCol->dataType.type && calcTypeBytes(pCol->dataType) > TSDB_MAX_NCHAR_LEN)) {
|
||||
(TSDB_DATA_TYPE_NCHAR == pCol->dataType.type && calcTypeBytes(pCol->dataType) > TSDB_MAX_NCHAR_LEN) ||
|
||||
(TSDB_DATA_TYPE_GEOMETRY == pCol->dataType.type && calcTypeBytes(pCol->dataType) > TSDB_MAX_GEOMETRY_LEN)) {
|
||||
code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,6 +99,7 @@ static int32_t setValueByBindParam(SValueNode* pVal, TAOS_MULTI_BIND* pParam) {
|
|||
switch (pParam->buffer_type) {
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
pVal->datum.p = taosMemoryCalloc(1, pVal->node.resType.bytes + VARSTR_HEADER_SIZE + 1);
|
||||
if (NULL == pVal->datum.p) {
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -108,6 +108,7 @@ class PlanStmtTest : public PlannerTestBase {
|
|||
switch (type) {
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_VARBINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
strncpy((char*)pBindParam->buffer, pVal, bytes);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
|
|
|
@ -52,6 +52,10 @@ static bool doValidateSchema(SSchema* pSchema, int32_t numOfCols, int32_t maxLen
|
|||
if (pSchema[i].bytes > TSDB_MAX_NCHAR_LEN) {
|
||||
return false;
|
||||
}
|
||||
} else if (pSchema[i].type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
if (pSchema[i].bytes > TSDB_MAX_GEOMETRY_LEN) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (pSchema[i].bytes != tDataTypes[pSchema[i].type].bytes) {
|
||||
return false;
|
||||
|
@ -297,6 +301,7 @@ int32_t dataConverToStr(char* str, int type, void* buf, int32_t bufSize, int32_t
|
|||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
if (bufSize < 0) {
|
||||
// tscError("invalid buf size");
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
|
|
|
@ -178,7 +178,7 @@ __compar_fn_t gUint64UsignCompare[] = {compareUint64Uint8, compareUint64Uint16,
|
|||
int8_t filterGetCompFuncIdx(int32_t type, int32_t optr) {
|
||||
int8_t comparFn = 0;
|
||||
|
||||
if (optr == OP_TYPE_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR)) {
|
||||
if (optr == OP_TYPE_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR && type != TSDB_DATA_TYPE_GEOMETRY)) {
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
|
@ -204,7 +204,7 @@ int8_t filterGetCompFuncIdx(int32_t type, int32_t optr) {
|
|||
}
|
||||
}
|
||||
|
||||
if (optr == OP_TYPE_NOT_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR)) {
|
||||
if (optr == OP_TYPE_NOT_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR && type != TSDB_DATA_TYPE_GEOMETRY)) {
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
|
@ -255,7 +255,8 @@ int8_t filterGetCompFuncIdx(int32_t type, int32_t optr) {
|
|||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
comparFn = 5;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
if (optr == OP_TYPE_MATCH) {
|
||||
comparFn = 19;
|
||||
} else if (optr == OP_TYPE_NMATCH) {
|
||||
|
@ -448,8 +449,9 @@ static FORCE_INLINE SFilterRangeNode *filterNewRange(SFilterRangeCtx *ctx, SFilt
|
|||
}
|
||||
|
||||
void *filterInitRangeCtx(int32_t type, int32_t options) {
|
||||
if (type > TSDB_DATA_TYPE_UBIGINT || type < TSDB_DATA_TYPE_BOOL || type == TSDB_DATA_TYPE_BINARY ||
|
||||
type == TSDB_DATA_TYPE_NCHAR) {
|
||||
if (type > TSDB_DATA_TYPE_UBIGINT || type < TSDB_DATA_TYPE_BOOL ||
|
||||
type == TSDB_DATA_TYPE_BINARY ||
|
||||
type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
qError("not supported range type:%d", type);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1567,6 +1569,7 @@ int32_t fltConverToStr(char *str, int type, void *buf, int32_t bufSize, int32_t
|
|||
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
if (bufSize < 0) {
|
||||
// tscError("invalid buf size");
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
|
@ -3739,7 +3742,8 @@ EDealRes fltReviseRewriter(SNode **pNode, void *pContext) {
|
|||
}
|
||||
|
||||
if (TSDB_DATA_TYPE_BINARY != valueNode->node.resType.type && TSDB_DATA_TYPE_NCHAR !=
|
||||
valueNode->node.resType.type) { return DEAL_RES_CONTINUE;
|
||||
valueNode->node.resType.type &&
|
||||
TSDB_DATA_TYPE_GEOMETRY != valueNode->node.resType.type) { return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
if (stat->precision < 0) {
|
||||
|
|
|
@ -289,7 +289,7 @@ static int32_t doScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarP
|
|||
static VarDataLenT tlength(char *input, int32_t type) { return varDataLen(input); }
|
||||
|
||||
static VarDataLenT tcharlength(char *input, int32_t type) {
|
||||
if (type == TSDB_DATA_TYPE_VARCHAR) {
|
||||
if (type == TSDB_DATA_TYPE_VARCHAR || type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return varDataLen(input);
|
||||
} else { // NCHAR
|
||||
return varDataLen(input) / TSDB_NCHAR_SIZE;
|
||||
|
@ -935,7 +935,8 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp
|
|||
}
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
if (inputType == TSDB_DATA_TYPE_BOOL) {
|
||||
// NOTE: sprintf will append '\0' at the end of string
|
||||
int32_t len = sprintf(varDataVal(output), "%.*s", (int32_t)(outputLen - VARSTR_HEADER_SIZE),
|
||||
|
|
|
@ -230,6 +230,8 @@ _getValueAddr_fn_t getVectorValueAddrFn(int32_t srcType) {
|
|||
p = getVectorValueAddr_VAR;
|
||||
} else if (srcType == TSDB_DATA_TYPE_NCHAR) {
|
||||
p = getVectorValueAddr_VAR;
|
||||
}else if(srcType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
p = getVectorValueAddr_VAR;
|
||||
} else {
|
||||
p = getVectorValueAddr_default;
|
||||
}
|
||||
|
@ -440,7 +442,7 @@ int32_t vectorConvertFromVarData(SSclVectorConvCtx *pCtx, int32_t *overflow) {
|
|||
if (vton) {
|
||||
memcpy(tmp, data, varDataTLen(data));
|
||||
} else {
|
||||
if (TSDB_DATA_TYPE_VARCHAR == convertType) {
|
||||
if (TSDB_DATA_TYPE_VARCHAR == convertType || TSDB_DATA_TYPE_GEOMETRY == convertType) {
|
||||
memcpy(tmp, varDataVal(data), varDataLen(data));
|
||||
tmp[varDataLen(data)] = 0;
|
||||
} else if (TSDB_DATA_TYPE_NCHAR == convertType) {
|
||||
|
@ -531,7 +533,7 @@ bool convertJsonValue(__compar_fn_t *fp, int32_t optr, int8_t typeLeft, int8_t t
|
|||
}
|
||||
|
||||
if (optr == OP_TYPE_LIKE || optr == OP_TYPE_NOT_LIKE || optr == OP_TYPE_MATCH || optr == OP_TYPE_NMATCH) {
|
||||
if (typeLeft != TSDB_DATA_TYPE_NCHAR && typeLeft != TSDB_DATA_TYPE_BINARY) {
|
||||
if (typeLeft != TSDB_DATA_TYPE_NCHAR && typeLeft != TSDB_DATA_TYPE_BINARY && typeLeft != TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -560,7 +562,8 @@ bool convertJsonValue(__compar_fn_t *fp, int32_t optr, int8_t typeLeft, int8_t t
|
|||
|
||||
if (IS_NUMERIC_TYPE(type)) {
|
||||
if (typeLeft == TSDB_DATA_TYPE_NCHAR ||
|
||||
typeLeft == TSDB_DATA_TYPE_VARCHAR) {
|
||||
typeLeft == TSDB_DATA_TYPE_VARCHAR ||
|
||||
typeLeft == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return false;
|
||||
} else if (typeLeft != type) {
|
||||
convertNumberToNumber(*pLeftData, pLeftOut, typeLeft, type);
|
||||
|
@ -568,13 +571,14 @@ bool convertJsonValue(__compar_fn_t *fp, int32_t optr, int8_t typeLeft, int8_t t
|
|||
}
|
||||
|
||||
if (typeRight == TSDB_DATA_TYPE_NCHAR ||
|
||||
typeRight == TSDB_DATA_TYPE_VARCHAR) {
|
||||
typeRight == TSDB_DATA_TYPE_VARCHAR ||
|
||||
typeRight == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
return false;
|
||||
} else if (typeRight != type) {
|
||||
convertNumberToNumber(*pRightData, pRightOut, typeRight, type);
|
||||
*pRightData = pRightOut;
|
||||
}
|
||||
} else if (type == TSDB_DATA_TYPE_BINARY) {
|
||||
} else if (type == TSDB_DATA_TYPE_BINARY || typeLeft == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
if (typeLeft == TSDB_DATA_TYPE_NCHAR) {
|
||||
*pLeftData = ncharTobinary(*pLeftData);
|
||||
*freeLeft = true;
|
||||
|
@ -864,7 +868,8 @@ int32_t vectorConvertSingleColImpl(const SScalarParam *pIn, SScalarParam *pOut,
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
return vectorConvertToVarData(&cCtx);
|
||||
}
|
||||
default:
|
||||
|
@ -875,27 +880,29 @@ int32_t vectorConvertSingleColImpl(const SScalarParam *pIn, SScalarParam *pOut,
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int8_t gConvertTypes[TSDB_DATA_TYPE_BLOB + 1][TSDB_DATA_TYPE_BLOB + 1] = {
|
||||
/* NULL BOOL TINY SMAL INT BIG FLOA DOUB VARC TIME NCHA UTIN USMA UINT UBIG JSON VARB DECI BLOB */
|
||||
/*NULL*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*BOOL*/ 0, 0, 2, 3, 4, 5, 6, 7, 5, 9, 7, 11, 12, 13, 14, 0, 7, 0, 0,
|
||||
/*TINY*/ 0, 0, 0, 3, 4, 5, 6, 7, 5, 9, 7, 3, 4, 5, 7, 0, 7, 0, 0,
|
||||
/*SMAL*/ 0, 0, 0, 0, 4, 5, 6, 7, 5, 9, 7, 3, 4, 5, 7, 0, 7, 0, 0,
|
||||
/*INT */ 0, 0, 0, 0, 0, 5, 6, 7, 5, 9, 7, 4, 4, 5, 7, 0, 7, 0, 0,
|
||||
/*BIGI*/ 0, 0, 0, 0, 0, 0, 6, 7, 5, 9, 7, 5, 5, 5, 7, 0, 7, 0, 0,
|
||||
/*FLOA*/ 0, 0, 0, 0, 0, 0, 0, 7, 7, 6, 7, 6, 6, 6, 6, 0, 7, 0, 0,
|
||||
/*DOUB*/ 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 0, 7, 0, 0,
|
||||
/*VARC*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 7, 7, 7, 7, 0, 0, 0, 0,
|
||||
/*TIME*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 7, 0, 7, 0, 0,
|
||||
/*NCHA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 0, 0, 0,
|
||||
/*UTIN*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 0, 7, 0, 0,
|
||||
/*USMA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 0, 7, 0, 0,
|
||||
/*UINT*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 7, 0, 0,
|
||||
/*UBIG*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0,
|
||||
/*JSON*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*VARB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*DECI*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*BLOB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int8_t gConvertTypes[TSDB_DATA_TYPE_MAX][TSDB_DATA_TYPE_MAX] = {
|
||||
/* NULL BOOL TINY SMAL INT BIG FLOA DOUB VARC TIME NCHA UTIN USMA UINT UBIG JSON GEOM VARB DECI BLOB MEDB*/
|
||||
/*NULL*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*BOOL*/ 0, 0, 2, 3, 4, 5, 6, 7, 5, 9, 7, 11, 12, 13, 14, 0, 7, 0, 0, 0, 0,
|
||||
/*TINY*/ 0, 0, 0, 3, 4, 5, 6, 7, 5, 9, 7, 3, 4, 5, 7, 0, 7, 0, 0, 0, 0,
|
||||
/*SMAL*/ 0, 0, 0, 0, 4, 5, 6, 7, 5, 9, 7, 3, 4, 5, 7, 0, 7, 0, 0, 0, 0,
|
||||
/*INT */ 0, 0, 0, 0, 0, 5, 6, 7, 5, 9, 7, 4, 4, 5, 7, 0, 7, 0, 0, 0, 0,
|
||||
/*BIGI*/ 0, 0, 0, 0, 0, 0, 6, 7, 5, 9, 7, 5, 5, 5, 7, 0, 7, 0, 0, 0, 0,
|
||||
/*FLOA*/ 0, 0, 0, 0, 0, 0, 0, 7, 7, 6, 7, 6, 6, 6, 6, 0, 7, 0, 0, 0, 0,
|
||||
/*DOUB*/ 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 0, 7, 0, 0, 0, 0,
|
||||
/*VARC*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0,
|
||||
/*TIME*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 7, 0, 7, 0, 0, 0, 0,
|
||||
/*NCHA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0,
|
||||
/*UTIN*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 0, 7, 0, 0, 0, 0,
|
||||
/*USMA*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 0, 7, 0, 0, 0, 0,
|
||||
/*UINT*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 7, 0, 0, 0, 0,
|
||||
/*UBIG*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,
|
||||
/*JSON*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*VARB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*DECI*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*BLOB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*MEDB*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*GEOM*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
int32_t vectorGetConvertType(int32_t type1, int32_t type2) {
|
||||
if (type1 == type2) {
|
||||
|
|
|
@ -4,6 +4,7 @@ add_library(util STATIC ${UTIL_SRC})
|
|||
if (DEFINED GRANT_CFG_INCLUDE_DIR)
|
||||
add_definitions(-DGRANTS_CFG)
|
||||
endif()
|
||||
|
||||
target_include_directories(
|
||||
util
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/util"
|
||||
|
@ -15,10 +16,9 @@ target_link_libraries(
|
|||
util
|
||||
PUBLIC os
|
||||
PUBLIC lz4_static
|
||||
PUBLIC api cjson
|
||||
PUBLIC api cjson geos_c
|
||||
)
|
||||
|
||||
if(${BUILD_TEST})
|
||||
ADD_SUBDIRECTORY(test)
|
||||
endif(${BUILD_TEST})
|
||||
|
||||
|
|
|
@ -1284,7 +1284,7 @@ int32_t comparewcsPatternNMatch(const void *pLeft, const void *pRight) {
|
|||
__compar_fn_t getComparFunc(int32_t type, int32_t optr) {
|
||||
__compar_fn_t comparFn = NULL;
|
||||
|
||||
if (optr == OP_TYPE_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR)) {
|
||||
if (optr == OP_TYPE_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR && type != TSDB_DATA_TYPE_GEOMETRY)) {
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
|
@ -1307,7 +1307,7 @@ __compar_fn_t getComparFunc(int32_t type, int32_t optr) {
|
|||
}
|
||||
}
|
||||
|
||||
if (optr == OP_TYPE_NOT_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR)) {
|
||||
if (optr == OP_TYPE_NOT_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR && type != TSDB_DATA_TYPE_GEOMETRY)) {
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
|
@ -1351,7 +1351,8 @@ __compar_fn_t getComparFunc(int32_t type, int32_t optr) {
|
|||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
comparFn = compareDoubleVal;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY: {
|
||||
if (optr == OP_TYPE_MATCH) {
|
||||
comparFn = comparestrRegexMatch;
|
||||
} else if (optr == OP_TYPE_NMATCH) {
|
||||
|
@ -1436,6 +1437,7 @@ __compar_fn_t getKeyComparFunc(int32_t keyType, int32_t order) {
|
|||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
return (order == TSDB_ORDER_ASC) ? compareUint64Val : compareUint64ValDesc;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
return (order == TSDB_ORDER_ASC) ? compareLenPrefixedStr : compareLenPrefixedStrDesc;
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
return (order == TSDB_ORDER_ASC) ? compareLenPrefixedWStr : compareLenPrefixedWStrDesc;
|
||||
|
|
|
@ -1385,6 +1385,14 @@ static struct {
|
|||
.endFn = tCompBinaryEnd,
|
||||
.getI64 = NULL,
|
||||
.putI64 = NULL},
|
||||
{.type = TSDB_DATA_TYPE_GEOMETRY,
|
||||
.bytes = 1,
|
||||
.isVarLen = 1,
|
||||
.startFn = tCompBinaryStart,
|
||||
.cmprFn = tCompBinary,
|
||||
.endFn = tCompBinaryEnd,
|
||||
.getI64 = NULL,
|
||||
.putI64 = NULL},
|
||||
};
|
||||
|
||||
struct SCompressor {
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tdef.h"
|
||||
#include "tgeosctx.h"
|
||||
|
||||
static threadlocal SGeosContext tlGeosCtx = {0};
|
||||
|
||||
SGeosContext* getThreadLocalGeosCtx() {
|
||||
return &tlGeosCtx;
|
||||
}
|
||||
|
||||
void destroyThreadLocalGeosCtx() {
|
||||
if (tlGeosCtx.WKTReader) {
|
||||
GEOSWKTReader_destroy_r(tlGeosCtx.handle, tlGeosCtx.WKTReader);
|
||||
tlGeosCtx.WKTReader = NULL;
|
||||
}
|
||||
|
||||
if (tlGeosCtx.WKTWriter) {
|
||||
GEOSWKTWriter_destroy_r(tlGeosCtx.handle, tlGeosCtx.WKTWriter);
|
||||
tlGeosCtx.WKTWriter = NULL;
|
||||
}
|
||||
|
||||
if (tlGeosCtx.WKBReader) {
|
||||
GEOSWKBReader_destroy_r(tlGeosCtx.handle, tlGeosCtx.WKBReader);
|
||||
tlGeosCtx.WKBReader = NULL;
|
||||
}
|
||||
|
||||
if (tlGeosCtx.WKBWriter) {
|
||||
GEOSWKBWriter_destroy_r(tlGeosCtx.handle, tlGeosCtx.WKBWriter);
|
||||
tlGeosCtx.WKBWriter = NULL;
|
||||
}
|
||||
|
||||
if(tlGeosCtx.handle) {
|
||||
GEOS_finish_r(tlGeosCtx.handle);
|
||||
tlGeosCtx.handle = NULL;
|
||||
}
|
||||
}
|
|
@ -194,6 +194,7 @@ _hash_fn_t taosGetDefaultHashFunction(int32_t type) {
|
|||
break;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
fn = MurmurHash3_32;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define _DEFAULT_SOURCE
|
||||
#include "tsched.h"
|
||||
#include "tdef.h"
|
||||
#include "tgeosctx.h"
|
||||
#include "tlog.h"
|
||||
#include "ttimer.h"
|
||||
#include "tutil.h"
|
||||
|
@ -164,6 +165,8 @@ void *taosProcessSchedQueue(void *scheduler) {
|
|||
(*(msg.tfp))(msg.ahandle, msg.thandle);
|
||||
}
|
||||
|
||||
destroyThreadLocalGeosCtx();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -376,6 +376,7 @@ void tSkipListPrint(SSkipList *pSkipList, int16_t nlevel) {
|
|||
fprintf(stdout, "%d: %" PRId64 " \n", id++, *(int64_t *)key);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
fprintf(stdout, "%d: %s \n", id++, key);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#define _DEFAULT_SOURCE
|
||||
#include "tworker.h"
|
||||
#include "tgeosctx.h"
|
||||
#include "taoserror.h"
|
||||
#include "tlog.h"
|
||||
|
||||
|
@ -92,6 +93,8 @@ static void *tQWorkerThreadFp(SQueueWorker *worker) {
|
|||
taosUpdateItemSize(qinfo.queue, 1);
|
||||
}
|
||||
|
||||
destroyThreadLocalGeosCtx();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,29 +78,38 @@ class TDSql:
|
|||
self.cursor.execute(s)
|
||||
time.sleep(2)
|
||||
|
||||
def error(self, sql):
|
||||
def error(self, sql, expectedErrno = None):
|
||||
caller = inspect.getframeinfo(inspect.stack()[1][0])
|
||||
expectErrNotOccured = True
|
||||
|
||||
try:
|
||||
self.cursor.execute(sql)
|
||||
except BaseException as e:
|
||||
expectErrNotOccured = False
|
||||
caller = inspect.getframeinfo(inspect.stack()[1][0])
|
||||
self.errno = e.errno
|
||||
self.error_info = repr(e)
|
||||
# print(error_info)
|
||||
# self.error_info = error_info[error_info.index('(')+1:-1].split(",")[0].replace("'","")
|
||||
# self.error_info = (','.join(error_info.split(",")[:-1]).split("(",1)[1:][0]).replace("'","")
|
||||
# print("!!!!!!!!!!!!!!",self.error_info)
|
||||
|
||||
|
||||
if expectErrNotOccured:
|
||||
caller = inspect.getframeinfo(inspect.stack()[1][0])
|
||||
tdLog.exit("%s(%d) failed: sql:%s, expect error not occured" % (caller.filename, caller.lineno, sql))
|
||||
else:
|
||||
self.queryRows = 0
|
||||
self.queryCols = 0
|
||||
self.queryResult = None
|
||||
tdLog.info("sql:%s, expect error occured" % (sql))
|
||||
|
||||
if expectedErrno != None:
|
||||
if expectedErrno == self.errno:
|
||||
tdLog.info("sql:%s, expected errno %s occured" % (sql, expectedErrno))
|
||||
else:
|
||||
tdLog.exit("%s(%d) failed: sql:%s, errno %s occured, but not expected errno %s" % (caller.filename, caller.lineno, sql, self.errno, expectedErrno))
|
||||
else:
|
||||
tdLog.info("sql:%s, expect error occured" % (sql))
|
||||
|
||||
return self.error_info
|
||||
|
||||
|
||||
|
||||
def query(self, sql, row_tag=None,queryTimes=10):
|
||||
self.sql = sql
|
||||
|
|
|
@ -453,6 +453,9 @@ void generateInsertSQL(BindData *data) {
|
|||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
len += sprintf(data->sql + len, "tubigdata");
|
||||
break;
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
len += sprintf(data->sql + len, "tgeometrydata");
|
||||
break;
|
||||
default:
|
||||
printf("!!!invalid tag type:%d", data->pTags[c].buffer_type);
|
||||
exit(1);
|
||||
|
@ -521,6 +524,9 @@ void generateInsertSQL(BindData *data) {
|
|||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
len += sprintf(data->sql + len, "ubigdata");
|
||||
break;
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
len += sprintf(data->sql + len, "tgeometrydata");
|
||||
break;
|
||||
default:
|
||||
printf("!!!invalid col type:%d", data->pBind[c].buffer_type);
|
||||
exit(1);
|
||||
|
@ -550,7 +556,7 @@ void bpAppendOperatorParam(BindData *data, int32_t *len, int32_t dataType, int32
|
|||
if (gCaseCtrl.optrIdxListNum > 0) {
|
||||
pInfo = &operInfo[gCaseCtrl.optrIdxList[idx]];
|
||||
} else {
|
||||
if (TSDB_DATA_TYPE_VARCHAR == dataType || TSDB_DATA_TYPE_NCHAR == dataType) {
|
||||
if (TSDB_DATA_TYPE_VARCHAR == dataType || TSDB_DATA_TYPE_NCHAR == dataType || TSDB_DATA_TYPE_GEOMETRY == dataType) {
|
||||
pInfo = &operInfo[varoperatorList[rand() % tListLen(varoperatorList)]];
|
||||
} else {
|
||||
pInfo = &operInfo[operatorList[rand() % tListLen(operatorList)]];
|
||||
|
@ -635,6 +641,9 @@ int32_t bpAppendColumnName(BindData *data, int32_t type, int32_t len) {
|
|||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
return sprintf(data->sql + len, "ubigdata");
|
||||
break;
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
len += sprintf(data->sql + len, "tgeometrydata");
|
||||
break;
|
||||
default:
|
||||
printf("!!!invalid col type:%d", type);
|
||||
exit(1);
|
||||
|
@ -868,6 +877,7 @@ int32_t prepareColData(BP_BIND_TYPE bType, BindData *data, int32_t bindIdx, int3
|
|||
pBase[bindIdx].is_null = data->isNull ? (data->isNull + rowIdx) : NULL;
|
||||
break;
|
||||
case TSDB_DATA_TYPE_VARCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
pBase[bindIdx].buffer_length = gVarCharSize;
|
||||
pBase[bindIdx].buffer = data->binaryData + rowIdx * gVarCharSize;
|
||||
pBase[bindIdx].length = data->binaryLen;
|
||||
|
@ -1210,6 +1220,7 @@ int32_t bpAppendValueString(char *buf, int type, void *value, int32_t valueLen,
|
|||
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
buf[*len] = '\'';
|
||||
++(*len);
|
||||
memcpy(buf + *len, value, valueLen);
|
||||
|
@ -1355,7 +1366,7 @@ void bpCheckColTagFields(TAOS_STMT *stmt, int32_t fieldNum, TAOS_FIELD_E* pField
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (pFields[i].type == TSDB_DATA_TYPE_BINARY) {
|
||||
if (pFields[i].type == TSDB_DATA_TYPE_BINARY || pFields[i].type == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
if (pFields[i].bytes != (pBind[i].buffer_length + 2)) {
|
||||
printf("!!!%s %dth field len %d mis-match expect len %d\n", BP_BIND_TYPE_STR(type), i, pFields[i].bytes, (pBind[i].buffer_length + 2));
|
||||
exit(1);
|
||||
|
@ -2499,6 +2510,9 @@ void generateCreateTableSQL(char *buf, int32_t tblIdx, int32_t colNum, int32_t *
|
|||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
blen += sprintf(buf + blen, "ubigdata bigint unsigned");
|
||||
break;
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
blen += sprintf(buf + blen, "geometrydata geometry(%d)", gVarCharSize);
|
||||
break;
|
||||
default:
|
||||
printf("invalid col type:%d", colList[c]);
|
||||
exit(1);
|
||||
|
@ -2557,13 +2571,16 @@ void generateCreateTableSQL(char *buf, int32_t tblIdx, int32_t colNum, int32_t *
|
|||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
blen += sprintf(buf + blen, "tubigdata bigint unsigned");
|
||||
break;
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
blen += sprintf(buf + blen, "tgeometrydata geometry(%d)", gVarCharSize);
|
||||
break;
|
||||
default:
|
||||
printf("invalid col type:%d", colList[c]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blen += sprintf(buf + blen, ")");
|
||||
blen += sprintf(buf + blen, ")");
|
||||
}
|
||||
|
||||
if (3 == tableType) {
|
||||
|
@ -2615,6 +2632,9 @@ void generateCreateTableSQL(char *buf, int32_t tblIdx, int32_t colNum, int32_t *
|
|||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
blen += sprintf(buf + blen, "%d", rand() % 128);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_GEOMETRY:
|
||||
blen += sprintf(buf + blen, "'geo%d'", rand() % 128);
|
||||
break;
|
||||
default:
|
||||
printf("invalid col type:%d", colList[c]);
|
||||
exit(1);
|
||||
|
|
|
@ -200,7 +200,8 @@ static int print_result(char *tbname, TAOS_RES* res, int block) {
|
|||
for (int f = 0; f < num_fields; f++) {
|
||||
if ((fields[f].type != TSDB_DATA_TYPE_VARCHAR)
|
||||
&& (fields[f].type != TSDB_DATA_TYPE_NCHAR)
|
||||
&& (fields[f].type != TSDB_DATA_TYPE_JSON)) {
|
||||
&& (fields[f].type != TSDB_DATA_TYPE_JSON)
|
||||
&& (fields[f].type != TSDB_DATA_TYPE_GEOMETRY)) {
|
||||
printf("col%d type is %d, no need get offset\n",
|
||||
f, fields[f].type);
|
||||
for (int64_t c = 0; c < rows; c++) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue