protected override SqlStatement PrepareStatement(IRequest context)
{
var values = Values.ToArray();
int firstLen = -1;
for (int n = 0; n < values.Length; ++n) {
var expList = (IList)values[n];
if (firstLen == -1 || firstLen == expList.Count) {
firstLen = expList.Count;
} else {
throw new InvalidOperationException("The insert data list varies in size.");
}
}
var tableName = context.Access().ResolveTableName(TableName);
var table = context.Access().GetTable(tableName);
if (table == null)
throw new ObjectNotFoundException(TableName);
if (Values.Any(x => x.OfType<SqlQueryExpression>().Any()))
throw new InvalidOperationException("Cannot set a value from a query.");
var tableQueryInfo = context.Access().GetTableQueryInfo(tableName, null);
var fromTable = new FromTableDirectSource(context.Query.IgnoreIdentifiersCase(), tableQueryInfo, "INSERT_TABLE", tableName, tableName);
var columns = new string[0];
if (ColumnNames != null)
columns = ColumnNames.ToArray();
if (columns.Length == 0) {
columns = new string[table.TableInfo.ColumnCount];
for (int i = 0; i < columns.Length; i++) {
columns[i] = table.TableInfo[i].ColumnName;
}
}
var colIndices = new int[columns.Length];
var colResolved = new ObjectName[columns.Length];
for (int i = 0; i < columns.Length; ++i) {
var inVar = new ObjectName(columns[i]);
var col = ResolveColumn(fromTable, inVar);
int index = table.FindColumn(col);
if (index == -1)
throw new InvalidOperationException(String.Format("Cannot find column '{0}' in table '{1}'.", col, tableName));
colIndices[i] = index;
colResolved[i] = col;
}
var columnInfos = new List<ColumnInfo>();
foreach (var name in columns) {
var columnName = new ObjectName(tableName, name);
var colIndex = table.FindColumn(columnName);
if (colIndex < 0)
throw new InvalidOperationException(String.Format("Cannot find column '{0}' in table '{1}'", columnName, table.TableInfo.TableName));
columnInfos.Add(table.TableInfo[colIndex]);
}
var assignments = new List<SqlAssignExpression[]>();
foreach (var valueSet in values) {
var valueAssign = new SqlAssignExpression[valueSet.Length];
for (int i = 0; i < valueSet.Length; i++) {
var columnInfo = columnInfos[i];
var value = valueSet[i];
if (value != null) {
// TODO: Deference columns with a preparer
}
if (value != null) {
var expReturnType = value.ReturnType(context, null);
if (!expReturnType.Equals(columnInfo.ColumnType) &&
!expReturnType.CanCastTo(columnInfo.ColumnType))
{
var sb = new StringBuilder ();
sb.AppendFormat ("Unable to convert type {0} of {1} into type {2} of column {3}", expReturnType, value, columnInfo.ColumnType, columnInfo.FullColumnName.FullName);
var ioe = new InvalidOperationException (sb.ToString());
throw ioe;
}
}
valueAssign[i] = SqlExpression.Assign(SqlExpression.Reference(columnInfo.FullColumnName), value);
}
assignments.Add(valueAssign);
}
return new Prepared(tableName, assignments);
}