or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

command-line-interface.mdconfiguration-options.mdindex.mdresult-handling-display.mdsession-context-management.mdsql-client-application.mdsql-execution-gateway.md

result-handling-display.mddocs/

0

# Result Handling and Display

1

2

Type-safe result containers with support for materialized and streaming results, plus multiple display formats. The result handling system provides comprehensive support for both batch and streaming query results with efficient pagination and real-time change streaming.

3

4

## Capabilities

5

6

### ResultDescriptor Class

7

8

Metadata container for query results providing comprehensive result information and access patterns.

9

10

```java { .api }

11

public class ResultDescriptor {

12

/**

13

* Get unique result identifier for tracking and access

14

* @return String identifier for this result set

15

*/

16

public String getResultId();

17

18

/**

19

* Get table schema information for result structure

20

* @return ResolvedSchema with column names, types, and metadata

21

*/

22

public ResolvedSchema getResultSchema();

23

24

/**

25

* Check if result is materialized in memory for pagination

26

* @return true if result supports random page access

27

*/

28

public boolean isMaterialized();

29

30

/**

31

* Check if result should use tableau display format

32

* @return true for direct tableau output, false for interactive display

33

*/

34

public boolean isTableauMode();

35

36

/**

37

* Check if result comes from streaming query execution

38

* @return true for streaming queries, false for batch queries

39

*/

40

public boolean isStreamingMode();

41

42

/**

43

* Get maximum column width for display formatting

44

* @return Maximum character width for column display

45

*/

46

public int maxColumnWidth();

47

}

48

```

49

50

**Usage Example:**

51

52

```java

53

// Execute query and get result descriptor

54

QueryOperation query = (QueryOperation) executor.parseOperation(sessionId, "SELECT * FROM orders");

55

ResultDescriptor descriptor = executor.executeQuery(sessionId, query);

56

57

// Check result characteristics

58

System.out.println("Result ID: " + descriptor.getResultId());

59

System.out.println("Is materialized: " + descriptor.isMaterialized());

60

System.out.println("Is streaming: " + descriptor.isStreamingMode());

61

System.out.println("Use tableau mode: " + descriptor.isTableauMode());

62

63

// Access schema information

64

ResolvedSchema schema = descriptor.getResultSchema();

65

schema.getColumns().forEach(column ->

66

System.out.println("Column: " + column.getName() + " Type: " + column.getDataType())

67

);

68

```

69

70

### TypedResult Class

71

72

Generic result container with type information providing type-safe access to result data and metadata.

73

74

```java { .api }

75

public class TypedResult<P> {

76

/**

77

* Get result type indicating data availability

78

* @return ResultType enum value

79

*/

80

public ResultType getType();

81

82

/**

83

* Get actual result payload data

84

* @return Payload data of type P, or null for non-PAYLOAD results

85

*/

86

public P getPayload();

87

88

/**

89

* Set result type

90

* @param type ResultType to set

91

*/

92

public void setType(ResultType type);

93

94

/**

95

* Set result payload

96

* @param payload Payload data to set

97

*/

98

public void setPayload(P payload);

99

}

100

```

101

102

### TypedResult Factory Methods

103

104

Static factory methods for creating typed results with appropriate type indicators.

105

106

```java { .api }

107

/**

108

* Create empty result indicating no data available

109

* @return TypedResult with EMPTY type

110

*/

111

public static <T> TypedResult<T> empty();

112

113

/**

114

* Create result with actual data payload

115

* @param payload Data to include in result

116

* @return TypedResult with PAYLOAD type and data

117

*/

118

public static <T> TypedResult<T> payload(T payload);

119

120

/**

121

* Create end-of-stream marker result

122

* @return TypedResult with EOS type indicating stream completion

123

*/

124

public static <T> TypedResult<T> endOfStream();

125

```

126

127

**Usage Example:**

128

129

```java

130

// Handle different result types

131

TypedResult<List<Row>> result = executor.retrieveResultChanges(sessionId, resultId);

132

133

switch (result.getType()) {

134

case PAYLOAD:

135

List<Row> rows = result.getPayload();

136

System.out.println("Received " + rows.size() + " rows");

137

rows.forEach(this::processRow);

138

break;

139

140

case EMPTY:

141

System.out.println("No new data available");

142

// Continue polling or wait

143

break;

144

145

case EOS:

146

System.out.println("Stream has ended");

147

// Cleanup and exit polling loop

148

break;

149

}

150

```

151

152

### ResultType Enumeration

153

154

Enumeration defining the type of result data availability.

155

