or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mddatabase-templates.mddml-operations.mdindex.mdquery-construction.mdsql-expressions.mdtype-system.md

sql-expressions.mddocs/

0

# SQL Expressions and Functions

1

2

QueryDSL SQL provides a comprehensive expression builder for SQL functions, operators, database-specific features, and advanced SQL constructs including window functions, aggregate functions, and conditional expressions.

3

4

## Capabilities

5

6

### Core Expression Factory

7

8

Central factory class for creating SQL expressions, functions, and operators.

9

10

```java { .api }

11

/**

12

* Factory class for SQL expressions and functions

13

*/

14

public class SQLExpressions {

15

/**

16

* Creates a constant expression with the specified value

17

* @param value Constant value

18

* @return Expression representing the constant

19

*/

20

public static <T> SimpleExpression<T> constant(T value);

21

22

/**

23

* Creates a case expression builder

24

* @return CaseBuilder for constructing CASE statements

25

*/

26

public static CaseBuilder cases();

27

28

/**

29

* Creates a SQL fragment expression

30

* @param sql Raw SQL fragment

31

* @param args Arguments for the SQL fragment

32

* @return Expression wrapping the SQL fragment

33

*/

34

public static SimpleExpression<Object> template(String sql, Object... args);

35

36

/**

37

* Creates a parameterized SQL template

38

* @param type Return type of the expression

39

* @param template SQL template with placeholders

40

* @param args Template arguments

41

* @return Typed expression from template

42

*/

43

public static <T> SimpleExpression<T> template(Class<? extends T> type, String template, Object... args);

44

}

45

```

46

47

**Usage Examples:**

48

49

```java

50

// Constant expressions

51

Expression<String> statusConstant = SQLExpressions.constant("ACTIVE");

52

Expression<Integer> zeroConstant = SQLExpressions.constant(0);

53

54

// SQL templates for database-specific features

55

Expression<Integer> customFunction = SQLExpressions.template(Integer.class,

56

"my_custom_function({0}, {1})", qUser.id, qUser.name);

57

58

// Case expressions

59

Expression<String> statusLabel = SQLExpressions.cases()

60

.when(qUser.active.isTrue()).then("Active")

61

.when(qUser.suspended.isTrue()).then("Suspended")

62

.otherwise("Inactive");

63

```

64

65

### String Functions

66

67

SQL string manipulation functions with type-safe expression building.

68

69

```java { .api }

70

/**

71

* String concatenation function

72

* @param args String expressions to concatenate

73

* @return String expression for concatenated result

74

*/

75

public static StringExpression concat(Expression<String>... args);

76

77

/**

78

* String length function

79

* @param str String expression

80

* @return Integer expression for string length

81

*/

82

public static NumberExpression<Integer> length(Expression<String> str);

83

84

/**

85

* Substring function

86

* @param str Source string expression

87

* @param start Starting position (1-based)

88

* @param length Length of substring

89

* @return String expression for substring result

90

*/

91

public static StringExpression substring(Expression<String> str, int start, int length);

92

93

/**

94

* String trimming function

95

* @param str String expression to trim

96

* @return String expression with whitespace removed

97

*/

98

public static StringExpression trim(Expression<String> str);

99

100

/**

101

* Converts string to uppercase

102

* @param str String expression

103

* @return Uppercase string expression

104

*/

105

public static StringExpression upper(Expression<String> str);

106

107

/**

108

* Converts string to lowercase

109

* @param str String expression

110

* @return Lowercase string expression

111

*/

112

public static StringExpression lower(Expression<String> str);

113

```

114

115

**Usage Examples:**

116

117

```java

118

// String concatenation

119

StringExpression fullName = SQLExpressions.concat(qUser.firstName,

120

SQLExpressions.constant(" "), qUser.lastName);

121

122

// String manipulation in queries

123

List<Tuple> results = queryFactory

124

.select(qUser.name,

125

SQLExpressions.upper(qUser.name).as("upper_name"),

126

SQLExpressions.length(qUser.email).as("email_length"))

127

.from(qUser)

128

.fetch();

129

130

// Substring operations

131

List<String> areaCodes = queryFactory

132

.select(SQLExpressions.substring(qUser.phone, 1, 3))

133

.from(qUser)

134

.where(qUser.phone.isNotNull())

135

.fetch();

136

```

137

138

### Numeric Functions

139

140

Mathematical functions and numeric operations for calculations.

141

142

