/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Other licenses:
 * -----------------------------------------------------------------------------
 * Commercial licenses for this work are available. These replace the above
 * Apache-2.0 license and offer limited warranties, support, maintenance, and
 * commercial database integrations.
 *
 * For more information, please visit: https://www.jooq.org/legal/licensing
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package org.jooq.impl;

import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.jooq.BindContext;
import org.jooq.Configuration;
import org.jooq.ExecuteContext;
import org.jooq.Field;

import io.r2dbc.spi.R2dbcException;

/**
 * @author Lukas Eder
 */
final class DefaultBindContext extends AbstractBindContext {

    DefaultBindContext(Configuration configuration, ExecuteContext ctx, PreparedStatement stmt) {
        super(configuration, ctx, stmt);
    }

    @Override
    @SuppressWarnings({ "unchecked" })
    protected final BindContext bindValue0(Object value, Field<?> field) throws SQLException {
        int nextIndex = nextIndex();

        try {
            ((Field<Object>) field).getBinding().set(new DefaultBindingSetStatementContext<>(
                executeContext() != null
                    ? executeContext()
                    : new SimpleExecuteContext(configuration(), data()),
                stmt,
                nextIndex,
                value
            ));
        }

        // [#14696] Maintain SQLState and ErrorCode if the exception is from the driver
        catch (SQLException e) {
            throw new SQLException("Error while writing value at JDBC bind index: " + nextIndex, e.getSQLState(), e.getErrorCode(), e);
        }

        // [#15028] Avoid misleading error when the original exception is an R2DBC one
        catch (R2dbcException e) {
            throw new SQLException("Error while writing value at R2DBC bind index: " + (nextIndex - 1), e.getSqlState(), e.getErrorCode(), e);
        }
        catch (Exception e) {
            throw new SQLException("Error while writing value at bind index: " + nextIndex, e);
        }

        return this;
    }
}
