or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

connection-management.mddata-types.mdexception-handling.mdindex.mdquery-execution.md

data-types.mddocs/

0

# Data Types

1

2

Comprehensive data type support including DB-API 2.0 type constructors, Vertica-specific types, and customizable type conversion system. Handles complex types like arrays, sets, and custom data structures with utilities for type inspection and conversion.

3

4

## Capabilities

5

6

### DB-API 2.0 Type Constructors

7

8

Standard type constructors for creating database-compatible objects.

9

10

```python { .api }

11

def Date(year: int, month: int, day: int):

12

"""

13

Construct a date object.

14

15

Parameters:

16

- year (int): Year value

17

- month (int): Month value (1-12)

18

- day (int): Day value (1-31)

19

20

Returns:

21

datetime.date: Date object

22

"""

23

24

def Time(hour: int, minute: int, second: int):

25

"""

26

Construct a time object.

27

28

Parameters:

29

- hour (int): Hour value (0-23)

30

- minute (int): Minute value (0-59)

31

- second (int): Second value (0-59)

32

33

Returns:

34

datetime.time: Time object

35

"""

36

37

def Timestamp(year: int, month: int, day: int, hour: int, minute: int, second: int):

38

"""

39

Construct a timestamp object.

40

41

Parameters:

42

- year (int): Year value

43

- month (int): Month value (1-12)

44

- day (int): Day value (1-31)

45

- hour (int): Hour value (0-23)

46

- minute (int): Minute value (0-59)

47

- second (int): Second value (0-59)

48

49

Returns:

50

datetime.datetime: Timestamp object

51

"""

52

53

def DateFromTicks(ticks: float):

54

"""

55

Construct a date from Unix timestamp.

56

57

Parameters:

58

- ticks (float): Unix timestamp (seconds since epoch)

59

60

Returns:

61

datetime.date: Date object

62

"""

63

64

def TimeFromTicks(ticks: float):

65

"""

66

Construct a time from Unix timestamp.

67

68

Parameters:

69

- ticks (float): Unix timestamp (seconds since epoch)

70

71

Returns:

72

datetime.time: Time object

73

"""

74

75

def TimestampFromTicks(ticks: float):

76

"""

77

Construct a timestamp from Unix timestamp.

78

79

Parameters:

80

- ticks (float): Unix timestamp (seconds since epoch)

81

82

Returns:

83

datetime.time: Time object (Note: This appears to be a bug in the source code - should return datetime)

84

"""

85

86

def Binary(string):

87

"""

88

Construct a binary object for handling binary data.

89

90

Parameters:

91

- string: Binary string data

92

93

Returns:

94

Bytea: Binary object wrapper

95

"""

96

```

97

98

### DB-API 2.0 Type Objects

99

100

Type objects for column type comparison and identification.

101

102

```python { .api }

103

STRING = VerticaType([VerticaType.CHAR, VerticaType.VARCHAR, VerticaType.BINARY,

104

VerticaType.VARBINARY, VerticaType.UNKNOWN,

105

VerticaType.LONGVARBINARY, VerticaType.LONGVARCHAR])

106

"""Type object for string-based column types."""

107

108

BINARY = VerticaType([VerticaType.BINARY, VerticaType.VARBINARY, VerticaType.LONGVARBINARY])

109

"""Type object for binary column types."""

110

111

NUMBER = VerticaType([VerticaType.INT8, VerticaType.FLOAT8, VerticaType.NUMERIC])

112

"""Type object for numeric column types."""

113

114

DATETIME = VerticaType([VerticaType.DATE, VerticaType.TIME, VerticaType.TIMETZ,

115

VerticaType.TIMESTAMP, VerticaType.TIMESTAMPTZ,

116

VerticaType.INTERVAL, VerticaType.INTERVALYM])

117

"""Type object for date/time column types."""

118

119

ROWID = VerticaType([])

120

"""Type object for row ID types (empty for Vertica)."""

121

```

122

123

### VerticaType Class

124

125