```java { .api }

143

/**

144

* Absolute value function

145

* @param number Numeric expression

146

* @return Numeric expression for absolute value

147

*/

148

public static <T extends Number & Comparable<T>> NumberExpression<T> abs(Expression<T> number);

149

150

/**

151

* Ceiling function (round up)

152

* @param number Numeric expression

153

* @return Numeric expression rounded up to nearest integer

154

*/

155

public static NumberExpression<Double> ceil(Expression<? extends Number> number);

156

157

/**

158

* Floor function (round down)

159

* @param number Numeric expression

160

* @return Numeric expression rounded down to nearest integer

161

*/

162

public static NumberExpression<Double> floor(Expression<? extends Number> number);

163

164

/**

165

* Round function

166

* @param number Numeric expression to round

167

* @param precision Number of decimal places

168

* @return Rounded numeric expression

169

*/

170

public static NumberExpression<Double> round(Expression<? extends Number> number, int precision);

171

172

/**

173

* Square root function

174

* @param number Numeric expression

175

* @return Square root expression

176

*/

177

public static NumberExpression<Double> sqrt(Expression<? extends Number> number);

178

179

/**

180

* Power function

181

* @param base Base expression

182

* @param exponent Exponent expression

183

* @return Power expression

184

*/

185

public static NumberExpression<Double> power(Expression<? extends Number> base,

186

Expression<? extends Number> exponent);

187

```

188

189

**Usage Examples:**

190

191

```java

192

// Mathematical calculations

193

List<Tuple> calculations = queryFactory

194

.select(qOrder.amount,

195

SQLExpressions.abs(qOrder.amount.subtract(qOrder.discount)).as("net_amount"),

196

SQLExpressions.round(qOrder.amount.multiply(0.1), 2).as("tax"),

197

SQLExpressions.sqrt(qOrder.quantity).as("sqrt_qty"))

198

.from(qOrder)

199

.fetch();

200

201

// Price calculations with rounding

202

NumberExpression<Double> finalPrice = SQLExpressions.round(

203

qProduct.price.multiply(1.0 - qDiscount.percentage.divide(100.0)), 2);

204

```

205

206

### Date and Time Functions

207

208

Date and time manipulation functions for temporal operations.

209

210

```java { .api }

211

/**

212

* Current timestamp function

213

* @return Expression for current database timestamp

214

*/

215

public static DateTimeExpression<Date> currentTimestamp();

216

217

/**

218

* Current date function

219

* @return Expression for current database date

220

*/

221

public static DateExpression<Date> currentDate();

222

223

/**

224

* Current time function

225

* @return Expression for current database time

226

*/

227

public static TimeExpression<Time> currentTime();

228

229

/**

230

* Date addition function

231

* @param date Date expression

232

* @param interval Interval to add

233

* @param part Date part to add (day, month, year, etc.)

234

* @return Date expression with added interval

235

*/

236

public static DateTimeExpression<Date> dateAdd(Expression<Date> date, int interval, DatePart part);

237

238

/**

239

* Date difference function

240

* @param date1 First date expression

241

* @param date2 Second date expression

242

* @param part Date part for difference calculation

243

* @return Integer expression for date difference

244

*/

245

public static NumberExpression<Integer> dateDiff(DatePart part,

246

Expression<Date> date1,

247

Expression<Date> date2);

248

249

/**

250

* Extract date part function

251

* @param part Date part to extract

252

* @param date Date expression

253

* @return Integer expression for extracted part

254

*/

255

public static NumberExpression<Integer> extract(DatePart part, Expression<Date> date);

256

```

257

258

**Usage Examples:**

259

260

```java

261

// Current timestamp operations

262

List<User> recentUsers = queryFactory

263

.selectFrom(qUser)

264

.where(qUser.createdAt.gt(SQLExpressions.dateAdd(

265

SQLExpressions.currentTimestamp(), -7, DatePart.day)))

266

.fetch();

267

268

// Date calculations

269

List<Tuple> ageCalculations = queryFactory

270

.select(qUser.name,

271

SQLExpressions.dateDiff(DatePart.year, qUser.birthDate,

272

SQLExpressions.currentDate()).as("age"),

273

SQLExpressions.extract(DatePart.month, qUser.birthDate).as("birth_month"))

274

.from(qUser)

275

.fetch();

276

277

// Date formatting and extraction

278

List<Integer> birthYears = queryFactory

279

.select(SQLExpressions.extract(DatePart.year, qUser.birthDate))

280

.from(qUser)

281

.distinct()

282

.orderBy(SQLExpressions.extract(DatePart.year, qUser.birthDate).asc())

283

.fetch();

284

```

