Class SqlServerSqlExpressionConvertVisitor
- Namespace
- LinqToDB.Internal.DataProvider.SqlServer
- Assembly
- linq2db.dll
public class SqlServerSqlExpressionConvertVisitor : SqlExpressionConvertVisitor
- Inheritance
-
objectSqlServerSqlExpressionConvertVisitor
- Derived
- Inherited Members
- Extension Methods
Constructors
SqlServerSqlExpressionConvertVisitor(bool, SqlServerVersion)
public SqlServerSqlExpressionConvertVisitor(bool allowModify, SqlServerVersion sqlServerVersion)
Parameters
allowModifyboolsqlServerVersionSqlServerVersion
Properties
CanLowerIntervalDifference
Every version counts elapsed time: 2016 and later through DATEDIFF_BIG, earlier ones through the
32-bit DATEDIFF over windows kept short enough for it.
public override bool CanLowerIntervalDifference { get; }
Property Value
FinestDateUnit
DATEDIFF_BIG counts nanoseconds, and datetime2 stores 100ns, so the leftover of a total
is exact. It is only ever applied to a sub-unit window, well inside the roughly 292 years at which the
nanosecond form would overflow.
protected override SqlIntervalUnit? FinestDateUnit { get; }
Property Value
Remarks
The nanosecond datepart arrived with datetime2 in 2008 - DATEADD on 2005 answers is not
a recognized dateadd option - so that version counts in milliseconds instead, which is as fine as its
own datetime resolves anyway. Version-checked here rather than overridden on the 2005 visitor,
because the 2008 one derives from it and would inherit the wrong answer.
IntervalResolution
On 2005 the measurement stops at the millisecond, so a component asked for below one is identically zero rather than merely imprecise - declined for the reason SQL CE and Sybase decline it.
public override SqlIntervalUnit IntervalResolution { get; }
Property Value
SupportsDistinctAsExistsIntersect
protected override bool SupportsDistinctAsExistsIntersect { get; }
Property Value
Methods
ConvertConcat(SqlConcatExpression)
public override ISqlExpression ConvertConcat(SqlConcatExpression element)
Parameters
elementSqlConcatExpression
Returns
ConvertConversion(SqlCastExpression)
Implements SqlCastExpression conversion.
protected override ISqlExpression ConvertConversion(SqlCastExpression cast)
Parameters
castSqlCastExpression
Returns
ConvertDefaultValue(SqlDefaultValueExpression)
Writes the default a reader substitutes for a NULL: as its value here, and as the least value of the column's type where a provider's type cannot hold it.
public override ISqlExpression ConvertDefaultValue(SqlDefaultValueExpression expression)
Parameters
expressionSqlDefaultValueExpressionThe default to write.
Returns
- ISqlExpression
The expression the default is written as.
ConvertSearchStringPredicate(SearchString)
public override ISqlPredicate ConvertSearchStringPredicate(SqlPredicate.SearchString predicate)
Parameters
predicateSqlPredicate.SearchString
Returns
ConvertSqlBinaryExpression(SqlBinaryExpression)
public override IQueryElement ConvertSqlBinaryExpression(SqlBinaryExpression element)
Parameters
elementSqlBinaryExpression
Returns
ConvertSqlFunction(SqlFunction)
public override ISqlExpression ConvertSqlFunction(SqlFunction func)
Parameters
funcSqlFunction
Returns
CountDateBoundaries(SqlIntervalUnit, ISqlExpression, ISqlExpression)
Counts unit boundaries crossed between two date/time values - the provider's DATEDIFF.
protected override ISqlExpression? CountDateBoundaries(SqlIntervalUnit unit, ISqlExpression start, ISqlExpression end)
Parameters
unitSqlIntervalUnitstartISqlExpressionendISqlExpression
Returns
Remarks
Boundary counting, not elapsed time. It is deliberately the wrong answer on its own: it is the cheap starting estimate that the anchor correction turns into the elapsed count, and being a count of whole units it cannot overflow the way a fine-grained difference over the same range would.
ElapsedTicks(SqlIntervalDifferenceExpression)
Before 2016 the base decomposition cannot be used as it is once the finest unit is the nanosecond: it
counts the remainder after whole days in that unit, and a day is 8.64e13 nanoseconds against the
roughly 2.1e9 a 32-bit DATEDIFF holds. The remainder is split once more instead - whole seconds
within it, then the nanoseconds within the last second, at most 1e9 - so every count stays in range and
the result stays exact at the 100ns datetime2 stores.
protected override ISqlExpression? ElapsedTicks(SqlIntervalDifferenceExpression element)
Parameters
elementSqlIntervalDifferenceExpression
Returns
Remarks
Each count is the raw boundary count, measured from exactly where the previous shift landed, so an
overshoot at one step returns as a negative remainder at the next and the parts telescope, as in the base.
That needs the second shift to be exact, which two storage types do not give: DATEADD refuses a
second on a date, and rounds a smalldatetime to the minute. So the anchor is widened to
datetime2 first, which holds either of them exactly - whatever the mapping declares, since that is
not what the column stores: a date column mapped as a plain DateTime is typed
datetime2 here.
IsWindowOrderByRequired(SqlExtendedFunction)
Every ranking function and every one that reads a neighbouring row - The function 'ROW_NUMBER' must
have an OVER clause with ORDER BY - and any frame at all, which is Incorrect syntax near 'ROWS'
without one. An unframed aggregate is exempt: SUM(x) OVER () is valid.
protected override bool IsWindowOrderByRequired(SqlExtendedFunction func)
Parameters
funcSqlExtendedFunction
Returns
LowerTemporalArithmetic(SqlTemporalArithmeticExpression)
Shifts as the base does - days, then seconds, then the rest in the finest unit - over the value widened to
datetime2 first, or to datetime on 2005.
protected override ISqlExpression? LowerTemporalArithmetic(SqlTemporalArithmeticExpression element)
Parameters
elementSqlTemporalArithmeticExpression
Returns
Remarks
DATEADD refuses the nanosecond the last step adds on a date, a smalldatetime and a
datetime - the common type before 2008, and what GETDATE() returns - and the first two would
not hold the time of day it adds anyway. The widening is applied whatever the mapping declares, for the
reason ElapsedTicks(SqlIntervalDifferenceExpression) gives. 2005 has no datetime2 and counts in milliseconds, which
DATEADD takes on a datetime; a smalldatetime is still widened there, since it keeps
no seconds and would round the result to the minute.
ShiftDate(SqlIntervalUnit, ISqlExpression, ISqlExpression)
Shifts a date/time value by a whole number of units - the provider's DATEADD.
protected override ISqlExpression? ShiftDate(SqlIntervalUnit unit, ISqlExpression amount, ISqlExpression date)
Parameters
unitSqlIntervalUnitamountISqlExpressiondateISqlExpression
Returns
Remarks
Must be exact: the anchor correction in IntervalLowering shifts by a computed count and compares the result against the original, so an approximate shift would produce an off-by-one count.
WrapColumnExpression(ISqlExpression)
protected override ISqlExpression WrapColumnExpression(ISqlExpression expr)
Parameters
exprISqlExpression