All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.easy.query.mssql.expression.MsSQLInsertSQLExpression Maven / Gradle / Ivy

The newest version!
package com.easy.query.mssql.expression;

import com.easy.query.core.basic.jdbc.parameter.ToSQLContext;
import com.easy.query.core.context.QueryRuntimeContext;
import com.easy.query.core.enums.EasyBehaviorEnum;
import com.easy.query.core.exception.EasyQueryInvalidOperationException;
import com.easy.query.core.expression.parser.core.available.TableAvailable;
import com.easy.query.core.expression.segment.InsertUpdateSetColumnSQLSegment;
import com.easy.query.core.expression.segment.SQLSegment;
import com.easy.query.core.expression.segment.builder.SQLBuilderSegment;
import com.easy.query.core.expression.sql.builder.ExpressionContext;
import com.easy.query.core.expression.sql.expression.EntityTableSQLExpression;
import com.easy.query.core.expression.sql.expression.impl.EntitySQLExpressionMetadata;
import com.easy.query.core.expression.sql.expression.impl.InsertSQLExpressionImpl;
import com.easy.query.core.metadata.EntityMetadata;
import com.easy.query.core.util.EasyClassUtil;
import com.easy.query.core.util.EasyCollectionUtil;
import com.easy.query.core.util.EasySQLExpressionUtil;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * create time 2023/7/27 17:56
 * 文件说明
 *
 * @author xuejiaming
 */
public class MsSQLInsertSQLExpression extends InsertSQLExpressionImpl {

    public MsSQLInsertSQLExpression(EntitySQLExpressionMetadata entitySQLExpressionMetadata, EntityTableSQLExpression table) {
        super(entitySQLExpressionMetadata, table);
    }