156

```java { .api }

157

public enum ResultType {

158

/** Result contains actual data payload */

159

PAYLOAD,

160

161

/** Result is empty - no data currently available */

162

EMPTY,

163

164

/** End of stream - no more data will be available */

165

EOS

166

}

167

```

168

169

## Result Interface Hierarchy

170

171

### DynamicResult Interface

172

173

Base interface for dynamic result handling providing common result operations.

174

175

```java { .api }

176

public interface DynamicResult extends AutoCloseable {

177

/**

178

* Check if result is materialized in memory

179

* @return true if result supports random access, false for streaming-only

180

*/

181

boolean isMaterialized();

182

183

/**

184

* Close result and release associated resources

185

* @throws IOException if cleanup fails

186

*/

187

void close() throws IOException;

188

}

189

```

190

191

### MaterializedResult Interface

192

193

Interface for materialized results supporting pagination and random access.

194

195

```java { .api }

196

public interface MaterializedResult extends DynamicResult {

197

/**

198

* Create materialized snapshot with specified page size

199

* @param pageSize Number of rows per page

200

* @return TypedResult containing total page count

201

*/

202

TypedResult<Integer> snapshot(int pageSize);

203

204

/**

205

* Retrieve specific page of results

206

* @param page Page number (0-based indexing)

207

* @return List of rows for the requested page

208

*/

209

List<Row> retrievePage(int page);

210

}

211

```

212

213

**Usage Example:**

214

215

```java

216

// Handle materialized results with pagination

217

if (result instanceof MaterializedResult) {

218

MaterializedResult materializedResult = (MaterializedResult) result;

219

220

// Create snapshot with 100 rows per page

221

TypedResult<Integer> pageCountResult = materializedResult.snapshot(100);

222

if (pageCountResult.getType() == ResultType.PAYLOAD) {

223

int totalPages = pageCountResult.getPayload();

224

System.out.println("Total pages: " + totalPages);

225

226

// Retrieve each page

227

for (int page = 0; page < totalPages; page++) {

228

List<Row> pageRows = materializedResult.retrievePage(page);

229

System.out.println("Page " + page + ": " + pageRows.size() + " rows");

230

pageRows.forEach(this::processRow);

231

}

232

}

233

}

234

```

235

236

### ChangelogResult Interface

237

238

Interface for streaming results providing incremental change access.

239

240

```java { .api }

241

public interface ChangelogResult extends DynamicResult {

242

/**

243

* Retrieve incremental changes from streaming result

244

* @return TypedResult containing list of changed rows or status

245

*/

246

TypedResult<List<Row>> retrieveChanges();

247

}

248

```

249

250

**Usage Example:**

251

252

```java

253

// Handle streaming results with changelog

254

if (result instanceof ChangelogResult) {

255

ChangelogResult changelogResult = (ChangelogResult) result;

256

257

// Poll for changes

258

while (true) {

259

TypedResult<List<Row>> changes = changelogResult.retrieveChanges();

260

261

switch (changes.getType()) {

262

case PAYLOAD:

263

List<Row> changedRows = changes.getPayload();

264

changedRows.forEach(row -> {

265

// Process row changes - each row includes change type (+I, -D, -U, +U)

266

RowKind kind = row.getKind();

267

System.out.println("Change type: " + kind + ", Data: " + row);

268

});

269

break;

270

271

case EMPTY:

272

Thread.sleep(100); // Wait before next poll

273

break;

274

275

case EOS:

276

System.out.println("Stream completed");

277

return; // Exit polling loop

278

}

279

}

280

}

281

```

282

283

## Result Display Components

284

285

### CliTableauResultView Class

286

287

Tableau-style result display providing direct formatted output without interactive features.

288

289

```java { .api }

290

public class CliTableauResultView implements AutoCloseable {

291

/**

292

* Create tableau result view

293

* @param terminal Terminal for output

294

* @param executor Executor for result access

295

* @param sessionId Session identifier

296

* @param resultDesc Result descriptor for metadata

297

*/

298

public CliTableauResultView(Terminal terminal, Executor executor, String sessionId, ResultDescriptor resultDesc);

299

300

/**

301

* Display results in tableau format

302

* Outputs formatted table directly to terminal

303

*/

304

public void displayResults();

305

306

/**

307

* Close view and cleanup resources

308

*/

309

public void close();

310

}

311

```

312

313

**Usage Example:**

314

315

```java

316

// Display results in tableau format

317

try (CliTableauResultView tableauView = new CliTableauResultView(

318

terminal, executor, sessionId, resultDescriptor)) {

319

tableauView.displayResults();

320

}

321

```