Type constants and comparison functionality for all Vertica data types.

126

127

```python { .api }

128

class VerticaType:

129

"""

130

Type constants and comparison class for Vertica data types.

131

Contains all Vertica type OID constants and comparison methods.

132

"""

133

134

# Basic Types

135

UNKNOWN = 4

136

BOOL = 5

137

INT8 = 6

138

FLOAT8 = 7

139

CHAR = 8

140

VARCHAR = 9

141

DATE = 10

142

TIME = 11

143

TIMESTAMP = 12

144

TIMESTAMPTZ = 13

145

INTERVAL = 14

146

INTERVALYM = 114

147

TIMETZ = 15

148

NUMERIC = 16

149

VARBINARY = 17

150

UUID = 20

151

LONGVARCHAR = 115

152

LONGVARBINARY = 116

153

BINARY = 117

154

155

# Complex Types

156

ROW = 300

157

ARRAY = 301

158

MAP = 302

159

160

# One-dimensional arrays (selected examples)

161

ARRAY1D_BOOL = 1505

162

ARRAY1D_INT8 = 1506

163

ARRAY1D_FLOAT8 = 1507

164

# ... (many more array type constants)

165

166

# One-dimensional sets (selected examples)

167

SET_BOOL = 2705

168

SET_INT8 = 2706

169

# ... (many more set type constants)

170

171

def __init__(self, type_list=None):

172

"""

173

Initialize VerticaType with list of type OIDs.

174

175

Parameters:

176

- type_list (list, optional): List of type OIDs for comparison

177

"""

178

179

def __eq__(self, other) -> bool:

180

"""

181

Compare type objects for equality.

182

183

Parameters:

184

- other: Type OID or VerticaType to compare

185

186

Returns:

187

bool: True if types match, False otherwise

188

"""

189

190

def __ne__(self, other) -> bool:

191

"""

192

Compare type objects for inequality.

193

194

Parameters:

195

- other: Type OID or VerticaType to compare

196

197

Returns:

198

bool: True if types don't match, False otherwise

199

"""

200

```

201

202

### Bytea Class

203

204

Binary string class for handling binary data with proper encoding.

205

206

```python { .api }

207

class Bytea:

208

"""

209

Binary string class for handling binary data.

210

"""

211

212

def __init__(self, data):

213

"""

214

Initialize Bytea object with binary data.

215

216

Parameters:

217

- data: Binary data (bytes, str, or other binary-compatible type)

218

"""

219

220

def __str__(self) -> str:

221

"""

222

Get string representation of binary data.

223

224

Returns:

225

str: String representation

226

"""

227

228

def __repr__(self) -> str:

229

"""

230

Get detailed string representation.

231

232

Returns:

233

str: Detailed representation

234

"""

235

236

def __eq__(self, other) -> bool:

237

"""

238

Compare Bytea objects for equality.

239

240

Parameters:

241

- other: Other Bytea object to compare

242

243

Returns:

244

bool: True if equal, False otherwise

245

"""

246

```

247

248

### Type Inspection Utilities

249

250

Utility functions for inspecting and working with Vertica data types.

251

252

