Skip to main content

ArpeNetezza — Data types

How Netezza types map to Apache Arrow on the read path, and how Arrow types map back to Netezza on the ingest and bind paths.

The non-obvious cases are called out below:

  • TIMESTAMP is a zoneless microsecond timestamp.
  • TIME WITH TIME ZONE and INTERVAL come back as text by default.
  • CHAR / VARCHAR are transcoded from LATIN9.
  • Fixed-length BINARY cannot be read yet.

Read path: Netezza → Arrow​

Netezza returns ordinary query results as a DBOS binary tuple stream, which the driver decodes straight into Arrow buffers. The table below describes that path. A few server-evaluated queries with no table (for example SELECT CURRENT_SCHEMA or SELECT version()) come back as text instead; see Text results.

Numeric​

Netezza typeArrow typeNotes
BYTEINTint8
SMALLINTint16
INTEGERint32
BIGINTint64
NUMERIC(p,s) / DECIMAL(p,s)decimal128(p,s)Exact, decoded from the binary value with no string detour. Netezza's maximum precision is 38, so decimal256 is never needed.
NUMERIC with no precisiondecimal128(18,0)Netezza's default precision and scale.
REALfloat32
DOUBLE PRECISIONfloat64
MONEYdecimal128(19,2)

Character, JSON & binary​

Netezza typeArrow typeNotes
CHAR(n) / VARCHAR(n)utf8Netezza stores these in LATIN9; the driver transcodes to UTF-8. CHAR values keep their blank padding. Set char_encoding=utf8 if your site stores UTF-8 bytes in VARCHAR.
NCHAR(n) / NVARCHAR(n)utf8Already UTF-8; passed through.
JSON / JSONButf8With json_extension=on, tagged with the arrow.json extension type.
JSONPATHutf8Never tagged.
VARBINARY(n)binary
ST_GEOMETRY(n)binaryThe raw stored bytes, with no GeoArrow annotation.
VECTORbinaryThe raw stored bytes.
BINARY(n) (fixed length)—Not supported: the query fails with "NzType … not yet supported". Cast to VARBINARY in the query.

Each session runs SET DATATYPE_BACKWARD_COMPATIBILITY ON after login, so JSON columns can be returned to the driver.

Temporal​

Netezza typeArrow typeNotes
DATEdate32
TIMEtime64[us]
TIME WITH TIME ZONEutf8Rendered by the driver, e.g. 12:34:56+02 or 12:34:56+05:30.
TIMESTAMPtimestamp[us] (no time zone)Netezza timestamps carry no zone.
INTERVALutf8 (default) / interval(month_day_nano)See interval_type.

Read options​

interval_type​

adbc.arpenz.interval_type (since v0.2.8) chooses the Arrow type of INTERVAL columns:

ValueArrow typeExample
text (default; alias string)utf81 day 02:00
native (alias month_day_nano)interval(month_day_nano)months, then the rest in nanoseconds (the days field is always 0)

interval(month_day_nano) has no Parquet representation, which is why text is the default. native applies to binary (DBOS) results only: a text result with an interval column fails to decode under native.

char_encoding​

adbc.arpenz.char_encoding (since v0.3.1): latin9 (default) transcodes CHAR / VARCHAR bytes from LATIN9 to UTF-8; utf8 passes them through unchanged. NCHAR / NVARCHAR are never transcoded.

json_extension​

adbc.arpenz.json_extension (since v0.2.8): on tags JSON and JSONB columns with the canonical arrow.json extension type (storage stays utf8). Default off.

There is no option to change the NUMERIC mapping: it is always decimal128(p,s).

Text results​

Server-evaluated queries with no table come back as text rows. The types follow the same table, with these differences:

  • INTERVAL, TIME WITH TIME ZONE and VARBINARY hold the server's own text rendering.
  • JSON is never tagged arrow.json.
  • interval_type=native fails on an interval column (see above).

Schemas without a query​

  • AdbcStatementExecuteSchema returns exactly the schema the query would return, using the same mapping and read options.
  • AdbcConnectionGetTableSchema builds the schema from information_schema.columns and is less exact:
    • It ignores interval_type and json_extension: INTERVAL is always utf8, and JSON is never tagged.
    • A NUMERIC with no precision is utf8.
    • A type it does not recognise is reported as utf8.

When the exact Arrow schema matters, use ExecuteSchema on SELECT * FROM <table>.


Write path: Arrow → Netezza (ingest)​

adbc_ingest (bulk ingest) is supported in the four ADBC modes: create, append, replace and create_append. adbc.ingest.mode must be set explicitly. Data is taken from a stream: Python's adbc_ingest and R's write_adbc do that for you. In the other APIs, bind the data with BindStream (an ArrowArrayStream / record-batch reader). Bind of a single batch to an ingest statement fails with "no data was bound".