285

286

### Aggregate Functions

287

288

SQL aggregate functions for data summarization and statistical operations.

289

290

```java { .api }

291

/**

292

* Count function

293

* @param expr Expression to count (use * for row count)

294

* @return Count expression

295

*/

296

public static NumberExpression<Long> count(Expression<?> expr);

297

298

/**

299

* Count distinct function

300

* @param expr Expression to count distinct values

301

* @return Count distinct expression

302

*/

303

public static NumberExpression<Long> countDistinct(Expression<?> expr);

304

305

/**

306

* Sum function

307

* @param expr Numeric expression to sum

308

* @return Sum expression

309

*/

310

public static <T extends Number> NumberExpression<T> sum(Expression<T> expr);

311

312

/**

313

* Average function

314

* @param expr Numeric expression to average

315

* @return Average expression

316

*/

317

public static NumberExpression<Double> avg(Expression<? extends Number> expr);

318

319

/**

320

* Maximum function

321

* @param expr Expression to find maximum value

322

* @return Maximum expression

323

*/

324

public static <T extends Comparable<T>> ComparableExpression<T> max(Expression<T> expr);

325

326

/**

327

* Minimum function

328

* @param expr Expression to find minimum value

329

* @return Minimum expression

330

*/

331

public static <T extends Comparable<T>> ComparableExpression<T> min(Expression<T> expr);

332

```

333

334

**Usage Examples:**

335

336

```java

337

// Basic aggregations

338

Tuple stats = queryFactory

339

.select(SQLExpressions.count(qOrder.id).as("total_orders"),

340

SQLExpressions.sum(qOrder.amount).as("total_amount"),

341

SQLExpressions.avg(qOrder.amount).as("avg_amount"),

342

SQLExpressions.max(qOrder.amount).as("max_amount"),

343

SQLExpressions.min(qOrder.createdAt).as("first_order"))

344

.from(qOrder)

345

.fetchOne();

346

347

// Group aggregations

348

List<Tuple> customerStats = queryFactory

349

.select(qOrder.customerId,

350

SQLExpressions.count(qOrder.id).as("order_count"),

351

SQLExpressions.sum(qOrder.amount).as("total_spent"),

352

SQLExpressions.countDistinct(qOrderItem.productId).as("unique_products"))

353

.from(qOrder)

354

.join(qOrderItem).on(qOrder.id.eq(qOrderItem.orderId))

355

.groupBy(qOrder.customerId)

356

.fetch();

357

```

358

359

### Window Functions

360

361

Advanced SQL window functions for analytical operations and ranking.

362

363

```java { .api }

364

/**

365

* ROW_NUMBER() window function

366

* @return Window function for row numbering

367

*/

368

public static WindowFunction<Long> rowNumber();

369

370

/**

371

* RANK() window function

372

* @return Window function for ranking with gaps

373

*/

374

public static WindowFunction<Long> rank();

375

376

/**

377

* DENSE_RANK() window function

378

* @return Window function for ranking without gaps

379

*/

380

public static WindowFunction<Long> denseRank();

381

382

/**

383

* LAG() window function - access previous row value

384

* @param expr Expression to get previous value of

385

* @param offset Number of rows back (default 1)

386

* @return Window function for accessing previous row

387

*/

388

public static <T> WindowFunction<T> lag(Expression<T> expr, int offset);

389

390

/**

391

* LEAD() window function - access next row value

392

* @param expr Expression to get next value of

393

* @param offset Number of rows forward (default 1)

394

* @return Window function for accessing next row

395

*/

396

public static <T> WindowFunction<T> lead(Expression<T> expr, int offset);

397

398

/**

399

* FIRST_VALUE() window function

400

* @param expr Expression to get first value of

401

* @return Window function for first value in partition

402

*/

403

public static <T> WindowFunction<T> firstValue(Expression<T> expr);

404

405

/**

406

* LAST_VALUE() window function

407

* @param expr Expression to get last value of

408

* @return Window function for last value in partition

409

*/

410

public static <T> WindowFunction<T> lastValue(Expression<T> expr);

411

```

412

413

**Usage Examples:**

414

415

