public String appendLockHint(LockMode mode, String tableName) {
   if (mode.greaterThan(LockMode.READ)) {
     return tableName + " holdlock";
   } else {
     return tableName;
   }
 }
  public String applyLocksToSql(String sql, Map aliasedLockModes, Map keyColumnNames) {
    Iterator itr = aliasedLockModes.entrySet().iterator();
    StringBuffer buffer = new StringBuffer(sql);
    int correction = 0;
    while (itr.hasNext()) {
      final Map.Entry entry = (Map.Entry) itr.next();
      final LockMode lockMode = (LockMode) entry.getValue();
      if (lockMode.greaterThan(LockMode.READ)) {
        final String alias = (String) entry.getKey();
        int start = -1, end = -1;
        if (sql.endsWith(" " + alias)) {
          start = (sql.length() - alias.length()) + correction;
          end = start + alias.length();
        } else {
          int position = sql.indexOf(" " + alias + " ");
          if (position <= -1) {
            position = sql.indexOf(" " + alias + ",");
          }
          if (position > -1) {
            start = position + correction + 1;
            end = start + alias.length();
          }
        }

        if (start > -1) {
          final String lockHint = appendLockHint(lockMode, alias);
          buffer.replace(start, end, lockHint);
          correction += (lockHint.length() - alias.length());
        }
      }
    }
    return buffer.toString();
  }
 public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) {
   // InterSystems Cache' does not current support "SELECT ... FOR UPDATE" syntax...
   // Set your transaction mode to READ_COMMITTED before using
   if (lockMode == LockMode.PESSIMISTIC_FORCE_INCREMENT) {
     return new PessimisticForceIncrementLockingStrategy(lockable, lockMode);
   } else if (lockMode == LockMode.PESSIMISTIC_WRITE) {
     return new PessimisticWriteUpdateLockingStrategy(lockable, lockMode);
   } else if (lockMode == LockMode.PESSIMISTIC_READ) {
     return new PessimisticReadUpdateLockingStrategy(lockable, lockMode);
   } else if (lockMode == LockMode.OPTIMISTIC) {
     return new OptimisticLockingStrategy(lockable, lockMode);
   } else if (lockMode == LockMode.OPTIMISTIC_FORCE_INCREMENT) {
     return new OptimisticForceIncrementLockingStrategy(lockable, lockMode);
   } else if (lockMode.greaterThan(LockMode.READ)) {
     return new UpdateLockingStrategy(lockable, lockMode);
   } else {
     return new SelectLockingStrategy(lockable, lockMode);
   }
 }
  @Override
  public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map keyColumnNames) {
    // TODO:  merge additional lockoptions support in Dialect.applyLocksToSql
    final Iterator itr = aliasedLockOptions.getAliasLockIterator();
    final StringBuilder buffer = new StringBuilder(sql);
    int correction = 0;
    while (itr.hasNext()) {
      final Map.Entry entry = (Map.Entry) itr.next();
      final LockMode lockMode = (LockMode) entry.getValue();
      if (lockMode.greaterThan(LockMode.READ)) {
        final String alias = (String) entry.getKey();
        int start = -1;
        int end = -1;
        if (sql.endsWith(" " + alias)) {
          start = (sql.length() - alias.length()) + correction;
          end = start + alias.length();
        } else {
          int position = sql.indexOf(" " + alias + " ");
          if (position <= -1) {
            position = sql.indexOf(" " + alias + ",");
          }
          if (position > -1) {
            start = position + correction + 1;
            end = start + alias.length();
          }
        }

        if (start > -1) {
          final String lockHint = appendLockHint(lockMode, alias);
          buffer.replace(start, end, lockHint);
          correction += (lockHint.length() - alias.length());
        }
      }
    }
    return buffer.toString();
  }