content: /*
   * Copyright (C) 2020 ActiveJ LLC.
   *
   * 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
   *
   * http://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.
   */
  
  package io.activej.cube.ot.sql;
  
  import java.sql.Connection;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.sql.Statement;
  
  public interface SqlAtomicSequence {
  	default long getAndAdd(Connection connection, int stride) throws SQLException {
  		return addAndGet(connection, stride) - stride;
  	}
  
  	default long addAndGet(Connection connection, int stride) throws SQLException {
  		return getAndAdd(connection, stride) + stride;
  	}
  
  	static SqlAtomicSequence ofLastInsertID(String table, String field) {
  		return ofLastInsertID(table, field, null);
  	}
  
  	static SqlAtomicSequence ofLastInsertID(String table, String field, String where) {
  		String sql = """
  			UPDATE {table}
  			SET {field} = LAST_INSERT_ID({table}.{field}) + :stride
  			"""
  			.replace("{table}", "`" + table + "`")
  			.replace("{field}", "`" + field + "`");
  		if (where != null) {
  			sql += " WHERE " + where;
  		}
  		String finalSql = sql;
  		return new SqlAtomicSequence() {
  			@Override
  			public long getAndAdd(Connection connection, int stride) throws SQLException {
  				try (Statement statement = connection.createStatement()) {
  					statement.execute(finalSql.replace(":stride", Integer.toString(stride)), Statement.RETURN_GENERATED_KEYS);
  					try (ResultSet generatedKeys = statement.getGeneratedKeys()) {
  						generatedKeys.next();
  						return generatedKeys.getLong(1);
  					}
  				}
  			}
  		};
  	}
  }
  