func (oracle OracleSQLDialecter) ParametersSql(name string) string {
	return fmt.Sprintf(`
select distinct
	ARGUMENT_NAME as name, POSITION as position, 
  	IN_OUT as dirmode, 
  	DATA_TYPE as datatype, 
  	COALESCE(CHAR_LENGTH,0) as length, 
  	COALESCE(DATA_PRECISION,0) as precision, 
  	COALESCE(DATA_SCALE,0) as scale 
from 
	ALL_ARGUMENTS
where
	DATA_LEVEL = 0 AND OBJECT_NAME = '%s' AND OWNER = (select sys_context('USERENV','SESSION_USER') from dual)
order by 
	POSITION 
`, name)
}
Parameters return sql to query procedure paramters schema
package kdb
import (
	"bytes"
	"database/sql"
	"errors"
	"fmt"
	"github.com/sdming/kdb/ansi"
	"reflect"
	"strconv"
	"strings"
)
type Driver interface {
	Compiler
}
type Compiler interface {
	Compile(source string, exp Expression) (query string, args []interface{}, err error)
}
var _compilers = make(map[string]Compiler)
func RegisterCompiler(driver string, compiler Compiler) {
	if compiler == nil {
		panic("register compiler is nil")
	}
	_compilers[driver] = compiler
}
func GetCompiler(driver string) (Compiler, error) {
	c, ok := _compilers[driver]
	if !ok {
		return nil, errors.New(fmt.Sprint("can not get compiler:", driver))
	}
	return c, nil
}
type Schemaer interface {
	Table(db *sql.DB, name string) (*ansi.DbTable, error)
	Function(db *sql.DB, name string) (*ansi.DbFunction, error)
}
var _schemaers = make(map[string]Schemaer)
func RegisterSchemaer(driver string, schemaer Schemaer) {
	if schemaer == nil {
		panic("register schemaer is nil")
	}
	_schemaers[driver] = schemaer
}
func GetSchemaer(driver string) (Schemaer, error) {
	schema, ok := _schemaers[driver]
	if !ok {
		return nil, errors.New(fmt.Sprint("can not get schemaer:", driver))
	}
	return schema, nil
}
type Dialecter interface {
	Name() string
	SupportNamedParameter() bool
	SupportIndexedParameter() bool
	ParameterPlaceHolder() string
	QuoteString(s string) string
	Quote(string) string
	TableSql(name string) string
	ColumnsSql(name string) string
	FunctionSql(name string) string
	ParametersSql(name string) string
	DbType(nativeType string) ansi.DbType
	SplitStatement() string
}
var _dialecters = make(map[string]Dialecter)
func RegisterDialecter(driver string, dialecter Dialecter) {
	if dialecter == nil {
		panic("register dialecter is nil")
	}
	_dialecters[driver] = dialecter
}
func GetDialecter(driver string) (Dialecter, error) {
	d, ok := _dialecters[driver]
	if !ok {
		return nil, errors.New(fmt.Sprint("can not get dialecter:", driver))
	}
	return d, nil
}
func DefaultDialecter() Dialecter {
	return AnsiDialecter{}
}
type AnsiDialecter struct {
}
func (ad AnsiDialecter) Name() string {
	return "ansi"
}
func (ad AnsiDialecter) SupportNamedParameter() bool {
	return false
}
func (ad AnsiDialecter) SupportIndexedParameter() bool {
	return false
}
func (ad AnsiDialecter) ParameterPlaceHolder() string {
	return " ? "
}
func (ad AnsiDialecter) QuoteString(s string) string {
	return "'" + s + "'"
}
func (ad AnsiDialecter) Quote(s string) string {
	return "\"" + s + "\""
}
func (ansi AnsiDialecter) TableSql(name string) string {
	return ""
}
func (ansi AnsiDialecter) ColumnsSql(name string) string {
	return ""
}
func (ad AnsiDialecter) FunctionSql(s string) string {
	return ""
}
func (ad AnsiDialecter) ParametersSql(name string) string {
	return ""
}
func (ad AnsiDialecter) SplitStatement() string {
	return " ; "
}
func (ad AnsiDialecter) DbType(nativeType string) ansi.DbType {
	switch strings.ToLower(nativeType) {
	case "xml", "tinytext", "mediumtext", "longtext", "ntext", "text", "sysname", "sql_variant", "note", "memo", "clob":
		return ansi.String
	case "char", "character", "nchar", "varchar", "nvarchar", "string", "longvarchar", "longchar", "varyingcharacter":
		return ansi.String
	case "nativecharacter", "native character", "nativevaryingcharacter", "character varying":
		return ansi.String
	case "bit", "bool", "boolean", "yesno", "logical":
		return ansi.Boolean
	case "tinyint unsigned", "uint16", "smallint unsigned", "uint32", "integer unsigned", "uint64", "bigint unsigned", "unsigned, bigint", "int2", "int8":
		return ansi.Int
	case "tinyint", "smallint", "int", "mediumint", "bigint", "int16", "int32", "int64", "integer", "long":
		return ansi.Int
	case "bigserial", "serial", "smallserial":
		return ansi.Int
	case "identity", "counter", "autoincrement":
		return ansi.Int
	case "decimal", "newdecimal", "numeric":
		return ansi.Numeric
	case "currency", "money", "smallmoney":
		return ansi.Numeric
	case "float", "real", "double", "double precision":
		return ansi.Float
	case "date", "smalldate":
		return ansi.Date
	case "time", "datetime", "datetime2", "smalldatetime", "timestamp", "timestamp without time zone", "timestamp with time zone":
		return ansi.DateTime
	case "year":
		return ansi.Int
	case "image", "varbinary", "binary", "blob", "tinyblob", "mediumblob", "longblob", "oleobject", "general", "bit varying", "bytea":
		return ansi.Bytes
	case "uniqueidentifier", "guid", "uuid":
		return ansi.Guid
	default:
		return ansi.Var
	}
	return ansi.Var
}
type SqliteDialecter struct {
	AnsiDialecter
}
func (sqlite SqliteDialecter) Name() string {
	return "sqlite"
}
func (sqlite SqliteDialecter) Table(db *sql.DB, name string) (table *ansi.DbTable, err error) {
	query := fmt.Sprintf(`SELECT name, type FROM sqlite_master WHERE name = '%s'; `, name)
	var rows *sql.Rows
	if rows, err = db.Query(query); err != nil {
		return
	}
	var t *ansi.DbTable
	for rows.Next() {
		tt := ansi.NewTable()
		if err = rows.Scan(&tt.Name, &tt.Type); err != nil {
		} else {
			t = tt
		}
	}
	if err = rows.Err(); err != nil {
		return
	}
	if t == nil {
		err = errors.New("table doesn't exist:" + name)
		return
	}
	query = fmt.Sprintf("PRAGMA table_info(%s)", t.Name)
	if rows, err = db.Query(query); err != nil {
		return
	}
	for rows.Next() {
		col := ansi.DbColumn{}
		var dflt sql.NullString
		if err = rows.Scan(&col.Position, &col.Name, &col.NativeType, &col.IsNullable, &dflt, &col.IsPrimaryKey); err != nil {
		} else {
			col.DbType = sqlite.DbType(col.NativeType)
			col.IsNullable = col.IsNullable == false
			t.Columns = append(t.Columns, col)
		}
	}
	if err = rows.Err(); err != nil {
		return
	}
	table = t
	return
}
func (sqlite SqliteDialecter) Function(db *sql.DB, name string) (*ansi.DbFunction, error) {
	return nil, errors.New("sqlite doesn't support store procedure")
}
type MssqlDialecter struct {
	AnsiDialecter
}
func (mssql MssqlDialecter) Name() string {
	return "mssql"
}
func (mssql MssqlDialecter) Quote(s string) string {
	return "[" + s + "]"
}
func (mssql MssqlDialecter) TableSql(name string) string {
	return fmt.Sprintf("SELECT TABLE_CATALOG AS [catalog], TABLE_SCHEMA AS [schema], TABLE_NAME AS [name], TABLE_TYPE AS [type] FROM information_schema.[TABLES] WHERE TABLE_NAME = '%s' ", name)
}
func (mssql MssqlDialecter) ColumnsSql(name string) string {
	return fmt.Sprintf(`
SELECT 
	isc.COLUMN_NAME AS [name], isc.[ORDINAL_POSITION] AS [position], CASE isc.[IS_NULLABLE] WHEN 'YES' THEN 1 ELSE 0 END as [nullable], isc.[DATA_TYPE] AS [datatype], 
	ISNULL(isc.[CHARACTER_MAXIMUM_LENGTH],0) AS [length], ISNULL(isc.[NUMERIC_PRECISION],0) AS [precision], ISNULL(isc.[NUMERIC_SCALE],0) AS [scale],
	c.is_identity as [autoincrement],
	CASE WHEN (c.is_identity = 1 or c.is_computed = 1) THEN 1 else 0 end as [readonly],
	ISNULL(ict.primarykey,0) AS [primarykey]
FROM 
	[INFORMATION_SCHEMA].[COLUMNS] isc
	INNER JOIN sys.columns c on c.object_id = object_id(isc.table_name) AND c.name = isc.COLUMN_NAME
	LEFT JOIN
	(
			SELECT ic.column_id, 1 primarykey
			FROM sys.indexes i
			INNER JOIN  sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id 
			where i.object_id = object_id('%s') and i.is_primary_key = 1
	) AS ict on c.column_id = ict.column_id
WHERE 
	isc.table_name = '%s' AND c.object_id = object_id('%s')
ORDER BY
	isc.[ORDINAL_POSITION] ;
`, name, name, name)
}
func (mssql MssqlDialecter) FunctionSql(name string) string {
	return fmt.Sprintf("SELECT ROUTINE_CATALOG AS [catalog], ROUTINE_SCHEMA AS [schema], ROUTINE_NAME as [name] FROM information_schema.ROUTINES WHERE ROUTINE_NAME = '%s' ;", name)
}
func (mssql MssqlDialecter) ParametersSql(name string) string {
	return fmt.Sprintf("SELECT Substring(PARAMETER_NAME,2,len(PARAMETER_NAME)-1) as [name], ORDINAL_POSITION as [position], PARAMETER_MODE as [dirmode], DATA_TYPE as [datatype],ISNULL(CHARACTER_MAXIMUM_LENGTH,0) as [length], ISNULL(NUMERIC_PRECISION,0) as [precision], ISNULL(NUMERIC_SCALE,0) as [scale] FROM information_schema.PARAMETERS WHERE SPECIFIC_NAME = '%s' ORDER BY ORDINAL_POSITION", name)
}
type MysqlDialecter struct {
	AnsiDialecter
}
func (mysql MysqlDialecter) Name() string {
	return "mysql"
}
func (mysql MysqlDialecter) QuoteString(s string) string {
	return "\"" + s + "\""
}
func (mysql MysqlDialecter) Quote(s string) string {
	return "'" + s + "'"
}
func (mysql MysqlDialecter) TableSql(name string) string {
	return fmt.Sprintf("SELECT TABLE_CATALOG AS `catalog`, TABLE_SCHEMA AS `schema`, TABLE_NAME AS `name`, TABLE_TYPE AS `type` FROM information_schema.`TABLES` WHERE TABLE_NAME = '%s' AND TABLE_SCHEMA= DATABASE() ", name)
}
func (mysql MysqlDialecter) ColumnsSql(name string) string {
	return fmt.Sprintf("SELECT COLUMN_NAME as `name`, ORDINAL_POSITION as `position`, CASE IS_NULLABLE WHEN 'YES' THEN TRUE ELSE FALSE END as `nullable`, DATA_TYPE as `datatype`, IFNULL(CHARACTER_MAXIMUM_LENGTH,0) as `length`, IFNULL(NUMERIC_PRECISION,0) as `precision`, IFNULL(NUMERIC_SCALE,0) as `scale`, CASE WHEN EXTRA LIKE '%%auto_increment%%' THEN TRUE ELSE FALSE END AS `autoincrement`, CASE WHEN EXTRA LIKE '%%auto_increment%%' THEN TRUE ELSE FALSE END AS `readonly`, CASE WHEN COLUMN_KEY = 'PRI' THEN TRUE ELSE FALSE END AS `primarykey` FROM information_schema.COLUMNS WHERE TABLE_NAME = '%s' and TABLE_SCHEMA= DATABASE() ORDER BY ORDINAL_POSITION ;", name)
}
func (mysql MysqlDialecter) FunctionSql(name string) string {
	return fmt.Sprintf("SELECT  ROUTINE_CATALOG AS `catalog`, ROUTINE_SCHEMA AS `schema`, ROUTINE_NAME as `name` FROM information_schema.ROUTINES WHERE ROUTINE_NAME = '%s' AND ROUTINE_SCHEMA = DATABASE(); ", name)
}
func (mysql MysqlDialecter) ParametersSql(name string) string {
	return fmt.Sprintf("SELECT PARAMETER_NAME as `name`, ORDINAL_POSITION as `position`, PARAMETER_MODE as `dirmode`, DATA_TYPE as `datatype`, IFNULL(CHARACTER_MAXIMUM_LENGTH,0) as `length`, IFNULL(NUMERIC_PRECISION,0) as `precision`, IFNULL(NUMERIC_SCALE,0) as `scale` FROM information_schema.PARAMETERS WHERE SPECIFIC_NAME = '%s' and SPECIFIC_SCHEMA = DATABASE() ORDER BY ORDINAL_POSITION", name)
}
type PostgreSQLDialecter struct {
	AnsiDialecter
}
func (pgsql PostgreSQLDialecter) Name() string {
	return "postgres"
}
func (pgsql PostgreSQLDialecter) SupportIndexedParameter() bool {
	return true
}
func (pgsql PostgreSQLDialecter) ParameterPlaceHolder() string {
	return "$"
}
func (pgsql PostgreSQLDialecter) QuoteString(s string) string {
	return "'" + s + "'"
}
func (pgsql PostgreSQLDialecter) Quote(s string) string {
	return "\"" + s + "\""
}
func (pgsql PostgreSQLDialecter) TableSql(name string) string {
	return fmt.Sprintf(`
select 
	table_catalog as "catalog", 
	table_schema as "schema", 
	table_name as "name", 
	table_type as "type" 
from 
	information_schema.tables 
where 
	table_name = '%s' 
	and table_schema = current_schema() 
	and table_schema not in ('pg_catalog', 'information_schema'); `, name)
}
func (pgsql PostgreSQLDialecter) ColumnsSql(name string) string {
	return fmt.Sprintf(`
select 
	column_name as "name", 
	ordinal_position as "position", 
	case is_nullable when 'YES' then true else false end as "nullable", 
	data_type as "datatype",
	COALESCE(character_maximum_length,0) as "length", 
	COALESCE(numeric_precision,0) as "precision", 
	COALESCE(numeric_scale,0) as "scale",
	case when pg_get_serial_sequence(table_name, column_name) is null then false else true end as "autoincrement",
	case is_updatable when 'YES' then false else true end as "readonly",
	case when exists (
		select 
			kc.column_name 
		from  
			information_schema.table_constraints tc,  
			information_schema.key_column_usage kc  
		where 
			kc.table_name = c.table_name and kc.table_schema =c.table_schema and kc.column_name = c.column_name
			and tc.constraint_type = 'PRIMARY KEY' 
			and kc.table_name = tc.table_name and kc.table_schema = tc.table_schema and kc.constraint_name = tc.constraint_name
	) then true else false end as "primarykey"
 from 
	information_schema.columns  c
 where 
	table_name = '%s' 
	and table_schema = current_schema()
 order by 
	ordinal_position ;
`, name)
}
func (pgsql PostgreSQLDialecter) FunctionSql(name string) string {
	return fmt.Sprintf(`select routine_catalog as "catalog", routine_schema as "schema", routine_name as "name" from information_schema.routines where routine_name = '%s' and routine_schema = current_schema() ;`, name)
}
func (pgsql PostgreSQLDialecter) ParametersSql(name string) string {
	return fmt.Sprintf(`
select 
	p.parameter_name as "name", p.ordinal_position as "position", p.parameter_mode as "dirmode", p.data_type as "datatype", COALESCE(p.character_maximum_length,0) as "length", COALESCE(p.numeric_precision,0) as "precision", COALESCE(p.numeric_scale,0) as "scale" 
from 
	information_schema.parameters p,
	information_schema.routines r
where
	p.specific_catalog = r.specific_catalog and p.specific_schema = r. specific_schema and p.specific_name = r.specific_name
	and r.routine_name = '%s' and r.routine_schema = current_schema()
order by 
	ordinal_position ;
`, name)
}
type OracleSQLDialecter struct {
	AnsiDialecter
}
func (oracle OracleSQLDialecter) Name() string {
	return "oracle"
}
func (oracle OracleSQLDialecter) ParameterPlaceHolder() string {
	return ":"
}
func (oracle OracleSQLDialecter) SupportNamedParameter() bool {
	return true
}
func (oracle OracleSQLDialecter) SupportIndexedParameter() bool {
	return true
}
func (oracle OracleSQLDialecter) Quote(s string) string {
	return s
}
func (oracle OracleSQLDialecter) TableSql(name string) string {
	return fmt.Sprintf(`
select
	TABLESPACE_NAME as catalog,
	TABLESPACE_NAME as schema, 
	TABLE_NAME as name, 
	DECODE(TABLESPACE_NAME, 'SYS', 'System', 'SYSTEM', 'System', 'SYSMAN', 'System','CTXSYS', 'System','MDSYS', 'System','OLAPSYS', 'System', 'ORDSYS', 'System','OUTLN', 'System', 'WKSYS', 'System','WMSYS', 'System','XDB', 'System','ORDPLUGINS', 'System','User') AS type
from 
	user_tables
where 
	TABLE_NAME = '%s' 
	`, name)
}
func (oracle OracleSQLDialecter) ColumnsSql(name string) string {
	return fmt.Sprintf(`
select
  	COLUMN_NAME as name, 
	COLUMN_ID as position, 
	case NULLABLE when 'Y' then '1'  else '0'  end as nullable, 
	DATA_TYPE as datatype,
	COALESCE(CHAR_LENGTH,0) as length, 
	COALESCE(DATA_PRECISION,0) as precision, 
	COALESCE(DATA_SCALE,0) as scale ,
	to_char(0)   as autoincrement,
	to_char(0)   as readonly,
	case when exists (
    select cc.COLUMN_NAME 
    from all_cons_columns cc inner join all_constraints cs  on cs.CONSTRAINT_NAME = cc.CONSTRAINT_NAME and cc.OWNER = cs.OWNER
    where cs.CONSTRAINT_TYPE = 'P' and cs.TABLE_NAME = '%s' and cc.COLUMN_NAME = c.COLUMN_NAME
	) then '1' else '0' end as primarykey
 from 
	user_tab_columns  c
 where 
	TABLE_NAME = '%s' 
 order by 
	COLUMN_ID 
`, name, name)
}
func (oracle OracleSQLDialecter) FunctionSql(name string) string {
	return fmt.Sprintf(`select distinct OWNER as catalog, OWNER as schema, OBJECT_NAME as name from all_procedures where OBJECT_NAME = '%s' and OWNER = (select sys_context('USERENV','SESSION_USER') from dual) `, name)
}