Revision 46505 trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.dal/org.gvsig.fmap.dal.db/org.gvsig.fmap.dal.db.jdbc/src/main/java/org/gvsig/fmap/dal/store/jdbc2/spi/JDBCHelperBase.java
JDBCHelperBase.java | ||
---|---|---|
27 | 27 |
import java.sql.Blob; |
28 | 28 |
import java.sql.Clob; |
29 | 29 |
import java.sql.ResultSet; |
30 |
import java.sql.ResultSetMetaData; |
|
30 | 31 |
import java.util.ArrayList; |
32 |
import java.util.Collections; |
|
33 |
import java.util.HashMap; |
|
31 | 34 |
import java.util.HashSet; |
32 | 35 |
import java.util.List; |
36 |
import java.util.Map; |
|
33 | 37 |
import java.util.function.Predicate; |
34 | 38 |
import org.apache.commons.io.IOUtils; |
35 | 39 |
import org.apache.commons.lang3.ArrayUtils; |
... | ... | |
97 | 101 |
import org.slf4j.LoggerFactory; |
98 | 102 |
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_$CONSTANT; |
99 | 103 |
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_$IDENTIFIER; |
104 |
import org.gvsig.fmap.dal.DataManager; |
|
105 |
import org.gvsig.fmap.dal.SQLBuilder.Column; |
|
106 |
import org.gvsig.fmap.dal.SQLBuilder.OrderByBuilder; |
|
107 |
import org.gvsig.fmap.dal.SQLBuilder.SelectBuilder; |
|
108 |
import org.gvsig.fmap.dal.SQLBuilder.SelectColumnBuilder; |
|
100 | 109 |
import org.gvsig.fmap.dal.store.jdbc2.JDBCConnection; |
101 | 110 |
import org.gvsig.fmap.dal.store.jdbc2.spi.expressionbuilder.formatters.ComputedAttribute; |
102 | 111 |
import org.gvsig.tools.util.ContainerUtils; |
... | ... | |
107 | 116 |
private static final boolean ALLOW_AUTOMATIC_VALUES = true; |
108 | 117 |
private static final String QUOTE_FOR_USE_IN_IDENTIFIERS = "\""; |
109 | 118 |
private static final String QUOTE_FOR_USE_IN_STRINGS = "'"; |
119 |
public static final String DONT_ADD_TABLE_NAME_TO_COLUMNS = "DONT_ADD_TABLE_NAME"; |
|
110 | 120 |
|
111 | 121 |
private static final Logger LOGGER = LoggerFactory.getLogger(JDBCHelperBase.class); |
112 | 122 |
|
... | ... | |
699 | 709 |
List<String> extra_column_names) { |
700 | 710 |
replaceForeingValueFunction(sqlbuilder, type, extra_column_names); |
701 | 711 |
replaceExistsFunction(sqlbuilder, type, extra_column_names); |
712 |
addTableToColumnReferences(sqlbuilder, type); |
|
702 | 713 |
} |
703 | 714 |
|
704 | 715 |
@SuppressWarnings("Convert2Lambda") |
... | ... | |
870 | 881 |
if (ContainerUtils.contains(extra_column_names, variable.name(), ContainerUtils.EQUALS_IGNORECASE_COMPARATOR)) { |
871 | 882 |
continue; |
872 | 883 |
} |
884 |
boolean alreadyReplaced = false; |
|
873 | 885 |
for (String foreingName : foreing_value_args) { |
874 | 886 |
String[] foreingNameParts = foreingName.split("[.]"); |
875 | 887 |
if (foreingNameParts.length != 2) { |
... | ... | |
878 | 890 |
String columnNameLocal = foreingNameParts[0]; |
879 | 891 |
String columnNameForeing = foreingNameParts[1]; |
880 | 892 |
if (StringUtils.equalsIgnoreCase(variable.name(), columnNameForeing)) { |
893 |
if(alreadyReplaced){ |
|
894 |
throw new RuntimeException("Column reference \""+ columnNameForeing+"\" is ambiguous"); |
|
895 |
} |
|
896 |
alreadyReplaced = true; |
|
881 | 897 |
|
882 | 898 |
FeatureAttributeDescriptor attr = type.getAttributeDescriptor(columnNameLocal); |
883 | 899 |
if (attr == null) { |
... | ... | |
960 | 976 |
); |
961 | 977 |
usedLeftJoins.add(foreingTable.getName()); |
962 | 978 |
} |
963 |
if ( !(sqlbuilder.select().has_group_by() || sqlbuilder.select().has_aggregate_functions()) ) { |
|
964 |
sqlbuilder.select().column().name(foreingTable, columnNameForeing); |
|
965 |
} |
|
979 |
//No est? claro si debe a?adirse esta columna o no, OJO quitarlo o ponerlo altera los test de H2 |
|
980 |
// if ( !(sqlbuilder.select().has_group_by() || sqlbuilder.select().has_aggregate_functions()) ) { |
|
981 |
// sqlbuilder.select().column().name(foreingTable, columnNameForeing); |
|
982 |
// } |
|
966 | 983 |
} |
967 | 984 |
} |
968 | 985 |
|
969 |
for (SQLBuilder.SelectColumnBuilder column : sqlbuilder.select().getColumns()) { |
|
970 |
if(column.getTable()==null && column.getName()!=null) { |
|
971 |
column.name(table, column.getName()); |
|
972 |
} |
|
973 |
} |
|
974 |
|
|
975 | 986 |
} catch (Throwable th) { |
976 | 987 |
LOGGER.warn("Can't replace FOREING_VALUE function.", th); |
977 | 988 |
throw th; |
... | ... | |
979 | 990 |
// LOGGER.trace("Exit from replaceForeingValueFunction."); |
980 | 991 |
} |
981 | 992 |
} |
993 |
|
|
994 |
protected void addTableToColumnReferences(SQLBuilder sqlbuilder, FeatureType type) { |
|
995 |
// List<SelectBuilder> selectBuilders = new ArrayList<>(); |
|
996 |
// selectBuilders.add(sqlbuilder.select()); |
|
997 |
// sqlbuilder.select().accept((ExpressionBuilder.Visitable value) -> { |
|
998 |
// selectBuilders.add((SelectBuilder) value); |
|
999 |
// |
|
1000 |
// }, (ExpressionBuilder.Visitable visitable) -> (visitable instanceof SelectBuilder)); |
|
1001 |
// for (SelectBuilder selectBuilder : selectBuilders) { |
|
1002 |
// addTableToColumnReferencesInSingleSelect(sqlbuilder, selectBuilder); |
|
1003 |
// } |
|
982 | 1004 |
|
1005 |
|
|
1006 |
addTableToColumnReferencesInSingleSelect(sqlbuilder, sqlbuilder.select(), new ArrayList<>()); |
|
1007 |
|
|
1008 |
} |
|
1009 |
|
|
1010 |
protected void addTableToColumnReferencesInSingleSelect(SQLBuilder sqlbuilder, SelectBuilder select, List<Column> parentColumns) { |
|
1011 |
|
|
1012 |
final SQLBuilder.TableNameBuilder table = select.from().table(); |
|
1013 |
|
|
1014 |
final List<ExpressionBuilder.Value[]> value_replacements = new ArrayList<>(); |
|
1015 |
List<ExpressionBuilder.Variable> variables = new ArrayList<>(); |
|
1016 |
List<ExpressionBuilder.Value> variablesToExclude = new ArrayList<>(); |
|
1017 |
|
|
1018 |
select.accept((ExpressionBuilder.Visitable value) -> { |
|
1019 |
if(value instanceof ExpressionBuilder.Function) { |
|
1020 |
ExpressionBuilder.Function fn = (ExpressionBuilder.Function) value; |
|
1021 |
if(StringUtils.equals(fn.name(), ExpressionBuilder.FUNCTION_GETATTR)){ |
|
1022 |
ExpressionBuilder.Value p1 = fn.parameters().get(0); |
|
1023 |
if(p1 instanceof ExpressionBuilder.Variable){ |
|
1024 |
ExpressionBuilder.Variable v = (ExpressionBuilder.Variable) p1; |
|
1025 |
variablesToExclude.add(v); |
|
1026 |
} |
|
1027 |
ExpressionBuilder.Value p2 = fn.parameters().get(1); |
|
1028 |
if(p2 instanceof ExpressionBuilder.Constant){ |
|
1029 |
ExpressionBuilder.Constant c = (ExpressionBuilder.Constant) p2; |
|
1030 |
variablesToExclude.add(c); |
|
1031 |
} |
|
1032 |
} |
|
1033 |
} else if(value instanceof Column) { |
|
1034 |
Column c = (Column)value; |
|
1035 |
if(c.table() == null || !c.table().has_name()){ |
|
1036 |
variables.add(c); |
|
1037 |
} |
|
1038 |
|
|
1039 |
} else if(value instanceof ExpressionBuilder.Variable) { |
|
1040 |
variables.add((ExpressionBuilder.Variable) value); |
|
1041 |
// } else if(value instanceof SelectColumnBuilder) { |
|
1042 |
// SelectColumnBuilder selectColumn = (SelectColumnBuilder)value; |
|
1043 |
// if(StringUtils.isNotBlank(selectColumn.getName()) && selectColumn.getTable().has_name()){ |
|
1044 |
// variablesToExclude.add(sel) |
|
1045 |
// } |
|
1046 |
} |
|
1047 |
|
|
1048 |
}, new ExpressionBuilder.VisitorFilter() { |
|
1049 |
@Override |
|
1050 |
public boolean skipChildren() { |
|
1051 |
return true; |
|
1052 |
} |
|
1053 |
|
|
1054 |
@Override |
|
1055 |
public boolean accept(ExpressionBuilder.Visitable visitable) { |
|
1056 |
if(select == visitable){ |
|
1057 |
return true; |
|
1058 |
} |
|
1059 |
if(visitable instanceof OrderByBuilder) { |
|
1060 |
return false; |
|
1061 |
} |
|
1062 |
if(visitable instanceof SelectBuilder) { |
|
1063 |
ArrayList<Column> columns = new ArrayList<>(parentColumns); |
|
1064 |
for (SelectColumnBuilder column : select.getColumns()) { |
|
1065 |
columns.add(sqlbuilder.column( |
|
1066 |
table, |
|
1067 |
column.getName())); |
|
1068 |
} |
|
1069 |
addTableToColumnReferencesInSingleSelect(sqlbuilder, (SelectBuilder) visitable, columns); |
|
1070 |
return false; |
|
1071 |
} |
|
1072 |
return true; |
|
1073 |
} |
|
1074 |
}); |
|
1075 |
|
|
1076 |
List<String> variableNamesToExclude = new ArrayList<>(); |
|
1077 |
for(SQLBuilder.SelectColumnBuilder column : select.getColumns()){ |
|
1078 |
if(StringUtils.isNotBlank(column.getAlias())){ |
|
1079 |
variableNamesToExclude.add(column.getAlias()); |
|
1080 |
} else { |
|
1081 |
parentColumns.add(sqlbuilder.column( |
|
1082 |
table, |
|
1083 |
column.getName())); |
|
1084 |
} |
|
1085 |
} |
|
1086 |
|
|
1087 |
for (ExpressionBuilder.Variable variable : variables) { |
|
1088 |
boolean found = false; |
|
1089 |
for (ExpressionBuilder.Value v : variablesToExclude) { |
|
1090 |
if(v == variable){ |
|
1091 |
found = true; |
|
1092 |
break; |
|
1093 |
} |
|
1094 |
} |
|
1095 |
if(found){ |
|
1096 |
continue; |
|
1097 |
} |
|
1098 |
// if(variableNamesToExclude.contains(variable.name())){ |
|
1099 |
// continue; |
|
1100 |
// } |
|
1101 |
Column column = getColumn(parentColumns,variable.name()); |
|
1102 |
if(column != null){ |
|
1103 |
ExpressionBuilder.Variable variable_replacement = sqlbuilder.column( |
|
1104 |
column.table(), |
|
1105 |
variable.name() |
|
1106 |
); |
|
1107 |
value_replacements.add( |
|
1108 |
new ExpressionBuilder.Value[]{ |
|
1109 |
variable, |
|
1110 |
variable_replacement |
|
1111 |
} |
|
1112 |
); |
|
1113 |
} else { |
|
1114 |
ExpressionBuilder.Variable variable_replacement = null; |
|
1115 |
if(variable instanceof SQLBuilder.Column){ |
|
1116 |
column = (SQLBuilder.Column) variable; |
|
1117 |
if (column.table() == null || !column.table().has_name()) { |
|
1118 |
variable_replacement = sqlbuilder.column( |
|
1119 |
table, |
|
1120 |
variable.name() |
|
1121 |
); |
|
1122 |
} else if(!column.table().has_schema()){ |
|
1123 |
SQLBuilder.TableNameBuilder t = sqlbuilder.table_name() |
|
1124 |
.name(column.table().getName()) |
|
1125 |
.schema(table.getSchema()); //Mismo esquema que en el FROM |
|
1126 |
variable_replacement = sqlbuilder.column( |
|
1127 |
t, |
|
1128 |
variable.name() |
|
1129 |
); |
|
1130 |
} |
|
1131 |
} else { |
|
1132 |
variable_replacement = sqlbuilder.column( |
|
1133 |
table, |
|
1134 |
variable.name() |
|
1135 |
); |
|
1136 |
} |
|
1137 |
if(variable_replacement != null){ |
|
1138 |
value_replacements.add( |
|
1139 |
new ExpressionBuilder.Value[]{ |
|
1140 |
variable, |
|
1141 |
variable_replacement |
|
1142 |
} |
|
1143 |
); |
|
1144 |
} |
|
1145 |
} |
|
1146 |
|
|
1147 |
} |
|
1148 |
|
|
1149 |
for (ExpressionBuilder.Value[] replaceValue : value_replacements) { |
|
1150 |
ExpressionBuilder.Value target = replaceValue[0]; |
|
1151 |
ExpressionBuilder.Value replacement = replaceValue[1]; |
|
1152 |
Boolean dontAddTableName = (Boolean) target.getProperty(DONT_ADD_TABLE_NAME_TO_COLUMNS); |
|
1153 |
if(dontAddTableName != null && dontAddTableName){ |
|
1154 |
continue; |
|
1155 |
} |
|
1156 |
select.replace(target, replacement); |
|
1157 |
} |
|
1158 |
|
|
1159 |
} |
|
1160 |
|
|
1161 |
protected Column getColumn(List<Column> columns, String name){ |
|
1162 |
for (int i = columns.size()-1; i >= 0; i--) { |
|
1163 |
if(StringUtils.equalsIgnoreCase(columns.get(i).name(), name)){ |
|
1164 |
return columns.get(i); |
|
1165 |
} |
|
1166 |
} |
|
1167 |
return null; |
|
1168 |
} |
|
1169 |
|
|
1170 |
|
|
983 | 1171 |
@Override |
984 | 1172 |
public void setTransaction(DataTransactionServices transaction) { |
985 | 1173 |
this.transaction = transaction; |
... | ... | |
1003 | 1191 |
public void expandCalculedColumns(JDBCSQLBuilderBase sqlbuilder) { |
1004 | 1192 |
ComputedAttribute computedAttributeFormater = new ComputedAttribute(sqlbuilder, sqlbuilder.formatter()); |
1005 | 1193 |
for (int i = 0; i < 10; i++) { |
1006 |
List<Pair<ExpressionBuilder.Value, ExpressionBuilder.Value>> variablesToReplace = new ArrayList<>(); |
|
1007 |
sqlbuilder.accept(new ExpressionBuilder.Visitor() { |
|
1008 |
@Override |
|
1009 |
public void visit(ExpressionBuilder.Visitable value) { |
|
1010 |
if (computedAttributeFormater.canApply((ExpressionBuilder.Value) value)) { |
|
1011 |
ExpressionBuilder.Variable variable = (ExpressionBuilder.Variable) value; |
|
1012 |
ExpressionBuilder.Value replace = computedAttributeFormater.expandedValue(variable); |
|
1013 |
variablesToReplace.add(Pair.of(variable, replace)); |
|
1014 |
} |
|
1194 |
List<Pair<ExpressionBuilder.Variable, ExpressionBuilder.Value>> variablesToReplace = new ArrayList<>(); |
|
1195 |
sqlbuilder.accept((ExpressionBuilder.Visitable value) -> { |
|
1196 |
if (computedAttributeFormater.canApply((ExpressionBuilder.Value) value)) { |
|
1197 |
ExpressionBuilder.Variable variable = (ExpressionBuilder.Variable) value; |
|
1198 |
ExpressionBuilder.Value replace = computedAttributeFormater.expandedValue(variable); |
|
1199 |
variablesToReplace.add(Pair.of(variable, replace)); |
|
1015 | 1200 |
} |
1016 | 1201 |
}, null); |
1017 | 1202 |
if (variablesToReplace.isEmpty()) { |
1018 | 1203 |
break; |
1019 | 1204 |
} |
1020 |
for (Pair<ExpressionBuilder.Value, ExpressionBuilder.Value> entry : variablesToReplace) {
|
|
1205 |
for (Pair<ExpressionBuilder.Variable, ExpressionBuilder.Value> entry : variablesToReplace) {
|
|
1021 | 1206 |
ExpressionBuilder.Value variable = entry.getKey(); |
1022 | 1207 |
ExpressionBuilder.Value replace = entry.getValue(); |
1208 |
Boolean dontAddTableName = (Boolean) variable.getProperty(DONT_ADD_TABLE_NAME_TO_COLUMNS); |
|
1209 |
if (dontAddTableName != null && dontAddTableName) { |
|
1210 |
continue; |
|
1211 |
} |
|
1023 | 1212 |
sqlbuilder.select().replace(variable, replace); |
1024 | 1213 |
} |
1025 | 1214 |
} |
Also available in: Unified diff