use of org.apache.cayenne.dba.QuotingStrategy in project cayenne by apache.
the class UnitDbAdapter method getConstraints.
/**
* Returns a map of database constraints with DbEntity names used as keys,
* and Collections of constraint names as values.
*/
protected Map<String, Collection<String>> getConstraints(Connection conn, DataMap map, Collection<String> includeTables) throws SQLException {
Map<String, Collection<String>> constraintMap = new HashMap<>();
DatabaseMetaData metadata = conn.getMetaData();
for (String name : includeTables) {
DbEntity entity = map.getDbEntity(name);
if (entity == null) {
continue;
}
QuotingStrategy strategy = adapter.getQuotingStrategy();
// Get all constraints for the table
ResultSet rs = metadata.getExportedKeys(entity.getCatalog(), entity.getSchema(), entity.getName());
try {
while (rs.next()) {
String fk = rs.getString("FK_NAME");
String fkTable = rs.getString("FKTABLE_NAME");
if (fk != null && fkTable != null) {
Collection<String> constraints = constraintMap.get(fkTable);
if (constraints == null) {
// use a set to avoid duplicate constraints
constraints = new HashSet<String>();
constraintMap.put(fkTable, constraints);
}
constraints.add(strategy.quotedIdentifier(entity, fk));
}
}
} finally {
rs.close();
}
}
return constraintMap;
}
use of org.apache.cayenne.dba.QuotingStrategy in project cayenne by apache.
the class FlattenedArcKey method buildJoinSnapshotsForDelete.
/**
* Returns pk snapshots for join records for the single-step flattened
* relationship. Multiple joins between the same pair of objects are
* theoretically possible, so the return value is a list.
*/
List buildJoinSnapshotsForDelete(DataNode node) {
Map<String, Object> snapshot = eagerJoinSnapshot();
DbEntity joinEntity = getJoinEntity();
boolean fetchKey = false;
for (DbAttribute dbAttr : joinEntity.getPrimaryKeys()) {
String dbAttrName = dbAttr.getName();
if (!snapshot.containsKey(dbAttrName)) {
fetchKey = true;
break;
}
}
if (!fetchKey) {
return Collections.singletonList(snapshot);
}
// ok, the key is not included in snapshot, must do the fetch...
// TODO: this should be optimized in the future, but now
// DeleteBatchQuery
// expects a PK snapshot, so we must provide it.
QuotingStrategy quoter = node.getAdapter().getQuotingStrategy();
StringBuilder sql = new StringBuilder("SELECT ");
Collection<DbAttribute> pk = joinEntity.getPrimaryKeys();
final List<DbAttribute> pkList = pk instanceof List ? (List<DbAttribute>) pk : new ArrayList<>(pk);
for (int i = 0; i < pkList.size(); i++) {
if (i > 0) {
sql.append(", ");
}
DbAttribute attribute = pkList.get(i);
sql.append("#result('");
sql.append(quoter.quotedName(attribute));
// since the name of the column can potentially be quoted and
// use reserved keywords as name, let's specify generated column
// name parameters to ensure the query doesn't explode
sql.append("' '").append(TypesMapping.getJavaBySqlType(attribute.getType()));
sql.append("' '").append("pk").append(i);
sql.append("')");
}
sql.append(" FROM ").append(quoter.quotedFullyQualifiedName(joinEntity)).append(" WHERE ");
int i = snapshot.size();
for (Object key : snapshot.keySet()) {
sql.append(quoter.quotedIdentifier(joinEntity, String.valueOf(key))).append(" #bindEqual($").append(key).append(")");
if (--i > 0) {
sql.append(" AND ");
}
}
SQLTemplate query = new SQLTemplate(joinEntity.getDataMap(), sql.toString(), true);
query.setParams(snapshot);
final List[] result = new List[1];
node.performQueries(Collections.singleton((Query) query), new DefaultOperationObserver() {
@Override
public void nextRows(Query query, List<?> dataRows) {
if (!dataRows.isEmpty()) {
// decode results...
List<DataRow> fixedRows = new ArrayList<>(dataRows.size());
for (Object o : dataRows) {
DataRow row = (DataRow) o;
DataRow fixedRow = new DataRow(2);
for (int i = 0; i < pkList.size(); i++) {
DbAttribute attribute = pkList.get(i);
fixedRow.put(attribute.getName(), row.get("pk" + i));
}
fixedRows.add(fixedRow);
}
dataRows = fixedRows;
}
result[0] = dataRows;
}
@Override
public void nextQueryException(Query query, Exception ex) {
throw new CayenneRuntimeException("Raising from query exception.", Util.unwindException(ex));
}
@Override
public void nextGlobalException(Exception ex) {
throw new CayenneRuntimeException("Raising from underlyingQueryEngine exception.", Util.unwindException(ex));
}
});
return result[0];
}
use of org.apache.cayenne.dba.QuotingStrategy in project cayenne by apache.
the class DefaultSelectTranslator method doTranslate.
@Override
protected void doTranslate() {
checkLimitAndJointPrefetch();
DataMap dataMap = queryMetadata.getDataMap();
JoinStack joins = getJoinStack();
QuotingStrategy strategy = getAdapter().getQuotingStrategy();
forcingDistinct = false;
// build column list
this.resultColumns = buildResultColumns();
// build qualifier
QualifierTranslator qualifierTranslator = adapter.getQualifierTranslator(this);
StringBuilder whereQualifierBuffer = qualifierTranslator.appendPart(new StringBuilder());
// build having qualifier
Expression havingQualifier = getSelectQuery().getHavingQualifier();
StringBuilder havingQualifierBuffer = null;
if (havingQualifier != null) {
haveAggregate = true;
QualifierTranslator havingQualifierTranslator = adapter.getQualifierTranslator(this);
havingQualifierTranslator.setQualifier(havingQualifier);
havingQualifierBuffer = havingQualifierTranslator.appendPart(new StringBuilder());
}
if (!haveAggregate && groupByColumns != null) {
// if no expression with aggregation function found
// in select columns and there is no having clause
groupByColumns.clear();
}
// build ORDER BY
OrderingTranslator orderingTranslator = new OrderingTranslator(this);
StringBuilder orderingBuffer = orderingTranslator.appendPart(new StringBuilder());
// assemble
StringBuilder queryBuf = new StringBuilder();
queryBuf.append("SELECT ");
// side effect: "suppressingDistinct" flag may end up being flipped here
if (forcingDistinct || getSelectQuery().isDistinct()) {
suppressingDistinct = queryMetadata.isSuppressingDistinct();
if (!suppressingDistinct) {
for (ColumnDescriptor column : resultColumns) {
if (isUnsupportedForDistinct(column.getJdbcType())) {
suppressingDistinct = true;
break;
}
}
}
if (!suppressingDistinct) {
queryBuf.append(buildDistinctStatement()).append(" ");
}
}
// convert ColumnDescriptors to column names
List<String> selectColumnExpList = new ArrayList<>();
for (ColumnDescriptor column : resultColumns) {
String fullName;
if (column.isExpression()) {
fullName = column.getName();
} else {
fullName = strategy.quotedIdentifier(dataMap, column.getNamePrefix(), column.getName());
}
selectColumnExpList.add(fullName);
}
// uses the DISTINCT modifier
if (forcingDistinct || getSelectQuery().isDistinct()) {
List<String> orderByColumnList = orderingTranslator.getOrderByColumnList();
for (String orderByColumnExp : orderByColumnList) {
// Convert to ColumnDescriptors??
if (!selectColumnExpList.contains(orderByColumnExp)) {
selectColumnExpList.add(orderByColumnExp);
}
}
}
appendSelectColumns(queryBuf, selectColumnExpList);
// append from clause
queryBuf.append(" FROM ");
// append tables and joins
joins.appendRootWithQuoteSqlIdentifiers(queryBuf, getQueryMetadata().getDbEntity());
joins.appendJoins(queryBuf);
joins.appendQualifier(whereQualifierBuffer, whereQualifierBuffer.length() == 0);
// append qualifier
if (whereQualifierBuffer.length() > 0) {
queryBuf.append(" WHERE ");
queryBuf.append(whereQualifierBuffer);
}
if (groupByColumns != null && !groupByColumns.isEmpty()) {
queryBuf.append(" GROUP BY ");
appendGroupByColumns(queryBuf, groupByColumns);
}
// append HAVING qualifier
if (havingQualifierBuffer != null && havingQualifierBuffer.length() > 0) {
queryBuf.append(" HAVING ");
queryBuf.append(havingQualifierBuffer);
}
// append prebuilt ordering
if (orderingBuffer.length() > 0) {
queryBuf.append(" ORDER BY ").append(orderingBuffer);
}
if (!isSuppressingDistinct()) {
appendLimitAndOffsetClauses(queryBuf);
}
this.sql = queryBuf.toString();
}
use of org.apache.cayenne.dba.QuotingStrategy in project cayenne by apache.
the class FirebirdMergerTokenFactory method createSetAllowNullToDb.
@Override
public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
return new SetAllowNullToDb(entity, column) {
public List<String> createSql(DbAdapter adapter) {
QuotingStrategy context = adapter.getQuotingStrategy();
String entityName = context.quotedFullyQualifiedName(getEntity());
String columnName = context.quotedName(getColumn());
// but this might be achived by modyfication system tables
return Collections.singletonList(String.format("UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = NULL " + " WHERE RDB$FIELD_NAME = '%s' AND RDB$RELATION_NAME = '%s'", columnName, entityName));
}
};
}
use of org.apache.cayenne.dba.QuotingStrategy in project cayenne by apache.
the class IngresMergerTokenFactory method createSetNotNullToDb.
@Override
public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
return new SetNotNullToDb(entity, column) {
@Override
public List<String> createSql(DbAdapter adapter) {
/*
* TODO: we generate this query as in ingres db documentation,
* but unfortunately ingres don't support it
*/
StringBuilder sqlBuffer = new StringBuilder();
QuotingStrategy context = adapter.getQuotingStrategy();
sqlBuffer.append("ALTER TABLE ");
sqlBuffer.append(getEntity().getFullyQualifiedName());
sqlBuffer.append(" ALTER COLUMN ");
sqlBuffer.append(context.quotedName(getColumn()));
sqlBuffer.append(" ");
sqlBuffer.append(adapter.externalTypesForJdbcType(getColumn().getType())[0]);
if (adapter.typeSupportsLength(getColumn().getType()) && getColumn().getMaxLength() > 0) {
sqlBuffer.append("(");
sqlBuffer.append(getColumn().getMaxLength());
sqlBuffer.append(")");
}
sqlBuffer.append(" NOT NULL");
return Collections.singletonList(sqlBuffer.toString());
}
};
}
Aggregations