    /**
     * 支持insert or update
     * 代码参考 FreeSQL
     *
     * @param toSQLContext
     * @return
     */
    @Override
    public String toSQL(ToSQLContext toSQLContext) {
//        List sqlSegments = columns.getSQLSegments();
        ExpressionContext expressionContext = entitySQLExpressionMetadata.getExpressionContext();
        boolean insertOrIgnore = expressionContext.getBehavior().hasBehavior(EasyBehaviorEnum.ON_DUPLICATE_KEY_IGNORE);
        boolean insertOrUpdate = expressionContext.getBehavior().hasBehavior(EasyBehaviorEnum.ON_DUPLICATE_KEY_UPDATE);
        if (!insertOrIgnore && !insertOrUpdate) {
            return super.toSQL(toSQLContext);
        } else {
            EasySQLExpressionUtil.expressionInvokeRoot(toSQLContext);
            QueryRuntimeContext runtimeContext = expressionContext.getRuntimeContext();
            EntityTableSQLExpression easyTableSQLExpression = tables.get(0);
            EntityMetadata entityMetadata = easyTableSQLExpression.getEntityMetadata();
            TableAvailable entityTable = easyTableSQLExpression.getEntityTable();
            String tableName = easyTableSQLExpression.toSQL(toSQLContext);

            Collection keyProperties = entityMetadata.getKeyProperties();

            Collection constraintPropertyNames = getConstraintPropertyName(keyProperties);
            Set duplicateKeyUpdateColumnsSet = getColumnsSet(columns);

            StringBuilder sql = new StringBuilder("MERGE INTO ");
            sql.append(tableName).append(" t1 USING (SELECT ");


            List sqlColumns = new ArrayList<>(columns.getSQLSegments().size());
            StringBuilder mergeAliasSql = new StringBuilder();
            for (SQLSegment sqlSegment : columns.getSQLSegments()) {
                if (!(sqlSegment instanceof InsertUpdateSetColumnSQLSegment)) {
                    throw new EasyQueryInvalidOperationException("insert not support:" + EasyBehaviorEnum.ON_DUPLICATE_KEY_UPDATE.name() + ",column type:" + EasyClassUtil.getSimpleName(sqlSegment.getClass()));
                }
                InsertUpdateSetColumnSQLSegment sqlEntitySegment = (InsertUpdateSetColumnSQLSegment) sqlSegment;
//                String propertyName = sqlEntitySegment.getPropertyName();
//                if (constraintPropertyNames.contains(propertyName) || keyProperties.contains(propertyName) || !duplicateKeyUpdateColumnsSet.contains(propertyName)) {
//                    continue;
//                }
                if (mergeAliasSql.length() != 0) {
                    mergeAliasSql.append(",");
                }

                String columnNameWithOwner = getColumnNameWithOwner(sqlEntitySegment, toSQLContext);
                sqlColumns.add(columnNameWithOwner);
                mergeAliasSql.append(sqlEntitySegment.toSQL(toSQLContext)).append(" AS ").append(columnNameWithOwner);
            }
            sql.append(mergeAliasSql);
            sql.append(" ) t2 ");
            sql.append("ON (");

            Iterator constraintPropertyIterator = constraintPropertyNames.iterator();
            String firstConstraintProperty = constraintPropertyIterator.next();
            String firstQuoteName = getQuoteName(entityTable, runtimeContext, firstConstraintProperty);
            sql.append("t1.").append(firstQuoteName).append(" = ").append("t2.").append(firstQuoteName);
            while (constraintPropertyIterator.hasNext()) {
                String nextConstraintProperty = constraintPropertyIterator.next();
                String quoteName = getQuoteName(entityTable, runtimeContext, nextConstraintProperty);
                sql.append(" AND t1.").append(quoteName).append(" = ").append("t2.").append(quoteName);
            }
            sql.append(") ");
            if (insertOrUpdate) {

                StringBuilder duplicateKeyUpdateSql = new StringBuilder();
                SQLBuilderSegment realDuplicateKeyUpdateColumns = getRealDuplicateKeyUpdateColumns();
                List realDuplicateKeyUpdateColumnsSQLSegments = realDuplicateKeyUpdateColumns.getSQLSegments();
                for (SQLSegment sqlSegment : realDuplicateKeyUpdateColumnsSQLSegments) {
                    if (!(sqlSegment instanceof InsertUpdateSetColumnSQLSegment)) {
                        throw new EasyQueryInvalidOperationException("insert not support:" + EasyBehaviorEnum.ON_DUPLICATE_KEY_UPDATE.name() + ",column type:" + EasyClassUtil.getSimpleName(sqlSegment.getClass()));
                    }
                    InsertUpdateSetColumnSQLSegment sqlEntitySegment = (InsertUpdateSetColumnSQLSegment) sqlSegment;
                    String propertyName = sqlEntitySegment.getPropertyName();
                    if (constraintPropertyNames.contains(propertyName) || keyProperties.contains(propertyName) || !duplicateKeyUpdateColumnsSet.contains(propertyName)) {
                        continue;
                    }
                    if (duplicateKeyUpdateSql.length() != 0) {
                        duplicateKeyUpdateSql.append(",");
                    }
                    String quoteName = sqlEntitySegment.getColumnNameWithOwner(toSQLContext);
                    duplicateKeyUpdateSql.append("t1.").append(quoteName).append(" = ").append("t2.").append(quoteName);
                }
                if (duplicateKeyUpdateSql.length() > 0) {
                    sql.append("WHEN MATCHED THEN UPDATE SET ");
                    sql.append(duplicateKeyUpdateSql).append(" ");
                }
            }
            sql.append("WHEN NOT MATCHED THEN INSERT (");
            sql.append(String.join(",", sqlColumns));
            sql.append(") VALUES (");
            sql.append(sqlColumns.stream().map(o -> "t2." + o).collect(Collectors.joining(",")));
            sql.append(");");

            return sql.toString();
        }
    }

    private String getQuoteName(TableAvailable entityTable, QueryRuntimeContext runtimeContext, String constraintProperty) {
        String keyColumnName = entityTable.getColumnName(constraintProperty);
        return EasySQLExpressionUtil.getQuoteName(runtimeContext, keyColumnName);
    }

    protected Collection getConstraintPropertyName(Collection keyProperties) {
        if (EasyCollectionUtil.isEmpty(duplicateKeys)) {
            return keyProperties;
        }
        return duplicateKeys;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy