or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

adapters.mdcli-interface.mddatabase-api.mdindex.mdsqlalchemy-integration.mdtype-system.md

type-system.mddocs/

0

# Type System

1

2

Comprehensive type system for data conversion, validation, and SQL integration with automatic type inference and custom field definitions. Handles conversion between Python types and SQL types with support for filtering and ordering operations.

3

4

## Capabilities

5

6

### Base Field Class

7

8

Foundation for all field types providing parsing, formatting, and SQL integration capabilities.

9

10

```python { .api }

11

class Field:

12

"""Base field class for data type handling."""

13

14

def parse(self, value):

15

"""

16

Parse value from external format to Python type.

17

18

Parameters:

19

- value: Raw value from data source

20

21

Returns:

22

Parsed Python value

23

"""

24

25

def format(self, value):

26

"""

27

Format Python value for external representation.

28

29

Parameters:

30

- value: Python value to format

31

32

Returns:

33

Formatted value for output

34

"""

35

36

def quote(self, value):

37

"""

38

Quote value for SQL query generation.

39

40

Parameters:

41

- value: Value to quote for SQL

42

43

Returns:

44

str: SQL-quoted value

45

"""

46

47

# Field properties

48

type: str # SQL type name

49

db_api_type: str # DB API 2.0 type constant

50

filters: list # Supported filter classes

51

```

52

53

### Basic Field Types

54

55

Standard field types for common data representations with automatic parsing and validation.

56

57

```python { .api }

58

class Boolean(Field):

59

"""Boolean field type."""

60

type = "BOOLEAN"

61

db_api_type = "NUMBER"

62

63

class StringBoolean(Field):

64

"""Boolean field stored as string (TRUE/FALSE)."""

65

type = "BOOLEAN"

66

db_api_type = "NUMBER"

67

68

class IntBoolean(Field):

69

"""Boolean field stored as integer (1/0)."""

70

type = "BOOLEAN"

71

db_api_type = "NUMBER"

72

73

class Integer(Field):

74

"""Integer field type."""

75

type = "INTEGER"

76

db_api_type = "NUMBER"

77

78

class StringInteger(Field):

79

"""Integer field stored as string (for large integers)."""

80

type = "INTEGER"

81

db_api_type = "NUMBER"

82

83

class Float(Field):

84

"""Floating point field type."""

85

type = "REAL"

86

db_api_type = "NUMBER"

87

88

class String(Field):

89

"""String field type."""

90

type = "TEXT"

91

db_api_type = "STRING"

92

93

class Decimal(Field):

94

"""Decimal field type for precise numeric values."""

95

type = "DECIMAL"

96

db_api_type = "NUMBER"

97

98

class StringDecimal(Field):

99

"""Decimal field stored as string."""

100

type = "DECIMAL"

101

db_api_type = "NUMBER"

102

```

103

104

### Date and Time Fields

105

106

Specialized field types for temporal data with timezone and format support.

107

108

```python { .api }

109

class DateTime(Field):

110

"""DateTime field using datetime.datetime objects."""

111

type = "TIMESTAMP"

112

db_api_type = "DATETIME"

113

114

class ISODateTime(Field):

115

"""DateTime field stored as ISO string."""

116

type = "TIMESTAMP"

117

db_api_type = "DATETIME"

118

119

class Date(Field):

120

"""Date field using datetime.date objects."""

121

type = "DATE"

122

db_api_type = "DATETIME"

123

124

class ISODate(Field):

125

"""Date field stored as ISO string."""

126

type = "DATE"

127

db_api_type = "DATETIME"

128

129

class Time(Field):

130

"""Time field using datetime.time objects."""

131

type = "TIME"

132

db_api_type = "DATETIME"

133

134

class ISOTime(Field):

135

"""Time field stored as ISO string."""

136

type = "TIME"

137

db_api_type = "DATETIME"

138

139

class Duration(Field):

140

"""Duration field using datetime.timedelta objects."""

141

type = "DURATION"

142

db_api_type = "DATETIME"

143

144

class StringDuration(Field):

145

"""Duration field stored as formatted string."""

146

type = "DURATION"

147

db_api_type = "DATETIME"

148

```

149

150

### Binary and Special Fields

151

152

Field types for binary data and special use cases.

153

154

```python { .api }

155

class Blob(Field):

156

"""Binary field using bytes objects."""

157

type = "BLOB"

158

db_api_type = "BINARY"

159

160

class StringBlob(Field):

161

"""Binary field stored as hexadecimal string."""

162

type = "BLOB"

163

db_api_type = "BINARY"

164

165

class RowID(Integer):

166

"""Special field for row identifiers."""

167

type = "INTEGER"

168

db_api_type = "NUMBER"

169

170

class Unknown(Field):

171

"""Field for unknown or dynamic types."""

172

type = "TEXT"

173

db_api_type = "STRING"

174

```

175

176

### Column Ordering

177

178

Enumeration for specifying column ordering capabilities and sort directions.

179

180

```python { .api }

181

class Order:

182

"""Enumeration for column ordering."""

183

184

NONE = "none" # No ordering

185

ASCENDING = "asc" # Ascending order

186

DESCENDING = "desc" # Descending order

187

```

188

189

### Type Analysis

190

191

Utilities for automatic type inference and data analysis from streams of data.

192

193