```python { .api }

253

def getTypeName(data_type_oid: int, type_modifier: int = -1) -> str:

254

"""

255

Get human-readable type name from type OID and modifier.

256

257

Parameters:

258

- data_type_oid (int): Vertica type OID

259

- type_modifier (int): Type modifier for precision/scale info (default: -1)

260

261

Returns:

262

str: Human-readable type name (e.g., 'VARCHAR(100)', 'NUMERIC(10,2)')

263

"""

264

265

def getComplexElementType(data_type_oid: int) -> int:

266

"""

267

Get element type OID for complex types (arrays, sets).

268

269

Parameters:

270

- data_type_oid (int): Complex type OID

271

272

Returns:

273

int: Element type OID, or 0 if not a complex type

274

"""

275

276

def getIntervalRange(data_type_oid: int, type_modifier: int) -> str:

277

"""

278

Get interval range string for interval types.

279

280

Parameters:

281

- data_type_oid (int): Interval type OID

282

- type_modifier (int): Type modifier containing range information

283

284

Returns:

285

str: Interval range string (e.g., 'DAY TO SECOND', 'YEAR TO MONTH')

286

"""

287

288

def getIntervalLeadingPrecision(data_type_oid: int, type_modifier: int) -> int:

289

"""

290

Get leading precision of interval types.

291

292

Parameters:

293

- data_type_oid (int): Interval type OID

294

- type_modifier (int): Type modifier containing precision information

295

296

Returns:

297

int: Leading precision value

298

"""

299

300

def getPrecision(data_type_oid: int, type_modifier: int) -> int:

301

"""

302

Get precision of numeric types.

303

304

Parameters:

305

- data_type_oid (int): Numeric type OID

306

- type_modifier (int): Type modifier containing precision information

307

308

Returns:

309

int: Precision value, or -1 if not applicable

310

"""

311

312

def getScale(data_type_oid: int, type_modifier: int) -> int:

313

"""

314

Get scale of numeric types.

315

316

Parameters:

317

- data_type_oid (int): Numeric type OID

318

- type_modifier (int): Type modifier containing scale information

319

320

Returns:

321

int: Scale value, or -1 if not applicable

322

"""

323

324

def getDisplaySize(data_type_oid: int, type_modifier: int) -> int:

325

"""

326

Get display size for a type.

327

328

Parameters:

329

- data_type_oid (int): Type OID

330

- type_modifier (int): Type modifier

331

332

Returns:

333

int: Display size in characters, or -1 if not applicable

334

"""

335

```

336

337

## Usage Examples

338

339

### Basic Type Construction

340

341

```python

342

from vertica_python.datatypes import Date, Time, Timestamp, Binary

343

344

# Create date/time objects

345

birthday = Date(1990, 5, 15)

346

meeting_time = Time(14, 30, 0)

347

event_timestamp = Timestamp(2024, 12, 25, 18, 0, 0)

348

349

# Create from Unix timestamps

350

import time

351

from vertica_python.datatypes import DateFromTicks, TimeFromTicks, TimestampFromTicks

352

now_date = DateFromTicks(time.time())

353

now_time = TimeFromTicks(time.time())

354

now_timestamp = TimestampFromTicks(time.time())

355

356

# Handle binary data

357

image_data = b'\x89PNG\r\n\x1a\n...' # Binary image data

358

binary_obj = Binary(image_data)

359

360

# Use in queries

361

with conn.cursor() as cursor:

362

cursor.execute(

363

"INSERT INTO events (name, date, time, timestamp, image) VALUES (:name, :date, :time, :ts, :img)",

364

{

365

'name': 'Holiday Party',

366

'date': birthday,

367

'time': meeting_time,

368

'ts': event_timestamp,

369

'img': binary_obj

370

}

371

)

372

```

373

374

### Type Comparison and Detection

375

376

```python

377

from vertica_python.datatypes import getTypeName, STRING, NUMBER, DATETIME, BINARY, VerticaType, getPrecision, getScale

378

379

with conn.cursor() as cursor:

380

cursor.execute("SELECT name, age, salary, hire_date FROM employees LIMIT 1")

381

382

# Examine column types

383

for i, col_desc in enumerate(cursor.description):

384

name, type_code, display_size, internal_size, precision, scale, null_ok = col_desc

385

386

print(f"Column {name}:")

387

print(f" Type code: {type_code}")

388

print(f" Type name: {getTypeName(type_code, -1)}")

389

390

# Check type categories

391

if type_code in STRING:

392

print(f" Category: String (max length: {display_size})")

393

elif type_code in NUMBER:

394

print(f" Category: Number (precision: {precision}, scale: {scale})")

395

elif type_code in DATETIME:

396

print(f" Category: Date/Time")

397

elif type_code in BINARY:

398

print(f" Category: Binary")

399

400

# Get detailed type information

401

if type_code == VerticaType.NUMERIC:

402

print(f" Precision: {getPrecision(type_code, precision)}")

403

print(f" Scale: {getScale(type_code, scale)}")

404

```

