com.sap.cds.impl.JdbcDataSourceAdapter Maven / Gradle / Ivy
/************************************************************************
* © 2019-2023 SAP SE or an SAP affiliate company. All rights reserved. *
************************************************************************/
package com.sap.cds.impl;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Optional;
import com.sap.cds.DataStoreConfiguration;
import com.sap.cds.impl.docstore.DocStoreDeleteStatementBuilder;
import com.sap.cds.impl.docstore.DocStoreSelectStatementBuilder;
import com.sap.cds.impl.docstore.DocStoreUpdateStatementBuilder;
import com.sap.cds.impl.docstore.DocStoreUtils;
import com.sap.cds.impl.localized.LocaleUtils;
import com.sap.cds.impl.qat.QatSelectableNode;
import com.sap.cds.impl.sql.DeleteStatementBuilder;
import com.sap.cds.impl.sql.InsertStatementBuilder;
import com.sap.cds.impl.sql.SQLStatementBuilder.SQLStatement;
import com.sap.cds.impl.sql.SelectStatementBuilder;
import com.sap.cds.impl.sql.UpdateStatementBuilder;
import com.sap.cds.impl.sql.UpsertStatementBuilder;
import com.sap.cds.jdbc.spi.StatementResolver;
import com.sap.cds.ql.cqn.CqnFilterableStatement;
import com.sap.cds.ql.cqn.CqnSelect;
import com.sap.cds.ql.cqn.CqnStatement;
public class JdbcDataSourceAdapter implements SQLDataSourceAdapter {
private static final ArrayDeque ROOT = new ArrayDeque<>();
private final Context context;
private final StatementResolver statementResolver;
private final LocaleUtils localeUtils;
private final DocStoreUtils docStoreUtils;
public JdbcDataSourceAdapter(Context context) {
this.context = context;
this.statementResolver = context.getDbContext().getStatementResolver();
this.localeUtils = new LocaleUtils(context.getCdsModel(), context.getDataStoreConfiguration());
this.docStoreUtils = new DocStoreUtils(context.getCdsModel());
}
@Override
public SQLStatement process(CqnStatement statement) {
if (docStoreUtils.targetsDocStore(statement)) {
return getDocStoreSqlStatement(statement);
}
return getColumnStoreSqlStatement(statement);
}
private SQLStatement getDocStoreSqlStatement(CqnStatement statement) {
assertThatDocStoreSupportIsEnabled();
if (statement.isSelect()) {
return new DocStoreSelectStatementBuilder(context, statement.asSelect()).build();
}
if (statement.isInsert()) {
return DocStoreUtils.getDocStoreInsertStatement(statement.asInsert(), context);
}
if (statement.isUpdate()) {
return new DocStoreUpdateStatementBuilder(context, statement.asUpdate()).build();
}
if (statement.isDelete()) {
return new DocStoreDeleteStatementBuilder(context, statement.asDelete()).build();
}
throw new UnsupportedOperationException("Unsupported statement type: " + statement);
}
private SQLStatement getColumnStoreSqlStatement(CqnStatement statement) {
if (statement.isSelect()) {
CqnSelect select = statement.asSelect();
return appendCollation(new SelectStatementBuilder(context, new ArrayList<>(), select, ROOT).build(),
select);
}
if (statement.isInsert()) {
return new InsertStatementBuilder(context, statement.asInsert()).build();
}
if (statement.isUpsert()) {
return new UpsertStatementBuilder(context, statement.asUpsert()).build();
}
if (statement.isUpdate()) {
return appendCollation(new UpdateStatementBuilder(context, statement.asUpdate()).build(),
statement.asUpdate());
}
if (statement.isDelete()) {
return appendCollation(new DeleteStatementBuilder(context, statement.asDelete()).build(),
statement.asDelete());
}
throw new UnsupportedOperationException("Unsupported statement type: " + statement);
}
private SQLStatement appendCollation(SQLStatement sqlStatement, CqnFilterableStatement statement) {
Locale locale = context.getSessionContext().getLocale();
if (localeUtils.requiresCollationClause(statement, locale)) { // TODO only required on HANA
Optional collationClause = statementResolver.withCollation(statement, locale);
if (collationClause.isPresent()) {
String sql = String.join(" ", sqlStatement.sql(), collationClause.get());
return new SQLStatement(sql, sqlStatement.params());
}
}
return sqlStatement;
}
public void assertThatDocStoreSupportIsEnabled() {
if (!context.getDataStoreConfiguration().getProperty(DataStoreConfiguration.DOCSTORE_INTEGRATION_ENABLED,
false)) {
throw new UnsupportedOperationException(
"Can't handle an entity annotated as doc-store enabled: DocStore integration is not enabled.");
}
}
}