```python { .api }

194

def analyze(data):

195

"""

196

Analyze data stream to infer types, ordering, and row count.

197

198

Parameters:

199

- data (Iterator[dict]): Stream of row dictionaries

200

201

Returns:

202

tuple: (num_rows, order_info, type_info)

203

- num_rows (int): Total number of rows

204

- order_info (dict): Column ordering information

205

- type_info (dict): Column type mappings

206

"""

207

208

def update_order(current_order, previous, current, num_rows):

209

"""

210

Update ordering information for a column.

211

212

Parameters:

213

- current_order (Order): Current ordering state

214

- previous: Previous value in sequence

215

- current: Current value in sequence

216

- num_rows (int): Number of rows processed

217

218

Returns:

219

Order: Updated ordering state

220

"""

221

```

222

223

### Field Registry

224

225

System for registering and accessing field types dynamically.

226

227

```python { .api }

228

# Available field types

229

FIELD_TYPES = {

230

'boolean': Boolean,

231

'integer': Integer,

232

'float': Float,

233

'string': String,

234

'datetime': DateTime,

235

'date': Date,

236

'time': Time,

237

'duration': Duration

238

}

239

```

240

241

## Usage Examples

242

243

### Custom Field Definition

244

245

```python

246

from shillelagh.fields import Field, String

247

248

class EmailField(Field):

249

"""Custom field for email addresses."""

250

251

def parse(self, value):

252

"""Parse and validate email format."""

253

if value and '@' not in str(value):

254

raise ValueError(f"Invalid email format: {value}")

255

return str(value) if value else None

256

257

def quote(self, value):

258

"""Quote email for SQL."""

259

return f"'{value}'" if value else 'NULL'

260

261

# Use in adapter

262

columns = {

263

'user_email': EmailField(),

264

'user_name': String(),

265

'created_at': DateTime()

266

}

267

```

268

269

### Automatic Type Inference

270

271

```python

272

from shillelagh.lib import analyze

273

274

# Sample data stream

275

data = [

276

{'id': 1, 'name': 'Alice', 'score': 95.5, 'active': True},

277

{'id': 2, 'name': 'Bob', 'score': 87.2, 'active': False},

278

{'id': 3, 'name': 'Charlie', 'score': 92.0, 'active': True}

279

]

280

281

# Analyze data for types and ordering

282

num_rows, order_info, type_info = analyze(iter(data))

283

284

print(f"Rows: {num_rows}")

285

print(f"Types: {type_info}")

286

print(f"Order: {order_info}")

287

288

# Output:

289

# Rows: 3

290

# Types: {'id': Integer, 'name': String, 'score': Float, 'active': Boolean}

291

# Order: {'id': Order.ASCENDING, 'name': Order.NONE, 'score': Order.NONE, 'active': Order.NONE}

292

```

293

294

### Field Configuration in Adapters

295

296

```python

297

from shillelagh.adapters.base import Adapter

298

from shillelagh.fields import Integer, String, DateTime, Boolean

299

300

class CustomAdapter(Adapter):

301

"""Custom adapter with explicit field definitions."""

302

303

def get_columns(self):

304

"""Define column types explicitly."""

305

return {

306

'id': Integer(),

307

'title': String(),

308

'created_at': DateTime(timezone='UTC'),

309

'is_published': Boolean(),

310

'view_count': Integer()

311

}

312

313

def get_data(self, bounds=None, order=None, **kwargs):

314

"""Return typed data matching field definitions."""

315

for row in self._fetch_raw_data():

316

yield {

317

'id': int(row['id']),

318

'title': str(row['title']),

319

'created_at': self._parse_datetime(row['created_at']),

320

'is_published': bool(row['is_published']),

321

'view_count': int(row['view_count'])

322

}

323

```

324

325

### Working with Temporal Data

326

327

```python

328

from shillelagh.fields import DateTime, Date, Time

329

from shillelagh.backends.apsw.db import connect

330

from datetime import datetime, timezone

331

332

# Configure datetime fields with timezone

333

datetime_field = DateTime(timezone='America/New_York')

334

date_field = Date()

335

time_field = Time()

336

337

# Parse various datetime formats

338

dt1 = datetime_field.parse('2023-12-25 15:30:00')

339

dt2 = datetime_field.parse('2023-12-25T15:30:00Z')

340

date1 = date_field.parse('2023-12-25')

341

time1 = time_field.parse('15:30:00')

342

343

# Use in SQL queries with proper quoting

344

connection = connect(":memory:")

345

cursor = connection.cursor()

346

347

cursor.execute(f"""

348

SELECT * FROM events

349

WHERE event_date >= {date_field.quote('2023-01-01')}

350

AND event_time BETWEEN {time_field.quote('09:00:00')}

351

AND {time_field.quote('17:00:00')}

352

""")

353

```

354

355

### Data Validation and Conversion

356

357

```python

358

from shillelagh.fields import Integer, Float, Boolean, String

359

360

# Create field instances

361

int_field = Integer()

362

float_field = Float()

363

bool_field = Boolean()

364

string_field = String()

365

366

# Parse various input formats

367

test_data = [

368

('123', int_field), # String to int

369

('45.67', float_field), # String to float

370

('true', bool_field), # String to bool

371

(123, string_field), # Int to string

372

]

373

374

for value, field in test_data:

375

parsed = field.parse(value)

376

formatted = field.format(parsed)

377

quoted = field.quote(parsed)

378

379

print(f"Input: {value} -> Parsed: {parsed} -> Formatted: {formatted} -> Quoted: {quoted}")

380

381

# Output:

382

# Input: 123 -> Parsed: 123 -> Formatted: 123 -> Quoted: 123

383

# Input: 45.67 -> Parsed: 45.67 -> Formatted: 45.67 -> Quoted: 45.67

384

# Input: true -> Parsed: True -> Formatted: True -> Quoted: 1

385

# Input: 123 -> Parsed: '123' -> Formatted: '123' -> Quoted: '123'

386

```