405

406

### Working with Complex Types

407

408

```python

409

from vertica_python.datatypes import VerticaType, getComplexElementType, getTypeName

410

411

# Arrays

412

with conn.cursor() as cursor:

413

cursor.execute("SELECT tags FROM articles WHERE id = 1")

414

row = cursor.fetchone()

415

tags = row[0] # This might be a list like ['python', 'database', 'vertica']

416

417

# Insert array data

418

cursor.execute(

419

"INSERT INTO articles (title, tags) VALUES (:title, :tags)",

420

{

421

'title': 'Database Guide',

422

'tags': ['sql', 'database', 'tutorial']

423

}

424

)

425

426

# Check if column is a complex type

427

with conn.cursor() as cursor:

428

cursor.execute("SELECT * FROM articles LIMIT 1")

429

for col_desc in cursor.description:

430

name, type_code = col_desc[0], col_desc[1]

431

432

if type_code == VerticaType.ARRAY:

433

element_type = getComplexElementType(type_code)

434

element_name = getTypeName(element_type, -1)

435

print(f"Column {name} is an array of {element_name}")

436

elif getComplexElementType(type_code) is not None:

437

element_type = getComplexElementType(type_code)

438

element_name = getTypeName(element_type, -1)

439

print(f"Column {name} is a set of {element_name}")

440

```

441

442

### Custom Type Conversion

443

444

```python

445

import decimal

446

from datetime import datetime, timezone

447

from vertica_python.datatypes import VerticaType

448

449

# Custom converter for high-precision decimals

450

def high_precision_decimal_converter(value):

451

"""Convert string to high-precision decimal."""

452

if value is None:

453

return None

454

return decimal.Decimal(value)

455

456

# Custom converter for timezone-aware timestamps

457

def timezone_timestamp_converter(value):

458

"""Convert timestamp to timezone-aware datetime."""

459

if value is None:

460

return None

461

# Assume UTC if no timezone info

462

if isinstance(value, datetime) and value.tzinfo is None:

463

return value.replace(tzinfo=timezone.utc)

464

return value

465

466

with conn.cursor() as cursor:

467

# Register custom converters

468

cursor.register_sqldata_converter(

469

VerticaType.NUMERIC,

470

high_precision_decimal_converter

471

)

472

cursor.register_sqldata_converter(

473

VerticaType.TIMESTAMPTZ,

474

timezone_timestamp_converter

475

)

476

477

# Use custom conversion

478

cursor.execute("SELECT price, created_at FROM products WHERE id = 1")

479

price, created_at = cursor.fetchone()

480

481

# price is now a decimal.Decimal with full precision

482

# created_at is now timezone-aware

483

484

print(f"Price: {price} (type: {type(price)})")

485

print(f"Created: {created_at} (timezone: {created_at.tzinfo})")

486

```

487

488

### SQL Literal Adapters

489

490

```python

491

import uuid

492

import json

493

494

# Custom adapter for UUID objects

495

def uuid_adapter(obj):

496

"""Convert UUID to SQL literal."""

497

return f"'{str(obj)}'"

498

499

# Custom adapter for JSON objects

500

def json_adapter(obj):

501

"""Convert dict/list to JSON SQL literal."""

502

return f"'{json.dumps(obj)}'"

503

504

with conn.cursor() as cursor:

505

# Register custom adapters

506

cursor.register_sql_literal_adapter(uuid.UUID, uuid_adapter)

507

cursor.register_sql_literal_adapter(dict, json_adapter)

508

cursor.register_sql_literal_adapter(list, json_adapter)

509

510

# Use custom adapters

511

product_id = uuid.uuid4()

512

metadata = {'category': 'electronics', 'tags': ['phone', 'mobile']}

513

514

cursor.execute(

515

"INSERT INTO products (id, name, metadata) VALUES (:id, :name, :metadata)",

516

{

517

'id': product_id, # Automatically converted to SQL string

518

'name': 'Smartphone',

519

'metadata': metadata # Automatically converted to JSON string

520

}

521

)

522

```

