Table of Contents

Class SQLiteSqlExpressionConvertVisitor

Namespace
LinqToDB.Internal.DataProvider.SQLite
Assembly
linq2db.dll
public class SQLiteSqlExpressionConvertVisitor : SqlExpressionConvertVisitor
Inheritance
object
SQLiteSqlExpressionConvertVisitor
Inherited Members
Extension Methods

Constructors

SQLiteSqlExpressionConvertVisitor(bool)

public SQLiteSqlExpressionConvertVisitor(bool allowModify)

Parameters

allowModify bool

Properties

CanLowerIntervalDifference

Whether an elapsed date difference can be lowered to a value here.

public override bool CanLowerIntervalDifference { get; }

Property Value

bool

Remarks

Declared beside the lowering it describes, and read by the member translator through ITranslationContext.ProviderFlags. The translator has to ask before it builds anything, because a difference it does not build stays an ordinary .NET subtraction and is computed on materialisation - and by the time this visitor runs, the read expression is already bound to its columns, so there is no going back.

CanLowerIntervalShift

Whether LowerTemporalArithmetic(SqlTemporalArithmeticExpression) can express a date shifted by an interval at all.

public override bool CanLowerIntervalShift { get; }

Property Value

bool

Remarks

Read by the member translator so a declared duration added to a date is declined while the expression is still being built, rather than reaching the builder as a node nothing can render - a refusal there has no client-side fallback left. The default follows what the base implementation needs: it spends the amount through ShiftDate(SqlIntervalUnit, ISqlExpression, ISqlExpression) at FinestDateUnit, so a provider that names no finest unit cannot lower one.

Only the declared half is declined early. A shift by a computed difference is left to be built, because start + (end - start) cancels against the difference it came from and asks the provider for nothing - refusing it here would sink a query that works everywhere.

ConcatRequiresExplicitStringCast

When true (default), ConvertConcat(SqlConcatExpression) wraps every non-string operand in an explicit CAST(... AS VARCHAR(N)) before adding it to the concat chain. Required for providers whose concat operator is + (SQL Server pre-2025, SqlCe, Access) — SQL-standard data-type precedence would otherwise try to coerce string operands to the non-string side's type. Most providers whose final concat operator is || (PostgreSQL / Oracle / SQLite / SAP HANA / DuckDB / Firebird / DB2 / Informix / SQL Server 2025+) or CONCAT(...) function (MySQL / ClickHouse) auto-coerce non-string operands and override this to false for cleaner SQL. Sybase ASE is the exception: it emits || but keeps this true, since ASE requires an explicit convert() for non-character operands under both + and ||.

protected override bool ConcatRequiresExplicitStringCast { get; }

Property Value

bool

IntervalResolution

julianday returns a double, and a Julian day number today is around 2460000 - so one unit in the last place is about 47 microseconds. The millisecond is the finest quantum that survives that, whatever the column holds.

public override SqlIntervalUnit IntervalResolution { get; }

Property Value

SqlIntervalUnit

Methods

ConvertConversion(SqlCastExpression)

Implements SqlCastExpression conversion.

protected override ISqlExpression ConvertConversion(SqlCastExpression cast)

Parameters

cast SqlCastExpression

Returns

ISqlExpression

ConvertExprExprPredicate(ExprExpr)

public override IQueryElement ConvertExprExprPredicate(SqlPredicate.ExprExpr predicate)

Parameters

predicate SqlPredicate.ExprExpr

Returns

IQueryElement

ConvertSearchStringPredicate(SearchString)

public override ISqlPredicate ConvertSearchStringPredicate(SqlPredicate.SearchString predicate)

Parameters

predicate SqlPredicate.SearchString

Returns

ISqlPredicate

ConvertSqlBinaryExpression(SqlBinaryExpression)

public override IQueryElement ConvertSqlBinaryExpression(SqlBinaryExpression element)

Parameters

element SqlBinaryExpression

Returns

IQueryElement

ElapsedTicks(SqlIntervalDifferenceExpression)

Elapsed ticks from the Julian day difference, resolved to the millisecond.

protected override ISqlExpression? ElapsedTicks(SqlIntervalDifferenceExpression element)

Parameters

element SqlIntervalDifferenceExpression

Returns

ISqlExpression

Remarks

SQLite has no date type: values are text, and julianday is the only way to do arithmetic on them. It returns a double whose spacing at present-day dates is around fifty microseconds, so the millisecond it is rounded to is the finest unit that comes back exact - and it is also the resolution SQLite date arithmetic already works at, since strftime's %f emits three fractional digits and AddTicks has always lost anything below that.

Rounding rather than truncating for the same reason: the true value is a whole number of milliseconds, and the error is far below half of one, so the nearest is the exact one.

LowerTemporalArithmetic(SqlTemporalArithmeticExpression)

Shifts through julianday arithmetic at millisecond resolution, then back through strftime in the same text format this provider writes a DateTime literal in.

protected override ISqlExpression? LowerTemporalArithmetic(SqlTemporalArithmeticExpression element)

Parameters

element SqlTemporalArithmeticExpression

Returns

ISqlExpression

Remarks

element's interval is either an already-known tick count or a still-unlowered difference/part node - either way it is spent as a number of ticks here, and the recursive Visit this method's result goes through lowers whatever of that remains, exactly as ElapsedTicks(SqlIntervalDifferenceExpression) does for the read direction.

A DateTimeOffset is not shifted. julianday reads it as UTC and strftime writes the result back with no offset, which one SQLite provider reads as local time and the other cannot read at all, so it is left to be refused by name.

VisitInListPredicate(InList)

A date computed from a column is brought to the timestamp text form beside an IN list, as in a comparison: the values keep their own DateTime type there, and SQLite compares the two as text. A value that is itself a date, such as a date column, is brought to the same form.

protected override IQueryElement VisitInListPredicate(SqlPredicate.InList predicate)

Parameters

predicate SqlPredicate.InList

Returns

IQueryElement