class YieldableMerge extends YieldableMerSert {

        final Merge mergeStatement;

        public YieldableMerge(Merge statement, AsyncHandler<AsyncResult<Integer>> asyncHandler) {
            super(statement, asyncHandler);
            this.mergeStatement = statement;
        }

        @Override
        protected boolean startInternal() {
            if (!table.trySharedLock(session))
                return true;
            session.getUser().checkRight(table, Right.INSERT);
            session.getUser().checkRight(table, Right.UPDATE);
            table.fire(session, Trigger.UPDATE | Trigger.INSERT, true);
            return super.startInternal();
        }

        @Override
        protected void stopInternal() {
            table.fire(session, Trigger.UPDATE | Trigger.INSERT, false);
        }

        @Override
        protected void merSert(Row row) {<FILL_FUNCTION_BODY>}
    }

            ArrayList<Parameter> k = mergeStatement.update.getParameters();
            for (int i = 0; i < statement.columns.length; i++) {
                Column col = statement.columns[i];
                Value v = row.getValue(col.getColumnId());
                if (v == null)
                    v = ValueNull.INSTANCE;
                Parameter p = k.get(i);
                p.setValue(v);
            }
            for (int i = 0; i < mergeStatement.keys.length; i++) {
                Column col = mergeStatement.keys[i];
                Value v = row.getValue(col.getColumnId());
                if (v == null) {
                    throw DbException.get(ErrorCode.COLUMN_CONTAINS_NULL_VALUES_1, col.getSQL());
                }
                Parameter p = k.get(statement.columns.length + i);
                p.setValue(v);
            }
            // 先更新，如果没有记录被更新，说明是一条新的记录，接着再插入
            int count = mergeStatement.update.update();
            if (count > 0) {
                updateCount.addAndGet(count);
            } else if (count == 0) {
                addRowInternal(row);
            } else if (count != 1) {
                throw DbException.get(ErrorCode.DUPLICATE_KEY_1, table.getSQL());
            }
        
<methods>public void <init>(com.lealone.db.session.ServerSession) ,public void addRow(com.lealone.sql.expression.Expression[]) ,public void clearRows() ,public int getPriority() ,public boolean isCacheable() ,public com.lealone.sql.PreparedSQLStatement prepare() ,public void setColumns(com.lealone.db.table.Column[]) ,public void setQuery(com.lealone.sql.query.Query) ,public void setTable(com.lealone.db.table.Table) <variables>protected com.lealone.db.table.Column[] columns,protected final ArrayList<com.lealone.sql.expression.Expression[]> list,protected com.lealone.sql.query.Query query,protected com.lealone.db.table.Table table