Table and column names are quoted as given, so my_table is created as the case-sensitive "my_table".

How rows are loaded​

With autocommit on, an ingest is one transaction: it succeeds or fails as a whole. With ingest_method=auto (the default):

  1. External-table load (since v0.3.0). The driver sends one INSERT INTO t (…) SELECT … FROM EXTERNAL … USING (REMOTESOURCE …) statement, then streams the rows as delimited text. The server parses them in parallel. It needs only INSERT on the target. Any rejected row fails the whole load, and the error includes the server's first bad-record diagnostic.
  2. Batched INSERT fallback. When the load cannot express the ingest, the driver uses INSERT … SELECT … UNION ALL statements of up to 1000 rows instead. This is much slower: Netezza plans each UNION ALL branch. The fallback happens before any data is sent when:
    • an Arrow column has no target column of exactly the same name;
    • an Arrow/target type pair is not in the table below;
    • a target NUMERIC has no precision, or a target VARBINARY is longer than 32000;
    • the row is wider than Netezza's 64 KiB external-record limit (for example, a JSONB column);
    • a temporary table shadows a permanent table of the same name.

With ingest_method=external those cases are an error instead; with ingest_method=insert the external load is never tried.

Arrow typeExternal load into
integersinteger, floating-point and NUMERIC columns; character columns
float32 / float64floating-point columns; character columns
decimal128NUMERIC and floating-point columns; character columns
boolBOOLEAN
utf8 / binarycharacter columns; VARBINARY (sent as hex)
date32DATE
timestampTIMESTAMP
time32 / time64TIME
interval(month_day_nano)INTERVAL

Accepted Arrow types​

AcceptedRejected before any DDL (NOT_IMPLEMENTED)
bool, int8/int16/int32/int64, float32/float64, utf8, large_utf8, binary, large_binary, decimal128(p,s) (p 1–38, s 0–p), date32, timestamp (any unit, with or without zone), time32/time64, interval(month_day_nano), dictionary-encoded columns (ingested as their values)unsigned integers, fixed_size_binary, string_view / binary_view, decimal32 / decimal64 / decimal256, negative scale, interval(months), interval(day_time)

Strings are sent as UTF-8; the server converts them for CHAR / VARCHAR targets. A NUL byte inside a string is an error. Time zones on timestamps are ignored, so the UTC value is stored, and nanoseconds are truncated to microseconds.

Tables created by create / replace / create_append​

ArrowNetezza column
boolBOOLEAN
int8SMALLINT
int16 / int32 / int64SMALLINT / INTEGER / BIGINT
float32 / float64REAL / DOUBLE PRECISION
utf8 / large_utf8NVARCHAR(n), n ≤ 16000
binary / large_binaryVARBINARY(n), n ≤ 64000
decimal128(p,s)NUMERIC(p,s)
date32DATE
time32 / time64TIME
timestampTIMESTAMP
interval(month_day_nano)not supported in create: ingest intervals in append mode into an existing INTERVAL column
  • An int8 column becomes SMALLINT, not BYTEINT, so it reads back as int16.
  • Non-nullable Arrow fields become NOT NULL columns.
  • String and binary widths. Netezza counts NVARCHAR(n) as 4n bytes of its 64 KiB row. The driver shares the row budget evenly across the string and binary columns, so a single string column gets NVARCHAR(16000) and many string columns get narrower ones. When the data needs a specific width, create the table yourself and ingest with append.
  • Temporary tables. adbc.ingest.temporary=true creates a CREATE TEMP TABLE and needs a username and password on the connection. adbc.ingest.target_db_schema is ignored for a temporary table.

Bound parameters​

Netezza has no server-side prepared statements, so Prepare does nothing on the server and bound values are rendered into the SQL text by the driver as escaped literals. Use ? placeholders ($1, $2, … are also recognised); placeholders inside string literals, quoted identifiers and comments are ignored. A batch of N parameter rows runs the statement N times. For a query, the N results are concatenated into one stream; for DML, the row counts are summed.

Arrow typeRendered as
nullNULL
booltrue / false
int8, uint8, int16, uint16, int32, int64integer literal
float32 / float64numeric literal; NaN and ±Infinity as casts
decimal128(p,s) (p ≤ 38, s ≥ 0)numeric literal
utf8, large_utf8, string_view, string dictionariesquoted string (' doubled)
binary, large_binary, binary_view, fixed_size_binary(n ≤ 255)CAST(X'…' AS VARBINARY(n))
date32quoted date
timestampquoted YYYY-MM-DD HH:MM:SS.ffffff (a zoned timestamp is rendered in UTC, with a +00 suffix)
time32 / time64quoted HH:MM:SS.ffffff

uint32, uint64, date64 and intervals cannot be bound (NOT_IMPLEMENTED). GetParameterSchema reports the number of placeholders, typed as int32 unless parameters were already bound.


See also​