```java

416

// Row numbering and ranking

417

List<Tuple> rankedProducts = queryFactory

418

.select(qProduct.name, qProduct.price,

419

SQLExpressions.rowNumber().over(qProduct.price.desc()).as("price_rank"),

420

SQLExpressions.rank().over(qProduct.categoryId.asc(), qProduct.price.desc()).as("category_rank"))

421

.from(qProduct)

422

.fetch();

423

424

// Running calculations with window functions

425

List<Tuple> runningTotals = queryFactory

426

.select(qOrder.date, qOrder.amount,

427

SQLExpressions.sum(qOrder.amount).over(qOrder.date.asc()).as("running_total"),

428

SQLExpressions.avg(qOrder.amount).over(qOrder.date.asc()).as("running_avg"))

429

.from(qOrder)

430

.orderBy(qOrder.date.asc())

431

.fetch();

432

433

// Lag/Lead for comparisons

434

List<Tuple> priceChanges = queryFactory

435

.select(qStockPrice.date, qStockPrice.price,

436

SQLExpressions.lag(qStockPrice.price, 1).over(qStockPrice.date.asc()).as("prev_price"),

437

SQLExpressions.lead(qStockPrice.price, 1).over(qStockPrice.date.asc()).as("next_price"))

438

.from(qStockPrice)

439

.where(qStockPrice.symbol.eq("AAPL"))

440

.orderBy(qStockPrice.date.asc())

441

.fetch();

442

```

443

444

### Conditional Expressions

445

446

SQL conditional logic including CASE statements, COALESCE, and NULL handling.

447

448

```java { .api }

449

/**

450

* COALESCE function - returns first non-null value

451

* @param exprs Expressions to evaluate in order

452

* @return Expression with first non-null value

453

*/

454

public static <T> SimpleExpression<T> coalesce(Expression<T>... exprs);

455

456

/**

457

* NULLIF function - returns null if expressions are equal

458

* @param expr1 First expression

459

* @param expr2 Second expression

460

* @return Null if equal, otherwise first expression

461

*/

462

public static <T> SimpleExpression<T> nullif(Expression<T> expr1, Expression<T> expr2);

463

464

/**

465

* Creates a CASE expression builder

466

* @return CaseBuilder for constructing CASE statements

467

*/

468

public static CaseBuilder cases();

469

470

/**

471

* CASE expression builder interface

472

*/

473

public interface CaseBuilder {

474

/**

475

* Adds a WHEN condition

476

* @param condition Boolean condition to test

477

* @return Case when builder for specifying result

478

*/

479

CaseWhen when(Predicate condition);

480

481

/**

482

* Case when builder for specifying THEN result

483

*/

484

interface CaseWhen {

485

/**

486

* Specifies result when condition is true

487

* @param expr Result expression

488

* @return Case builder for additional conditions

489

*/

490

<T> CaseBuilder then(Expression<T> expr);

491

}

492

493

/**

494

* Specifies default result for ELSE clause

495

* @param expr Default expression

496

* @return Final case expression

497

*/

498

<T> SimpleExpression<T> otherwise(Expression<T> expr);

499

}

500

```

501

502

**Usage Examples:**

503

504

```java

505

// CASE expressions for conditional logic

506

Expression<String> orderStatus = SQLExpressions.cases()

507

.when(qOrder.shippedAt.isNotNull()).then("Shipped")

508

.when(qOrder.paidAt.isNotNull()).then("Paid")

509

.when(qOrder.createdAt.isNotNull()).then("Pending")

510

.otherwise("Unknown");

511

512

// COALESCE for null handling

513

Expression<String> displayName = SQLExpressions.coalesce(

514

qUser.nickname, qUser.firstName, qUser.username,

515

SQLExpressions.constant("Anonymous"));

516

517

// Complex conditional aggregations

518

Expression<Long> activeOrderCount = SQLExpressions.cases()

519

.when(qOrder.status.eq("ACTIVE")).then(1L)

520

.otherwise(0L);

521

522

List<Tuple> customerSummary = queryFactory

523

.select(qCustomer.name,

524

SQLExpressions.sum(activeOrderCount).as("active_orders"),

525

SQLExpressions.coalesce(SQLExpressions.max(qOrder.amount),

526

SQLExpressions.constant(0.0)).as("max_order"))

527

.from(qCustomer)

528

.leftJoin(qOrder).on(qCustomer.id.eq(qOrder.customerId))

529

.groupBy(qCustomer.id, qCustomer.name)

530

.fetch();

531

```

532

533

### Database-Specific Functions

534

535

Specialized functions for specific database systems and their unique features.

536

537

