package org.beetl.sql.core.db;

import org.beetl.sql.clazz.kit.KeyWordHandler;
import org.beetl.sql.core.ConnectionSource;
import org.beetl.sql.core.ExecuteContext;
import org.beetl.sql.core.SQLExecutor;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.engine.template.SQLTemplateEngine;
import org.beetl.sql.core.meta.MetadataManager;
import org.beetl.sql.core.meta.SchemaMetadataManager;
import org.beetl.sql.core.range.RangeSql;

import java.util.Properties;

/**
 * 用来描述数据库差异，主键生成，sql语句，翻页等，有一部分元数据的差异在{@link SchemaMetadataManager}
 *
 * @author xiandafu
 */
public interface DBStyle extends DBAutoGeneratedSql {


    /**
     * 返回DBStyle名称
     * @return
     */
    String getName();

    /**
     * 返回一个DBStyle代码
     * @return
     */
    int getDBType();

    /**
     * 翻页语句实现
     * @return
     */
    RangeSql getRangeSql();




    int getIdType(Class c,String idProperty);

    KeyWordHandler getKeyWordHandler();
    
    /**
     * 通过序列名字返回获取序列值的sql片段，比如
     *
     * @param seqName
     * @return
     * @see org.beetl.sql.annotation.entity.SeqID
     * @see OracleStyle#getSeqValue(String)
     */
    String getSeqValue(String seqName);

    /**
     * sql中的关键字处理
     * @param keyWordHandler
     */
    void setKeyWordHandler(KeyWordHandler keyWordHandler);



    /**
     * jdbc 的batch 个数在数据库收到限制，beetlsql会把批处理数据分批处理
     * 这里配置了一个数据库允许的最大批处理个数，默认1000个 TODO,SQLExecutor里未实现
     * @return
     */
    default int getMaxBatchCount(){
        return 1000;
    }

    /**
     * 是否是NOSql
     * @return
     */
    default boolean  isNoSql(){
        return false;
    }

    /**
     * 对应的数据库是否支持jdbc metadata
     * @return
     */
    default boolean metadataSupport(){
        return true ;
    }

    /**
     * 是否支持PreparedStatement，对于数据库来说，几乎都支持，对于Nosql，则不一定支持
     * @return
     */
    default boolean preparedStatementSupport(){
        return true;
    }

	/**
	 * 批量插入或者更新的时候聚，数据库是否支持自动生成值，如自增
	 * @return
	 */
	default boolean batchGeneratedKeysSupport(){
		return true;
	}

    /**
     * 如果不支持preparedStatement，在直接使用Statement的时候，返回输出变量到sql语句里，例如，当变量是字符串a"bc
     * 应该输出{@code "a\"bc"}，注意，需要考虑SQL注入漏洞
     *
     * @param value
     * @return
     */
    String wrapStatementValue(Object value);

    /**
     * 得到一个SQL执行类{@code SQLExecutor},它是系统的核心类之一
     * @param executeContext
     * @return
     */
    SQLExecutor buildExecutor(ExecuteContext executeContext);


    MetadataManager initMetadataManager(ConnectionSource cs);

    MetadataManager initMetadataManager(ConnectionSource cs, String defaultSchema, String defaultCatalog);

    /**
     * 初始化dbSt
     * @param sqlTemplateEngine
     * @param ps
     */
    void init(SQLTemplateEngine sqlTemplateEngine, Properties ps);

    /**
     * 通过jdbc connection可以得到 schema和catalog，但可能低版本驱动不支持，这里提供数据库默认的
     * @return
     */
    String getDefaultSchema();

    void setOffsetStartZero(boolean offsetStartZero);

    SQLTemplateEngine getSQLTemplateEngine();

    /**
     * 在SQLManager配置好后，会调用此方法，最后对sqlmanager进行修改配置
     *
     * @param sqlManager
     * @see org.beetl.sql.core.nosql.ClickHouseStyle
     */
    void config(SQLManager sqlManager);


}
