|
88 | 88 | import org.apache.calcite.sql.TableCharacteristic; |
89 | 89 | import org.apache.calcite.sql.fun.SqlCase; |
90 | 90 | import org.apache.calcite.sql.fun.SqlStdOperatorTable; |
91 | | -import org.apache.calcite.sql.fun.SqlSumAggFunction; |
92 | 91 | import org.apache.calcite.sql.parser.SqlParserPos; |
93 | 92 | import org.apache.calcite.sql.type.*; |
94 | 93 | import org.apache.calcite.sql.util.IdPair; |
@@ -167,6 +166,7 @@ public class SqlValidatorImpl implements SqlValidatorWithHints { |
167 | 166 | * Alias prefix generated for source columns when rewriting UPDATE to MERGE. |
168 | 167 | */ |
169 | 168 | public static final String UPDATE_ANON_PREFIX = "SYS$ANON"; |
| 169 | + public static final String IMPLICIT_COL_NAME = "_ROWID"; |
170 | 170 |
|
171 | 171 | //~ Instance fields -------------------------------------------------------- |
172 | 172 |
|
@@ -4895,7 +4895,7 @@ protected RelDataType createTargetRowType( |
4895 | 4895 | ? logicalTargetRowType |
4896 | 4896 | : realTargetRowType; |
4897 | 4897 |
|
4898 | | - checkFieldCount(insert.getTargetTable(), table, strategies, |
| 4898 | + checkFieldCount(insert.getTargetColumnList(), insert.getTargetTable(), table, strategies, |
4899 | 4899 | targetRowTypeToValidate, realTargetRowType, |
4900 | 4900 | source, logicalSourceRowType, logicalTargetRowType); |
4901 | 4901 |
|
@@ -5027,21 +5027,23 @@ private void checkConstraint( |
5027 | 5027 | * make a subset of fields(start from the left first field) whose |
5028 | 5028 | * length is equals with the source row type fields number |
5029 | 5029 | */ |
5030 | | - private void checkFieldCount(SqlNode node, SqlValidatorTable table, |
| 5030 | + private void checkFieldCount(SqlNodeList targetColumnList, SqlNode node, SqlValidatorTable table, |
5031 | 5031 | List<ColumnStrategy> strategies, RelDataType targetRowTypeToValidate, |
5032 | 5032 | RelDataType realTargetRowType, SqlNode source, |
5033 | 5033 | RelDataType logicalSourceRowType, RelDataType logicalTargetRowType) { |
5034 | | - final int sourceFieldCount = logicalSourceRowType.getFieldCount(); |
5035 | | - final int targetFieldCount = logicalTargetRowType.getFieldCount(); |
5036 | | - final int targetRealFieldCount = realTargetRowType.getFieldCount(); |
5037 | | - if (sourceFieldCount != targetFieldCount |
5038 | | - && sourceFieldCount != targetRealFieldCount) { |
| 5034 | + //final int sourceFieldCount = logicalSourceRowType.getFieldCount(); |
| 5035 | + //final int targetFieldCount = logicalTargetRowType.getFieldCount(); |
| 5036 | + //final int targetRealFieldCount = realTargetRowType.getFieldCount(); |
| 5037 | + //if (sourceFieldCount != targetFieldCount |
| 5038 | + // && sourceFieldCount != targetRealFieldCount) { |
5039 | 5039 | // Allows the source row fields count to be equal with either |
5040 | 5040 | // the logical or the real(excludes columns that can not insert into) |
5041 | 5041 | // target row fields count. |
5042 | | - throw newValidationError(node, |
5043 | | - RESOURCE.unmatchInsertColumn(targetFieldCount, sourceFieldCount)); |
5044 | | - } |
| 5042 | + //throw newValidationError(node, |
| 5043 | + // RESOURCE.unmatchInsertColumn(targetFieldCount, sourceFieldCount)); |
| 5044 | + // return; |
| 5045 | + //} |
| 5046 | + checkFieldCount(targetColumnList, node, logicalSourceRowType, logicalTargetRowType); |
5045 | 5047 | // Ensure that non-nullable fields are targeted. |
5046 | 5048 | for (final RelDataTypeField field : table.getRowType().getFieldList()) { |
5047 | 5049 | final RelDataTypeField targetField = |
@@ -5071,6 +5073,41 @@ private void checkFieldCount(SqlNode node, SqlValidatorTable table, |
5071 | 5073 | } |
5072 | 5074 | } |
5073 | 5075 |
|
| 5076 | + protected void checkFieldCount(SqlNodeList targetColumnList, SqlNode node, RelDataType logicalSourceRowType, |
| 5077 | + RelDataType logicalTargetRowType) { |
| 5078 | + final int sourceFieldCount = logicalSourceRowType.getFieldCount(); |
| 5079 | + final int targetFieldCount = logicalTargetRowType.getFieldCount(); |
| 5080 | + int implicitNum = 0; |
| 5081 | + int sourceImplicitNum = 0; |
| 5082 | + |
| 5083 | + if (targetColumnList != null) { |
| 5084 | + for (SqlNode identifier : targetColumnList.getList()) { |
| 5085 | + if (identifier instanceof SqlIdentifier && isImplicitKey(((SqlIdentifier) identifier).getLastName())) { |
| 5086 | + sourceImplicitNum++; |
| 5087 | + } |
| 5088 | + } |
| 5089 | + } else { |
| 5090 | + // if there is no target column in insert sql,then use default row type |
| 5091 | + for (String fieldName : logicalSourceRowType.getFieldNames()) { |
| 5092 | + if (isImplicitKey(fieldName)) { |
| 5093 | + sourceImplicitNum++; |
| 5094 | + } |
| 5095 | + } |
| 5096 | + } |
| 5097 | + for (String fieldName : logicalTargetRowType.getFieldNames()) { |
| 5098 | + if (isImplicitKey(fieldName)) { |
| 5099 | + implicitNum++; |
| 5100 | + } |
| 5101 | + } |
| 5102 | + if ((sourceFieldCount - sourceImplicitNum) != (targetFieldCount - implicitNum)) { |
| 5103 | + throw newValidationError(node, RESOURCE.unmatchInsertColumn(targetFieldCount, sourceFieldCount)); |
| 5104 | + } |
| 5105 | + } |
| 5106 | + |
| 5107 | + public static boolean isImplicitKey(String fieldName) { |
| 5108 | + return IMPLICIT_COL_NAME.equals(fieldName); |
| 5109 | + } |
| 5110 | + |
5074 | 5111 | /** Returns whether a query uses {@code DEFAULT} to populate a given |
5075 | 5112 | * column. */ |
5076 | 5113 | private static boolean isValuesWithDefault(SqlNode source, int column) { |
|
0 commit comments