```java { .api }

538

/**

539

* PostgreSQL-specific functions

540

*/

541

public class PostgreSQLExpressions {

542

/**

543

* PostgreSQL array contains operator

544

* @param array Array expression

545

* @param element Element to check for

546

* @return Boolean expression for containment check

547

*/

548

public static BooleanExpression arrayContains(Expression<?> array, Expression<?> element);

549

550

/**

551

* PostgreSQL JSONB path query

552

* @param jsonb JSONB column expression

553

* @param path JSON path expression

554

* @return Expression for JSONB path result

555

*/

556

public static SimpleExpression<String> jsonbPath(Expression<String> jsonb, String path);

557

}

558

559

/**

560

* MySQL-specific functions

561

*/

562

public class MySQLExpressions {

563

/**

564

* MySQL MATCH AGAINST full-text search

565

* @param columns Columns to search in

566

* @param searchText Search text

567

* @return Boolean expression for full-text match

568

*/

569

public static BooleanExpression match(Expression<?>[] columns, String searchText);

570

}

571

572

/**

573

* Oracle-specific functions

574

*/

575

public class OracleExpressions {

576

/**

577

* Oracle CONNECT BY hierarchical query

578

* @param condition Connect by condition

579

* @return Hierarchical query expression

580

*/

581

public static BooleanExpression connectBy(Predicate condition);

582

583

/**

584

* Oracle ROWNUM pseudo-column

585

* @return Row number expression

586

*/

587

public static NumberExpression<Long> rownum();

588

}

589

```

590

591

**Usage Examples:**

592

593

```java

594

// PostgreSQL array operations

595

List<User> usersWithTag = queryFactory

596

.selectFrom(qUser)

597

.where(PostgreSQLExpressions.arrayContains(qUser.tags,

598

SQLExpressions.constant("premium")))

599

.fetch();

600

601

// PostgreSQL JSONB queries

602

List<String> emailsFromJson = queryFactory

603

.select(PostgreSQLExpressions.jsonbPath(qUser.metadata, "$.email"))

604

.from(qUser)

605

.where(qUser.metadata.isNotNull())

606

.fetch();

607

608

// MySQL full-text search

609

List<Article> searchResults = queryFactory

610

.selectFrom(qArticle)

611

.where(MySQLExpressions.match(

612

new Expression<?>[]{qArticle.title, qArticle.content},

613

"java spring boot"))

614

.fetch();

615

616

// Oracle hierarchical queries

617

List<Employee> hierarchy = queryFactory

618

.selectFrom(qEmployee)

619

.where(OracleExpressions.connectBy(qEmployee.managerId.eq(qEmployee.id)))

620

.fetch();

621

```

622

623

### Custom Function Registration

624

625

Framework for registering and using custom database functions.

626

627

```java { .api }

628

/**

629

* Represents a custom SQL function call

630

* @param <T> Return type of the function

631

*/

632

public class RelationalFunctionCall<T> extends SimpleExpression<T> {

633

/**

634

* Creates a custom function call

635

* @param type Return type

636

* @param function Function name

637

* @param args Function arguments

638

*/

639

public RelationalFunctionCall(Class<? extends T> type, String function, Expression<?>... args);

640

}

641

```

642

643

**Usage Examples:**

644

645

```java

646

// Custom function registration

647

public class CustomFunctions {

648

public static NumberExpression<Double> calculateDistance(

649

NumberExpression<Double> lat1, NumberExpression<Double> lon1,

650

NumberExpression<Double> lat2, NumberExpression<Double> lon2) {

651

return new RelationalFunctionCall<>(Double.class, "calculate_distance",

652

lat1, lon1, lat2, lon2);

653

}

654

655

public static StringExpression formatCurrency(NumberExpression<? extends Number> amount,

656

StringExpression currencyCode) {

657

return new RelationalFunctionCall<>(String.class, "format_currency",

658

amount, currencyCode);

659

}

660

}

661

662

// Usage of custom functions

663

List<Tuple> storeDistances = queryFactory

664

.select(qStore.name,

665

CustomFunctions.calculateDistance(

666

SQLExpressions.constant(40.7128), // NYC latitude

667

SQLExpressions.constant(-74.0060), // NYC longitude

668

qStore.latitude,

669

qStore.longitude).as("distance"))

670

.from(qStore)

671

.orderBy(CustomFunctions.calculateDistance(

672

SQLExpressions.constant(40.7128),

673

SQLExpressions.constant(-74.0060),

674

qStore.latitude,

675

qStore.longitude).asc())

676

.fetch();

677

```