package org.beetl.sql.core.db;

import org.beetl.sql.core.range.RangeSql;

import java.util.Map;

/**
 * SQL Server 2012以上版本请使用此DBStyle，对翻页做了优化
 * @author darren
 *
 */
public class SqlServer2012Style extends SqlServerStyle {
	SqlServer2012Range sqlServer2012Range = null;
	public SqlServer2012Style() {
		super();
		sqlServer2012Range = new SqlServer2012Range(this);
	}

	@Override
	public RangeSql getRangeSql() {
		return sqlServer2012Range;
	}


	static class SqlServer2012Range implements RangeSql {
		SqlServer2012Style style = null;
		public SqlServer2012Range(SqlServer2012Style sqlServerStyle){
			this.style = sqlServerStyle;
		}

		@Override
		public String toRange(String jdbcSql, Object objOffset, Long limit) {
			Long offset = ((Number)objOffset).longValue();
			StringBuilder builder = new StringBuilder(jdbcSql);
			//sqlserver 2012 以上的 offset 分页必须要跟在order by后面
			//因此如果语句本身没有order by则为其添加一个按默认时间戳的order by
			if(!jdbcSql.matches("(?is).*\\s+order\\s+by[^)]+$")) {
				builder.append(" order by current_timestamp ");
			}
			return builder.append(" offset ")
					.append(PageParamKit.sqlServer2012Offset(style.offsetStartZero, offset))
					.append(" rows fetch next ")
					.append(limit)
					.append(" rows only ").toString();
		}

		@Override
		public String toTemplateRange(Class mapping,String template) {
			StringBuilder builder = new StringBuilder(template);
			//sqlserver 2012 以上的 offset 分页必须要跟在order by后面
			//因此如果语句本身没有order by则为其添加一个按默认时间戳的order by
			//先判断 是否有包含order by条件的 pageIgnoreTag函数 或者单纯的order by xxx结尾
			//有则忽略不再拼接条件，没有则拼接一个定制的getOrderBy函数
			if(!template.matches("(?is).*pageIgnoreTag\\s*\\(\\s*\\)[^}]*?order\\s+by.*|.*\\s+order\\s+by[^)]+$")) {
				builder.append(style.getOrderBy());
			}
			return builder.append(" offset ")
					.append(style.appendExpress(DBAutoGeneratedSql.OFFSET))
					.append(" rows fetch next ")
					.append(style.appendExpress(DBAutoGeneratedSql.PAGE_SIZE))
					.append(" rows only ").toString();
		}

		@Override
		public void addTemplateRangeParas(Map<String, Object> paras, Object objOffset, long size) {
			Long offset = (Long)objOffset;
			long s = offset - (style.offsetStartZero ? 0 : 1);
			paras.put(DBAutoGeneratedSql.OFFSET, s);
			paras.put(DBAutoGeneratedSql.PAGE_SIZE, size);
		}
	}

}