322

323

### CliView Abstract Class

324

325

Base class for CLI view components providing common view functionality.

326

327

```java { .api }

328

public abstract class CliView<OP, OUT> {

329

/**

330

* Get associated CLI client

331

* @return CliClient instance

332

*/

333

protected CliClient getClient();

334

335

/**

336

* Get terminal for output operations

337

* @return Terminal instance

338

*/

339

protected Terminal getTerminal();

340

341

/**

342

* Check if terminal is plain (limited features)

343

* @return true if terminal has limited capabilities

344

*/

345

protected boolean isPlainTerminal();

346

}

347

```

348

349

### CliResultView Abstract Class

350

351

Base class for result display views providing common result handling.

352

353

```java { .api }

354

public abstract class CliResultView<OP> extends CliView<OP, Void> {

355

/**

356

* Open result view for interaction

357

*/

358

public abstract void open();

359

360

/**

361

* Get result descriptor

362

* @return ResultDescriptor for this view

363

*/

364

protected ResultDescriptor getResultDescriptor();

365

}

366

```

367

368

## Row Processing and Data Types

369

370

### Row Access Patterns

371

372

Working with Row objects in results:

373

374

```java

375

// Process row data

376

void processRow(Row row) {

377

// Get row kind for change tracking

378

RowKind kind = row.getKind();

379

380

// Access fields by position

381

Object field0 = row.getField(0);

382

Object field1 = row.getField(1);

383

384

// Access fields with type safety

385

String name = row.getFieldAs(0, String.class);

386

Integer age = row.getFieldAs(1, Integer.class);

387

388

// Iterate over all fields

389

for (int i = 0; i < row.getArity(); i++) {

390

Object field = row.getField(i);

391

System.out.println("Field " + i + ": " + field);

392

}

393

}

394

```

395

396

### Schema Integration

397

398

Using ResolvedSchema for type-safe result processing:

399

400

```java

401

void processResultWithSchema(ResultDescriptor descriptor, List<Row> rows) {

402

ResolvedSchema schema = descriptor.getResultSchema();

403

List<Column> columns = schema.getColumns();

404

405

for (Row row : rows) {

406

for (int i = 0; i < columns.size(); i++) {

407

Column column = columns.get(i);

408

Object value = row.getField(i);

409

410

System.out.printf("Column %s (%s): %s%n",

411

column.getName(),

412

column.getDataType(),

413

value);

414

}

415

}

416

}

417

```

418

419

## Error Handling

420

421

Result handling includes comprehensive error management:

422

423

```java

424

try {

425

TypedResult<List<Row>> result = executor.retrieveResultChanges(sessionId, resultId);

426

// Process result

427

} catch (SqlExecutionException e) {

428

if (e.getMessage().contains("Result expired")) {

429

System.err.println("Result has expired - restart query");

430

} else if (e.getMessage().contains("Result not found")) {

431

System.err.println("Invalid result ID");

432

} else {

433

System.err.println("Execution error: " + e.getMessage());

434

}

435

}

436

437

// Handle pagination errors

438

try {

439

List<Row> page = materializedResult.retrievePage(pageNumber);

440

} catch (IndexOutOfBoundsException e) {

441

System.err.println("Invalid page number: " + pageNumber);

442

} catch (IllegalStateException e) {

443

System.err.println("Result snapshot has expired");

444

}

445

```

446

447

## Performance Considerations

448

449

### Efficient Result Processing

450

451

```java

452

// Batch process rows for better performance

453

List<Row> batch = new ArrayList<>();

454

TypedResult<List<Row>> result = executor.retrieveResultChanges(sessionId, resultId);

455

456

if (result.getType() == ResultType.PAYLOAD) {

457

batch.addAll(result.getPayload());

458

459

// Process in batches of 1000 rows

460

if (batch.size() >= 1000) {

461

processBatch(batch);

462

batch.clear();

463

}

464

}

465

```

466

467

### Memory Management

468

469

```java

470

// Use try-with-resources for automatic cleanup

471

try (CliTableauResultView view = new CliTableauResultView(terminal, executor, sessionId, descriptor)) {

472

view.displayResults();

473

} // Automatic resource cleanup

474

475

// Cancel long-running queries when needed

476

if (shouldCancel) {

477

executor.cancelQuery(sessionId, resultId);

478

}

479

```

480

481

The result handling and display system provides a comprehensive framework for managing both batch and streaming query results with efficient memory usage, type safety, and flexible display options.