1 - 将 LONG VARCHAR 和 LONG VARBINARY 数据类型与 ODBC 配合使用
ODBC 驱动程序支持 LONG VARCHAR 和 LONG VARBINARY 数据类型(这两种数据类型分别类似于 VARCHAR 和 VARBINARY 数据类型)。将输入参数或输出参数绑定到查询中的 LONG VARCHAR 或 LONG VARBINARY 列时,请使用 SQL_LONGVARCHAR 和 SQL_LONGVARBINARY 常数设置列的数据类型。例如,若要将输入参数绑定到 LONG VARCHAR 列,应使用如下所示的语句:
rc = SQLBindParameter(hdlStmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR,
80000, 0, (SQLPOINTER)myLongString, sizeof(myLongString), NULL);
注意
请勿针对 LONG VARBINARY 和 LONG VARCHAR 值使用效率低下的编码格式。Vertica不能加载大于 32MB 的编码值,即使解码值的大小小于 32MB。例如,如果您尝试加载以八进制格式编码的 32MB LONG VARBINARY 值,Vertica 将返回错误,因为八进制编码使值的大小翻了两番(每个字节都转换成了反斜杠后跟三位数)。
2 - 将 LONG VARCHAR 和 LONG VARBINARY 数据类型与 JDBC 配合使用
在 JDBC 客户端应用程序中使用 LONG VARCHAR 和 LONG VARBINARY 数据类型与使用 VARCHAR 和 VARBINARY 数据类型相似。JDBC 驱动程序以透明方式处理转换(例如,Java String
对象和 LONG VARCHAR 之间的转换)。
以下示例代码演示了插入和检索 LONG VARCHAR 字符串。此示例使用 JDBC Types 类确定由 Vertica 返回的字符串的数据类型,但它实际上不需要知道数据库列是 LONG VARCHAR 还是 VARCHAR 即可检索值。
import java.sql.*;
import java.util.Properties;
public class LongVarcharExample {
public static void main(String[] args) {
try {
Class.forName("com.vertica.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.err.println("Could not find the JDBC driver class.");
e.printStackTrace();
return;
}
Properties myProp = new Properties();
myProp.put("user", "ExampleUser");
myProp.put("password", "password123");
Connection conn;
try {
conn = DriverManager.getConnection(
"jdbc:vertica://VerticaHost:5433/ExampleDB",
myProp);
// establish connection and make a table for the data.
Statement stmt = conn.createStatement();
// How long we want the example string to be. This is
// larger than can fit into a traditional VARCHAR (which is limited
// to 65000.
int length = 100000;
// Create a table with a LONG VARCHAR column that can store
// the string we want to insert.
stmt.execute("DROP TABLE IF EXISTS longtable CASCADE");
stmt.execute("CREATE TABLE longtable (text LONG VARCHAR(" + length
+ "))");
// Build a long string by appending an integer to a string builder
// until we hit the size limit. Will result in a string
// containing 01234567890123....
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++)
{
sb.append(i % 10);
}
String value = sb.toString();
System.out.println("String value is " + value.length() +
" characters long.");
// Create the prepared statement
PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO longtable (text)" +
" VALUES(?)");
try {
// Insert LONG VARCHAR value
System.out.println("Inserting LONG VARCHAR value");
pstmt.setString(1, value);
pstmt.addBatch();
pstmt.executeBatch();
// Query the table we created to get the value back.
ResultSet rs = null;
rs = stmt.executeQuery("SELECT * FROM longtable");
// Get metadata about the result set.
ResultSetMetaData rsmd = rs.getMetaData();
// Print the type of the first column. Should be
// LONG VARCHAR. Also check it against the Types class, to
// recognize it programmatically.
System.out.println("Column #1 data type is: " +
rsmd.getColumnTypeName(1));
if (rsmd.getColumnType(1) == Types.LONGVARCHAR) {
System.out.println("It is a LONG VARCHAR");
} else {
System.out.println("It is NOT a LONG VARCHAR");
}
// Print out the string length of the returned value.
while (rs.next()) {
// Use the same getString method to get the value that you
// use to get the value of a VARCHAR.
System.out.println("Returned string length: " +
rs.getString(1).length());
}
} catch (SQLException e) {
System.out.println("Error message: " + e.getMessage());
return; // Exit if there was an error
}
// Cleanup
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
注意
请勿针对 LONG VARBINARY 和 LONG VARCHAR 值使用效率低下的编码格式。Vertica不能加载大于 32MB 的编码值,即使解码值的大小小于 32MB。例如,如果您尝试加载以八进制格式编码的 32MB LONG VARBINARY 值,Vertica 将返回错误,因为八进制编码使值的大小翻了两番(每个字节都转换成了反斜杠后跟三位数)。
3 - 将 GEOMETRY 和 GEOGRAPHY 数据类型用于 ODBC
Vertica GEOMETRY 和 GEOGRAPHY 数据类型受 LONG VARBINARY 原生类型支持,ODBC 客户端应用程序将其视为二进制数据。但是,这些数据类型的格式是 Vertica 所特有的。要在 C++ 应用程序中操纵此数据,必须使用 Vertica 中可将其转换为识别的格式的函数。
要将 WKT 或 WKB 转换为 GEOMETRY 或 GEOGRAPHY 格式,请使用以下 SQL 函数之一:
要将 GEOMETRY 或 GEOGRAPHY 对象转换为其对应的 WKT 或 WKB,请使用以下 SQL 函数之一:
以下代码示例使用 ST_GeomFromText
将 WKT 数据转换为 GEOMETRY 数据,然后将其存储在表中。之后,此示例从该表中检索 GEOMETRY 数据,并使用 ST_AsText
和 ST_AsBinary
将它转换为 WKT 和 WKB 格式。
// Compile on Linux using:
// g++ -g -I/opt/vertica/include -L/opt/vertica/lib64 -lodbc -o SpatialData SpatialData.cpp
// Some standard headers
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sstream>
// Only needed for Windows clients
// #include <windows.h>
// Standard ODBC headers
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
// Helper function to print SQL error messages.
template <typename HandleT>
void reportError(int handleTypeEnum, HandleT hdl)
{
// Get the status records.
SQLSMALLINT i, MsgLen;
SQLRETURN ret2;
SQLCHAR SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
SQLINTEGER NativeError;
i = 1;
printf("\n");
while ((ret2 = SQLGetDiagRec(handleTypeEnum, hdl, i, SqlState, &NativeError,
Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA) {
printf("error record %d\n", i);
printf("sqlstate: %s\n", SqlState);
printf("detailed msg: %s\n", Msg);
printf("native error code: %d\n\n", NativeError);
i++;
}
exit(EXIT_FAILURE); // bad form... but Ok for this demo
}
int main()
{
// Set up the ODBC environment
SQLRETURN ret;
SQLHENV hdlEnv;
ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hdlEnv);
assert(SQL_SUCCEEDED(ret));
// Tell ODBC that the application uses ODBC 3.
ret = SQLSetEnvAttr(hdlEnv, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER) SQL_OV_ODBC3, SQL_IS_UINTEGER);
assert(SQL_SUCCEEDED(ret));
// Allocate a database handle.
SQLHDBC hdlDbc;
ret = SQLAllocHandle(SQL_HANDLE_DBC, hdlEnv, &hdlDbc);
assert(SQL_SUCCEEDED(ret));
// Connect to the database
printf("Connecting to database.\n");
const char *dsnName = "ExampleDB";
const char* userID = "dbadmin";
const char* passwd = "password123";
ret = SQLConnect(hdlDbc, (SQLCHAR*)dsnName,
SQL_NTS,(SQLCHAR*)userID,SQL_NTS,
(SQLCHAR*)passwd, SQL_NTS);
if(!SQL_SUCCEEDED(ret)) {
printf("Could not connect to database.\n");
reportError<SQLHDBC>(SQL_HANDLE_DBC, hdlDbc);
} else {
printf("Connected to database.\n");
}
// Disable AUTOCOMMIT
ret = SQLSetConnectAttr(hdlDbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF,
SQL_NTS);
// Set up a statement handle
SQLHSTMT hdlStmt;
SQLAllocHandle(SQL_HANDLE_STMT, hdlDbc, &hdlStmt);
// Drop any previously defined table.
ret = SQLExecDirect(hdlStmt, (SQLCHAR*)"DROP TABLE IF EXISTS polygons",
SQL_NTS);
if (!SQL_SUCCEEDED(ret)) {reportError<SQLHDBC>(SQL_HANDLE_STMT, hdlStmt);}
// Run query to create a table to hold a geometry.
ret = SQLExecDirect(hdlStmt,
(SQLCHAR*)"CREATE TABLE polygons(id INTEGER PRIMARY KEY, poly GEOMETRY);",
SQL_NTS);
if (!SQL_SUCCEEDED(ret)) {reportError<SQLHDBC>(SQL_HANDLE_STMT, hdlStmt);}
// Create the prepared statement. This will insert data into the
// table we created above. It uses the ST_GeomFromText function to convert the
// string-formatted polygon definition to a GEOMETRY datat type.
printf("Creating prepared statement\n");
ret = SQLPrepare (hdlStmt,
(SQLTCHAR*)"INSERT INTO polygons(id, poly) VALUES(?, ST_GeomFromText(?))",
SQL_NTS) ;
if (!SQL_SUCCEEDED(ret)) {reportError<SQLHDBC>(SQL_HANDLE_STMT, hdlStmt);}
SQLINTEGER id = 0;
int numBatches = 5;
int rowsPerBatch = 10;
// Polygon definition as a string.
char polygon[] = "polygon((1 1, 1 2, 2 2, 2 1, 1 1))";
// Bind variables to the parameters in the prepared SQL statement
ret = SQLBindParameter(hdlStmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
0, 0, &id, 0 , NULL);
if (!SQL_SUCCEEDED(ret)) {reportError<SQLHDBC>(SQL_HANDLE_STMT,hdlStmt);}
// Bind polygon string to the geometry column
SQLBindParameter(hdlStmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR,
strlen(polygon), 0, (SQLPOINTER)polygon, strlen(polygon), NULL);
if (!SQL_SUCCEEDED(ret)) {reportError<SQLHDBC>(SQL_HANDLE_STMT,hdlStmt);}
// Execute the insert
ret = SQLExecute(hdlStmt);
if(!SQL_SUCCEEDED(ret)) {
reportError<SQLHDBC>(SQL_HANDLE_STMT, hdlStmt);
} else {
printf("Executed batch.\n");
}
// Commit the transaction
printf("Committing transaction\n");
ret = SQLEndTran(SQL_HANDLE_DBC, hdlDbc, SQL_COMMIT);
if(!SQL_SUCCEEDED(ret)) {
reportError<SQLHDBC>(SQL_HANDLE_STMT, hdlStmt);
} else {
printf("Committed transaction\n");
}
// Now, create a query to retrieve the geometry.
ret = SQLAllocHandle(SQL_HANDLE_STMT, hdlDbc, &hdlStmt);
if (!SQL_SUCCEEDED(ret)) {reportError<SQLHDBC>(SQL_HANDLE_STMT, hdlStmt);}
printf("Getting data from table.\n");
// Execute a query to get the id, raw geometry data, and
// the geometry data as a string. Uses the ST_AsText SQL function to
// format raw data back into a string polygon definition
ret = SQLExecDirect(hdlStmt,
(SQLCHAR*)"select id,ST_AsBinary(poly),ST_AsText(poly) from polygons ORDER BY id;",
SQL_NTS);
if (!SQL_SUCCEEDED(ret)) {reportError<SQLHDBC>(SQL_HANDLE_STMT,hdlStmt);}
SQLINTEGER idval;
// 10MB buffer to hold the raw data from the geometry (10Mb is the maximum
// length of a GEOMETRY)
SQLCHAR* polygonval = (SQLCHAR*)malloc(10485760);
SQLLEN polygonlen, polygonstrlen;
// Buffer to hold a LONGVARCHAR that can result from converting the
// geometry to a string.
SQLTCHAR* polygonstr = (SQLTCHAR*)malloc(33554432);
// Get the results of the query and print each row.
do {
ret = SQLFetch(hdlStmt);
if (SQL_SUCCEEDED(ret)) {
// ID column
ret = SQLGetData(hdlStmt, 1, SQL_C_LONG, &idval, 0, NULL);
if (!SQL_SUCCEEDED(ret)) {reportError<SQLHDBC>(SQL_HANDLE_STMT, hdlStmt);}
printf("id: %d\n",idval);
// The WKB format geometry data
ret = SQLGetData(hdlStmt, 2, SQL_C_BINARY, polygonval, 10485760,
&polygonlen);
if (!SQL_SUCCEEDED(ret)) {reportError<SQLHDBC>(SQL_HANDLE_STMT, hdlStmt);}
printf("Polygon in WKB format: ");
// Print each byte of polygonval buffer in hex format.
for (int z = 0; z < polygonlen; z++)
printf("%02x ",polygonval[z]);
printf("\n");
// Geometry data formatted as a string.
ret = SQLGetData(hdlStmt, 3, SQL_C_TCHAR, polygonstr, 33554432, &polygonstrlen);
if (!SQL_SUCCEEDED(ret)) {reportError<SQLHDBC>(SQL_HANDLE_STMT, hdlStmt);}
printf("Polygon in WKT format: %s\n", polygonstr);
}
} while(SQL_SUCCEEDED(ret));
free(polygonval);
free(polygonstr);
// Clean up
printf("Free handles.\n");
ret = SQLFreeHandle(SQL_HANDLE_STMT, hdlStmt);
if (!SQL_SUCCEEDED(ret)) {reportError<SQLHDBC>(SQL_HANDLE_STMT, hdlStmt);}
ret = SQLFreeHandle(SQL_HANDLE_DBC, hdlDbc);
if (!SQL_SUCCEEDED(ret)) {reportError<SQLHDBC>(SQL_HANDLE_STMT, hdlStmt);}
ret = SQLFreeHandle(SQL_HANDLE_ENV, hdlEnv);
if (!SQL_SUCCEEDED(ret)) {reportError<SQLHDBC>(SQL_HANDLE_STMT, hdlStmt);}
exit(EXIT_SUCCESS);
}
运行上述示例后的输出如下所示:
Connecting to database.
Connected to database.
Creating prepared statement
Executed batch.
Committing transaction
Committed transaction
Getting data from table.
id: 0
Polygon in WKB format: 01 03 00 00 00 01 00 00 00 05 00 00 00 00 00 00 00 00 00 f0 3f 00 00 00 00 00 00 f0 3f 00 00 00 00 00 00 f0 3f 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 f0 3f 00 00 00 00 00 00 f0 3f 00 00 00 00 00 00 f0 3f
Polygon in WKT format: POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1))
Free handles.
注意
请勿针对 LONG VARBINARY 和 LONG VARCHAR 值使用效率低下的编码格式。Vertica 不能加载大于 32 MB 的编码值,即使解码值的大小小于 32MB。例如,如果您尝试加载以八进制格式编码的 32 MB LONG VARBINARY 值,Vertica 将返回错误,因为八进制编码使值的大小翻了两番(每个字节都转换成了反斜杠后跟三位数)。
4 - 将 GEOMETRY 和 GEOGRAPHY 数据类型用于 JDBC
Vertica GEOMETRY 和 GEOGRAPHY 数据类型受 LONG VARBINARY 原生类型支持,JDBC 客户端应用程序将其视为二进制数据。但是,这些数据类型的格式是 Vertica 所特有的。要在 Java 应用程序中操纵此数据,必须使用 Vertica 中可将其转换为识别的格式的函数。
要将 WKT 或 WKB 转换为 GEOMETRY 或 GEOGRAPHY 格式,请使用以下 SQL 函数之一:
要将 GEOMETRY 或 GEOGRAPHY 对象转换为其对应的 WKT 或 WKB,请使用以下 SQL 函数之一:
以下代码示例使用 ST_GeomFromText
和 ST_GeomFromWKB
将 WKT 和 WKB 数据转换为 GEOMETRY 数据,然后将其存储在表中。之后,此示例从该表中检索 GEOMETRY 数据,并使用 ST_AsText
和 ST_AsBinary
将它转换为 WKT 和 WKB 格式。
import java.io.InputStream;
import java.io.Reader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
public class GeospatialDemo
{
public static void main(String [] args) throws Exception
{
Class.forName("com.vertica.jdbc.Driver");
Connection conn =
DriverManager.getConnection("jdbc:vertica://localhost:5433/db",
"user", "password");
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
stmt.execute("CREATE TABLE polygons(id INTEGER PRIMARY KEY, poly GEOMETRY)");
int id = 0;
int numBatches = 5;
int rowsPerBatch = 10;
//batch inserting WKT data
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO polygons
(id, poly) VALUES(?, ST_GeomFromText(?))");
for(int i = 0; i < numBatches; i++)
{
for(int j = 0; j < rowsPerBatch; j++)
{
//Insert your own WKT data here
pstmt.setInt(1, id++);
pstmt.setString(2, "polygon((1 1, 1 2, 2 2, 2 1, 1 1))");
pstmt.addBatch();
}
pstmt.executeBatch();
}
conn.commit();
pstmt.close();
//batch insert WKB data
pstmt = conn.prepareStatement("INSERT INTO polygons(id, poly)
VALUES(?, ST_GeomFromWKB(?))");
for(int i = 0; i < numBatches; i++)
{
for(int j = 0; j < rowsPerBatch; j++)
{
//Insert your own WKB data here
byte [] wkb = getWKB();
pstmt.setInt(1, id++);
pstmt.setBytes(2, wkb);
pstmt.addBatch();
}
pstmt.executeBatch();
}
conn.commit();
pstmt.close();
//selecting data as WKT
ResultSet rs = stmt.executeQuery("select ST_AsText(poly) from polygons");
while(rs.next())
{
String wkt = rs.getString(1);
Reader wktReader = rs.getCharacterStream(1);
//process the wkt as necessary
}
rs.close();
//selecting data as WKB
rs = stmt.executeQuery("select ST_AsBinary(poly) from polygons");
while(rs.next())
{
byte [] wkb = rs.getBytes(1);
InputStream wkbStream = rs.getBinaryStream(1);
//process the wkb as necessary
}
rs.close();
//binding parameters in predicates
pstmt = conn.prepareStatement("SELECT id FROM polygons WHERE
ST_Contains(ST_GeomFromText(?), poly)");
pstmt.setString(1, "polygon((1 1, 1 2, 2 2, 2 1, 1 1))");
rs = pstmt.executeQuery();
while(rs.next())
{
int pk = rs.getInt(1);
//process the results as necessary
}
rs.close();
conn.close();
}
}
5 - 将 GEOMETRY 和 GEOGRAPHY 数据类型用于 ADO.NET
Vertica GEOMETRY 和 GEOGRAPHY 数据类型受 LONG VARBINARY 原生类型支持,ADO.NET 客户端应用程序将其视为二进制数据。但是,这些数据类型的格式是 Vertica 所特有的。要在 C# 应用程序中操纵此数据,必须使用 Vertica 中可将其转换为识别的格式的函数。
要将 WKT 或 WKB 转换为 GEOMETRY 或 GEOGRAPHY 格式,请使用以下 SQL 函数之一:
要将 GEOMETRY 或 GEOGRAPHY 对象转换为其对应的 WKT 或 WKB,请使用以下 SQL 函数之一:
以下 C# 代码示例使用 ST_GeomFromText
将 WKT 数据转换为 GEOMETRY 数据,然后将其存储在表中。之后,此示例从该表中检索 GEOMETRY 数据,并使用 ST_AsText
和 ST_AsBinary
将它转换为 WKT 和 WKB 格式。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Vertica.Data.VerticaClient;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
VerticaConnectionStringBuilder builder =
new VerticaConnectionStringBuilder();
builder.Host = "VerticaHost";
builder.Database = "VMart";
builder.User = "ExampleUser";
builder.Password = "password123";
VerticaConnection _conn = new
VerticaConnection(builder.ToString());
_conn.Open();
VerticaCommand command = _conn.CreateCommand();
command.CommandText = "DROP TABLE IF EXISTS polygons";
command.ExecuteNonQuery();
command.CommandText =
"CREATE TABLE polygons (id INTEGER PRIMARY KEY, poly GEOMETRY)";
command.ExecuteNonQuery();
// Prepare to insert a polygon using a prepared statement. Use the
// ST_GeomFromtText SQl function to convert from WKT to GEOMETRY.
VerticaTransaction txn = _conn.BeginTransaction();
command.CommandText =
"INSERT into polygons VALUES(@id, ST_GeomFromText(@polygon))";
command.Parameters.Add(new
VerticaParameter("id", VerticaType.BigInt));
command.Parameters.Add(new
VerticaParameter("polygon", VerticaType.VarChar));
command.Prepare();
// Set the values for the parameters
command.Parameters["id"].Value = 0;
//
command.Parameters["polygon"].Value =
"polygon((1 1, 1 2, 2 2, 2 1, 1 1))";
// Execute the query to insert the value
command.ExecuteNonQuery();
// Now query the table
VerticaCommand query = _conn.CreateCommand();
query.CommandText =
"SELECT id, ST_AsText(poly), ST_AsBinary(poly) FROM polygons;";
VerticaDataReader dr = query.ExecuteReader();
while (dr.Read())
{
Console.WriteLine("ID: " + dr[0]);
Console.WriteLine("Polygon WKT format data type: "
+ dr.GetDataTypeName(1) +
" Value: " + dr[1]);
// Get the WKB format of the polygon and print it out as hex.
Console.Write("Polygon WKB format data type: "
+ dr.GetDataTypeName(2));
Console.WriteLine(" Value: "
+ BitConverter.ToString((byte[])dr[2]));
}
_conn.Close();
}
}
}
示例代码在系统控制台上输出以下内容:
ID: 0
Polygon WKT format data type: LONG VARCHAR Value: POLYGON ((1 1, 1 2,
2 2, 2 1,1 1))
Polygon WKB format data type: LONG VARBINARY Value: 01-03-00-00-00-01
-00-00-00-05-00-00-00-00-00-00-00-00-00-F0-3F-00-00-00-00-00-00-F0-3F
-00-00-00-00-00-00-F0-3F-00-00-00-00-00-00-00-40-00-00-00-00-00-00-00
-40-00-00-00-00-00-00-00-40-00-00-00-00-00-00-00-40-00-00-00-00-00-00
-F0-3F-00-00-00-00-00-00-F0-3F-00-00-00-00-00-00-F0-3F