523

524

### Working with Intervals

525

526

```python

527

from datetime import timedelta

528

from vertica_python.datatypes import VerticaType, getIntervalRange, getIntervalLeadingPrecision

529

530

with conn.cursor() as cursor:

531

# Query with interval type

532

cursor.execute("SELECT name, duration FROM events WHERE duration > INTERVAL '1 hour'")

533

534

for row in cursor.fetchall():

535

name, duration = row

536

print(f"Event: {name}")

537

538

# Check column metadata for interval details

539

for col_desc in cursor.description:

540

col_name, type_code, _, _, precision, scale, _ = col_desc

541

if col_name == 'duration' and type_code == VerticaType.INTERVAL:

542

range_str = getIntervalRange(type_code, precision)

543

leading_precision = getIntervalLeadingPrecision(type_code, precision)

544

print(f" Duration: {duration} (range: {range_str}, precision: {leading_precision})")

545

546

# Insert interval data

547

with conn.cursor() as cursor:

548

# Vertica accepts various interval formats

549

cursor.execute(

550

"INSERT INTO events (name, duration) VALUES (:name, :duration)",

551

{

552

'name': 'Meeting',

553

'duration': '2 hours 30 minutes' # String format

554

}

555

)

556

557

# Or using Python timedelta (if converter is set up)

558

duration = timedelta(hours=2, minutes=30)

559

cursor.execute(

560

"INSERT INTO events (name, duration) VALUES (:name, INTERVAL :duration)",

561

{

562

'name': 'Workshop',

563

'duration': f'{duration.total_seconds()} seconds'

564

}

565

)

566

```

567

568

### Type Utility Functions

569

570

```python

571

from vertica_python.datatypes import (

572

getTypeName, NUMBER, STRING, VerticaType, getPrecision, getScale,

573

getDisplaySize, getIntervalRange, getIntervalLeadingPrecision,

574

getComplexElementType

575

)

576

577

def analyze_table_schema(cursor, table_name):

578

"""Analyze and display detailed schema information."""

579

cursor.execute(f"SELECT * FROM {table_name} LIMIT 0") # Get just metadata

580

581

print(f"Schema for table: {table_name}")

582

print("-" * 60)

583

584

for col_desc in cursor.description:

585

name, type_code, display_size, internal_size, precision, scale, null_ok = col_desc

586

587

# Get type name with modifiers

588

type_name = getTypeName(type_code, precision)

589

590

print(f"Column: {name}")

591

print(f" Type: {type_name} (OID: {type_code})")

592

print(f" Nullable: {'Yes' if null_ok else 'No'}")

593

594

# Type-specific information

595

if type_code in NUMBER:

596

if getPrecision(type_code, precision) is not None:

597

prec = getPrecision(type_code, precision)

598

scl = getScale(type_code, scale)

599

print(f" Precision: {prec}, Scale: {scl}")

600

601

elif type_code in STRING:

602

disp_size = getDisplaySize(type_code, display_size)

603

if disp_size is not None:

604

print(f" Max Length: {disp_size}")

605

606

elif type_code == VerticaType.INTERVAL:

607

range_str = getIntervalRange(type_code, precision)

608

leading_prec = getIntervalLeadingPrecision(type_code, precision)

609

print(f" Range: {range_str}")

610

print(f" Leading Precision: {leading_prec}")

611

612

elif type_code == VerticaType.ARRAY or getComplexElementType(type_code) is not None:

613

element_type = getComplexElementType(type_code)

614

if element_type is not None:

615

element_name = getTypeName(element_type, -1)

616

type_desc = "Array" if type_code == VerticaType.ARRAY else "Set"

617

print(f" {type_desc} of: {element_name}")

618

619

print()

620

621

# Usage

622

with conn.cursor() as cursor:

623

analyze_table_schema(cursor, 'employees')

624

```