public bool QueryCount(Table table, WithEnums with, Dictionary <string, object> parms, out ulong count)
        {
            StringBuilder sb = new StringBuilder()
                               .Append("SELECT COUNT(*) AS '_ROW_COUNT_' FROM ")
                               .Append(ProcessTableName(table.SourceName, table.SourceSchema, with));

            if (!string.IsNullOrEmpty(table.WhereSQL))
            {
                if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                {
                    sb.Append(" WHERE");
                }
                sb.Append($" {table.WhereSQL}");
            }

            count = 0;
            if (Query(sb.ToString(), parms, out IDataWrapper data))
            {
                try
                {
                    if (data.Read())
                    {
                        count = ulong.Parse(data.GetValue(0).ToString());
                    }

                    return(true);
                }
                finally
                {
                    data.Close();
                }
            }
            else
            {
                return(false);
            }
        }
        public bool QueryPage(Table table, uint fromRow, uint toRow, WithEnums with, Dictionary <string, object> parms, out IDataWrapper reader)
        {
            StringBuilder sb = new StringBuilder();

            // 如果存在主键:
            // SELECT <B.fieldsSQL> FROM <tableName> B JOIN (SELECT <keyFields> FROM
            // (SELECT <keyFields>, ROW_NUMBER() OVER (ORDER BY <orderSQL>) AS "_RowNum_"
            // FROM <tableName>
            // {WHERE <whereSQL>}
            // ) A WHERE "_RowNum_" BETWEEN <fromRow> AND <toRow>) A ON <B.keyFields> = <A.keyFields>
            if (table.KeyFields.Length > 0)
            {
                string fieldsSQL          = ProcessFieldNames(table.SourceFields, "B");
                string tableName          = ProcessTableName(table.SourceName, table.SourceSchema);
                string tableNameWithB     = ProcessTableName(table.SourceName, table.SourceSchema, "B");
                string keyFields          = ProcessFieldNames(table.KeyFields);
                string keyFieldsWithAlias = ProcessFieldNames(table.KeyFields, ProcessTableName(table.SourceName, table.SourceSchema));
                string keyField           = ProcessFieldName(table.KeyFields[0]);

                sb.Append($"SELECT {fieldsSQL} FROM {tableNameWithB} JOIN (SELECT {keyFields} FROM")
                .Append($" (SELECT {keyFieldsWithAlias}, ROW_NUMBER() OVER (ORDER BY {table.OrderSQL})")
                .Append($" AS \"_RowNum_\" FROM {tableName}");
                if (!string.IsNullOrEmpty(table.WhereSQL))
                {
                    if (table.WhereSQL.IndexOf(" WEHRE ", StringComparison.OrdinalIgnoreCase) < 0)
                    {
                        sb.Append(" WHERE");
                    }
                    sb.Append($" {table.WhereSQL}");
                }
                sb.Append($") A WHERE A.\"_RowNum_\" BETWEEN {fromRow} AND {toRow}) A ON B.{keyField} = A.{keyField}");
                for (int i = 1; i < table.KeyFields.Length; i++)
                {
                    keyField = ProcessFieldName(table.KeyFields[i]);
                    sb.Append($" AND B.{keyField} = A.{keyField}");
                }

                return(Query(sb.ToString(), parms, out reader));
            }
            else
            {
                // 语法格式形如:
                // SELECT <fieldsSQL> FROM (SELECT ROW_NUMBER() OVER (ORDER BY <orderSQL>)
                // AS "_RowNum_", <fieldsSQL> FROM <tableName>
                // {WHERE <whereSQL>}
                // ) A WHERE A."_RowNum_" BETWEEN <fromRow> AND <toRow>
                string fieldsSQL       = ProcessFieldNames(table.SourceFields);
                string fieldsWithAlias = ProcessFieldNames(table.SourceFields, ProcessTableName(table.SourceName, table.SourceSchema));

                sb.Append($"SELECT {fieldsSQL} FROM (SELECT ROW_NUMBER() OVER (ORDER BY {table.OrderSQL})")
                .Append($" AS \"_RowNum_\", {fieldsWithAlias} FROM {ProcessTableName(table.SourceName, table.SourceSchema)}");
                if (!string.IsNullOrEmpty(table.WhereSQL))
                {
                    if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                    {
                        sb.Append(" WHERE");
                    }
                    sb.Append($" {table.WhereSQL}");
                }
                sb.Append($") A WHERE A.\"_RowNum_\" BETWEEN {fromRow} AND {toRow}");

                return(Query(sb.ToString(), parms, out reader));
            }
        }
        public bool QueryPage(Table table, uint fromRow, uint toRow, WithEnums with, Dictionary <string, object> parms, out IDataWrapper reader)
        {
            StringBuilder sb = new StringBuilder();

            // 如果主键字段只有一个:
            // SELECT <fieldsSQL> FROM <tableName> WHERE ROWNUM <= <toRow - fromRow + 1>
            // { AND <keyField> > @LastMaxKey}{ AND {<whereSQL>}} ORDER BY <keyField> ASC
            // 其中
            // @LastMaxKey = SELECT MAX(<keyField>) AS "_MaxKey_" FROM (
            // SELECT <keyField> FROM <tableName> WHERE ROWNUM <= <toRow - fromRow + 1>
            // { AND <keyField> > @LastMaxKey}{ AND {<whereSQL>}} ORDER BY <keyField> ASC
            if (table.KeyFields.Length == 1)
            {
                string tableName          = ProcessTableName(table.SourceName, table.SourceSchema);
                string keyField           = ProcessFieldName(table.KeyFields[0]);
                string keyFieldWithPrefix = ProcessFieldName(table.KeyFields[0], ProcessTableName(table.SourceName, table.SourceSchema));

                // 查询最大键值
                sb.Append($"SELECT MAX({keyField}) AS \"_MaxKey_\" FROM (")
                .Append($"SELECT {keyFieldWithPrefix} FROM {tableName}");
                if (!string.IsNullOrEmpty(table.WhereSQL))
                {
                    if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                    {
                        sb.Append(" WHERE");
                    }
                    sb.Append(" ").Append(table.WhereSQL);
                    if (parms.ContainsKey("LastMaxKey"))
                    {
                        sb.Append($" AND {keyFieldWithPrefix} > @LastMaxKey");
                    }
                    sb.Append(" AND");
                }
                else if (parms.ContainsKey("LastMaxKey"))
                {
                    sb.Append($" WHERE {keyFieldWithPrefix} > @LastMaxKey AND");
                }
                else
                {
                    sb.Append(" WHERE");
                }
                sb.Append($" ROWNUM <= {toRow - fromRow + 1} ORDER BY {keyFieldWithPrefix} ASC) A");

                if (QueryMaxKey(sb.ToString(), parms, out object maxValue))
                {
                    string fieldsSQL = ProcessFieldNames(table.SourceFields, ProcessTableName(table.SourceName, table.SourceSchema));

                    sb.Length = 0;
                    sb.Append($"SELECT {fieldsSQL} FROM {tableName}");
                    if (!string.IsNullOrEmpty(table.WhereSQL))
                    {
                        if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                        {
                            sb.Append(" WHERE");
                        }
                        sb.Append(" ").Append(table.WhereSQL);
                        if (parms.ContainsKey("LastMaxKey"))
                        {
                            sb.Append($" AND {keyFieldWithPrefix} > @LastMaxKey");
                        }
                        sb.Append(" AND");
                    }
                    else if (parms.ContainsKey("LastMaxKey"))
                    {
                        sb.Append($" WHERE {keyFieldWithPrefix} > @LastMaxKey AND");
                    }
                    else
                    {
                        sb.Append(" WHERE");
                    }
                    sb.Append($" ROWNUM <= {toRow - fromRow + 1} ORDER BY {keyFieldWithPrefix} ASC");

                    bool rst = Query(sb.ToString(), parms, out reader);

                    parms["LastMaxKey"] = maxValue;

                    return(rst);
                }
                else
                {
                    reader = null;

                    return(false);
                }
            }
            // 如果存在复合主键:
            // SELECT <B.fieldsSQL> FROM <tableName> B JOIN (SELECT <keyFields> FROM
            // (SELECT <keyFields>, ROW_NUMBER() OVER (ORDER BY <orderSQL>) AS "_RowNum_"
            // FROM <tableName>
            // {WHERE <whereSQL>}
            // ) A WHERE "_RowNum_" BETWEEN <fromRow> AND <toRow>) A ON <B.keyFields> = <A.keyFields>
            else if (table.KeyFields.Length > 1)
            {
                string fieldsSQL          = ProcessFieldNames(table.SourceFields, "B");
                string tableName          = ProcessTableName(table.SourceName, table.SourceSchema);
                string tableNameWithB     = ProcessTableName(table.SourceName, table.SourceSchema, "B");
                string keyFields          = ProcessFieldNames(table.KeyFields);
                string keyFieldsWithAlias = ProcessFieldNames(table.KeyFields, ProcessTableName(table.SourceName, table.SourceSchema));
                string keyField           = ProcessFieldName(table.KeyFields[0]);

                sb.Append($"SELECT {fieldsSQL} FROM {tableNameWithB} JOIN (SELECT {keyFields} FROM")
                .Append($" (SELECT {keyFieldsWithAlias}, ROW_NUMBER() OVER (ORDER BY {table.OrderSQL})")
                .Append($" AS \"_RowNum_\" FROM {tableName}");
                if (!string.IsNullOrEmpty(table.WhereSQL))
                {
                    if (table.WhereSQL.IndexOf(" WEHRE ", StringComparison.OrdinalIgnoreCase) < 0)
                    {
                        sb.Append(" WHERE");
                    }
                    sb.Append($" {table.WhereSQL}");
                }
                sb.Append($") A WHERE A.\"_RowNum_\" BETWEEN {fromRow} AND {toRow}) A ON B.{keyField} = A.{keyField}");
                for (int i = 1; i < table.KeyFields.Length; i++)
                {
                    keyField = ProcessFieldName(table.KeyFields[i]);
                    sb.Append($" AND B.{keyField} = A.{keyField}");
                }

                return(Query(sb.ToString(), parms, out reader));
            }
            else
            {
                // 语法格式形如:
                // SELECT <fieldsSQL> FROM (SELECT ROW_NUMBER() OVER (ORDER BY <orderSQL>)
                // AS "_RowNum_", <fieldsSQL> FROM <tableName>
                // {WHERE <whereSQL>}
                // ) A WHERE A."_RowNum_" BETWEEN <fromRow> AND <toRow>
                string fieldsSQL       = ProcessFieldNames(table.SourceFields);
                string fieldsWithAlias = ProcessFieldNames(table.SourceFields, ProcessTableName(table.SourceName, table.SourceSchema));

                sb.Append($"SELECT {fieldsSQL} FROM (SELECT ROW_NUMBER() OVER (ORDER BY {table.OrderSQL})")
                .Append($" AS \"_RowNum_\", {fieldsWithAlias} FROM {ProcessTableName(table.SourceName, table.SourceSchema)}");
                if (!string.IsNullOrEmpty(table.WhereSQL))
                {
                    if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                    {
                        sb.Append(" WHERE");
                    }
                    sb.Append($" {table.WhereSQL}");
                }
                sb.Append($") A WHERE A.\"_RowNum_\" BETWEEN {fromRow} AND {toRow}");

                return(Query(sb.ToString(), parms, out reader));
            }
        }
        public bool QueryPage(Table table, uint fromRow, uint toRow, WithEnums with, Dictionary <string, object> parms,
                              out IDataWrapper reader)
        {
            StringBuilder sb        = new StringBuilder();
            string        tableName = ProcessTableName(table.SourceName, table.SourceSchema);

            // 语法格式形如:
            // SELECT <fieldsSQL> FROM <tableName> {WHERE <whereSQL>}
            // {ORDER BY <orderSQL>} LIMIT <fromRow - 1>, <toRow - fromRow + 1>
            //
            // 如果存在主键,可以优化为:
            // SELECT <A.fieldsSQL> FROM <tableName> A JOIN (SELECT <keyFields> FROM <tableName> {WHERE <whereSQL>}
            // {ORDER BY <orderSQL>} LIMIT <fromRow - 1>, <toRow - fromRow + 1>) B ON <A.keyFields> = <B.keyFields>
            //
            // 如果主键字段只有一个,可以进一步优化为:
            // SELECT <fieldsSQL> FROM <tableName> {WHERE {<keyField> > @LastMaxKey} {AND {<whereSQL>}}}
            // ORDER BY <keyField> ASC LIMIT <toRow - fromRow + 1>
            // 其中
            // @LastMaxKey = SELECT MAX(<keyField>) AS '_MaxKey_' FROM (SELECT <keyField> FROM <tableName>
            // {WHERE {<keyField> > @LastMaxKey} {AND {<whereSQL>}}} ORDER BY <keyField> ASC
            // LIMIT <toRow - fromRow + 1>) A
            if (table.KeyFields.Length == 1)
            {
                string keyField           = ProcessFieldName(table.KeyFields[0]);
                string keyFieldWithPrefix = ProcessFieldName(table.KeyFields[0], tableName);

                // 查询最大键值
                sb.Append($"SELECT MAX({keyField}) AS '_MaxKey_' FROM (SELECT {keyFieldWithPrefix} FROM {tableName}");
                if (!string.IsNullOrEmpty(table.WhereSQL))
                {
                    if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                    {
                        sb.Append(" WHERE");
                    }
                    sb.Append(" ").Append(table.WhereSQL);
                    if (parms.ContainsKey("LastMaxKey"))
                    {
                        sb.Append($" AND {keyFieldWithPrefix} > @LastMaxKey");
                    }
                }
                else if (parms.ContainsKey("LastMaxKey"))
                {
                    sb.Append($" WHERE {keyFieldWithPrefix} > @LastMaxKey");
                }
                sb.Append($" ORDER BY {keyFieldWithPrefix} LIMIT {toRow - fromRow + 1}) A");

                if (QueryMaxKey(sb.ToString(), parms, out object maxValue))
                {
                    string fieldsSQL = ProcessFieldNames(table.SourceFields, tableName);

                    sb.Length = 0;
                    sb.Append($"SELECT {fieldsSQL} FROM {tableName}");
                    if (!string.IsNullOrEmpty(table.WhereSQL))
                    {
                        if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                        {
                            sb.Append(" WHERE");
                        }
                        sb.Append(" ").Append(table.WhereSQL);
                        if (parms.ContainsKey("LastMaxKey"))
                        {
                            sb.Append($" AND {keyFieldWithPrefix} > @LastMaxKey");
                        }
                    }
                    else if (parms.ContainsKey("LastMaxKey"))
                    {
                        sb.Append($" WHERE {keyFieldWithPrefix} > @LastMaxKey");
                    }
                    sb.Append($" ORDER BY {keyFieldWithPrefix} LIMIT {toRow - fromRow + 1}");

                    bool rst = Query(sb.ToString(), parms, out reader);

                    parms["LastMaxKey"] = maxValue;

                    return(rst);
                }
                else
                {
                    reader = null;

                    return(false);
                }
            }
            else
            {
                if (table.KeyFields.Length > 0)
                {
                    string fieldsSQL = ProcessFieldNames(table.SourceFields, "A");
                    string keyField  = ProcessFieldName(table.KeyFields[0]);
                    string keyFields = ProcessFieldNames(table.KeyFields, tableName);

                    sb.Append($"SELECT {fieldsSQL} FROM {tableName} A JOIN (SELECT {keyFields} FROM {tableName}");
                    if (!string.IsNullOrEmpty(table.WhereSQL))
                    {
                        if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                        {
                            sb.Append(" WHERE");
                        }
                        sb.Append($" {table.WhereSQL}");
                    }
                    if (!string.IsNullOrEmpty(table.OrderSQL))
                    {
                        sb.Append(" ORDER BY ").Append(table.OrderSQL);
                    }
                    sb.Append($" LIMIT {fromRow - 1}, {toRow - fromRow + 1}) B ON A.{keyField} = B.{keyField}");
                    for (int i = 1; i < table.KeyFields.Length; i++)
                    {
                        keyField = ProcessFieldName(table.KeyFields[i]);
                        sb.Append($" AND A.{keyField} = B.{keyField}");
                    }
                }
                else
                {
                    string fieldsSQL = ProcessFieldNames(table.SourceFields, tableName);

                    sb.Append($"SELECT {fieldsSQL} FROM {tableName}");
                    if (!string.IsNullOrEmpty(table.WhereSQL))
                    {
                        if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                        {
                            sb.Append(" WHERE");
                        }
                        sb.Append($" {table.WhereSQL}");
                    }
                    if (!string.IsNullOrEmpty(table.OrderSQL))
                    {
                        sb.Append(" ORDER BY ").Append(table.OrderSQL);
                    }
                    sb.Append($" LIMIT {fromRow - 1}, {toRow - fromRow + 1}");
                }

                return(Query(sb.ToString(), parms, out reader));
            }
        }
        public bool QueryPage(Table table, uint fromRow, uint toRow, WithEnums with, Dictionary <string, object> parms,
                              out IDataWrapper reader)
        {
            StringBuilder sb = new StringBuilder();

            // 如果主键字段只有一个:
            // SELECT TOP <toRow - fromRow + 1> <fieldsSQL> FROM <tableName>
            // {WHERE {<keyField> > @LastMaxKey} {AND {<whereSQL>}}} ORDER BY <keyField> ASC
            // 其中
            // @LastMaxKey = SELECT MAX(<keyField>) AS '_MaxKey_' FROM (
            // SELECT TOP <toRow - fromRow + 1> <keyField> FROM <tableName>
            // {WHERE {<keyField> > @LastMaxKey} {AND {<whereSQL>}}} ORDER BY <keyField> ASC
            if (table.KeyFields.Length == 1)
            {
                string tableName          = ProcessTableName(table.SourceName, table.SourceSchema, with);
                string keyField           = ProcessFieldName(table.KeyFields[0]);
                string keyFieldWithPrefix = ProcessFieldName(table.KeyFields[0],
                                                             ProcessTableName(table.SourceName, table.SourceSchema));

                // 查询最大键值
                sb.Append($"SELECT MAX({keyField}) AS '_MaxKey_' FROM (")
                .Append($"SELECT TOP {toRow - fromRow + 1} {keyFieldWithPrefix} FROM {tableName}");
                if (!string.IsNullOrEmpty(table.WhereSQL))
                {
                    if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                    {
                        sb.Append(" WHERE");
                    }
                    sb.Append(" ").Append(table.WhereSQL);
                    if (parms.ContainsKey("LastMaxKey"))
                    {
                        sb.Append($" AND {keyFieldWithPrefix} > @LastMaxKey");
                    }
                }
                else if (parms.ContainsKey("LastMaxKey"))
                {
                    sb.Append($" WHERE {keyFieldWithPrefix} > @LastMaxKey");
                }
                sb.Append($" ORDER BY {keyFieldWithPrefix} ASC) A");

                if (QueryMaxKey(sb.ToString(), parms, out object maxValue))
                {
                    string fieldsSQL = ProcessFieldNames(table.SourceFields,
                                                         ProcessTableName(table.SourceName, table.SourceSchema));

                    sb.Length = 0;
                    sb.Append($"SELECT TOP {toRow - fromRow + 1} {fieldsSQL} FROM {tableName}");
                    if (!string.IsNullOrEmpty(table.WhereSQL))
                    {
                        if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                        {
                            sb.Append(" WHERE");
                        }
                        sb.Append(" ").Append(table.WhereSQL);
                        if (parms.ContainsKey("LastMaxKey"))
                        {
                            sb.Append($" AND {keyFieldWithPrefix} > @LastMaxKey");
                        }
                    }
                    else if (parms.ContainsKey("LastMaxKey"))
                    {
                        sb.Append($" WHERE {keyFieldWithPrefix} > @LastMaxKey");
                    }
                    sb.Append($" ORDER BY {keyFieldWithPrefix} ASC");

                    bool rst = Query(sb.ToString(), parms, out reader);

                    parms["LastMaxKey"] = maxValue;

                    return(rst);
                }
                else
                {
                    reader = null;

                    return(false);
                }
            }
            else if (Version.Parse(conn.ServerVersion).Major >= 10) // 2008 或更新版本
            {
                // 语法格式形如:
                // SELECT <fieldsSQL> FROM (SELECT ROW_NUMBER() OVER (ORDER BY <orderSQL>)
                // AS '_RowNum_', <fieldsSQL> FROM <tableName>
                // {WHERE <whereSQL>}
                // ) A WHERE A.[_RowNum_] BETWEEN <fromRow> AND <toRow>
                //
                // 如果存在主键,可以优化为:
                // SELECT <B.fieldsSQL> FROM <tableName> B JOIN (SELECT <keyFields> FROM
                // (SELECT <keyFields>, ROW_NUMBER() OVER (ORDER BY <orderSQL>) AS '_RowNum_'
                // FROM <tableName>
                // {WHERE <whereSQL>}
                // ) A WHERE [_RowNum_] BETWEEN <fromRow> AND <toRow>) A ON <B.keyFields> = <A.keyFields>
                if (table.KeyFields.Length > 1)
                {
                    string fieldsSQL          = ProcessFieldNames(table.SourceFields, "B");
                    string tableName          = ProcessTableName(table.SourceName, table.SourceSchema, with);
                    string tableNameWithB     = ProcessTableName(table.SourceName, table.SourceSchema, with, "B");
                    string keyFields          = ProcessFieldNames(table.KeyFields);
                    string keyFieldsWithAlias = ProcessFieldNames(table.KeyFields,
                                                                  ProcessTableName(table.SourceName, table.SourceSchema));
                    string keyField = ProcessFieldName(table.KeyFields[0]);

                    sb.Append($"SELECT {fieldsSQL} FROM {tableNameWithB} JOIN (SELECT {keyFields} FROM")
                    .Append($" (SELECT {keyFieldsWithAlias}, ROW_NUMBER() OVER (ORDER BY {table.OrderSQL})")
                    .Append($" AS '_RowNum_' FROM {tableName}");
                    if (!string.IsNullOrEmpty(table.WhereSQL))
                    {
                        if (table.WhereSQL.IndexOf(" WEHRE ", StringComparison.OrdinalIgnoreCase) < 0)
                        {
                            sb.Append(" WHERE");
                        }
                        sb.Append($" {table.WhereSQL}");
                    }
                    sb.Append($") A WHERE A.[_RowNum_] BETWEEN {fromRow} AND {toRow}) A ON B.{keyField} = A.{keyField}");
                    for (int i = 1; i < table.KeyFields.Length; i++)
                    {
                        keyField = ProcessFieldName(table.KeyFields[i]);
                        sb.Append($" AND B.{keyField} = A.{keyField}");
                    }
                }
                else
                {
                    string fieldsSQL       = ProcessFieldNames(table.SourceFields);
                    string fieldsWithAlias = ProcessFieldNames(table.SourceFields,
                                                               ProcessTableName(table.SourceName, table.SourceSchema));

                    sb.Append($"SELECT {fieldsSQL} FROM (SELECT ROW_NUMBER() OVER (ORDER BY {table.OrderSQL})")
                    .Append($" AS '_RowNum_', {fieldsWithAlias} FROM {ProcessTableName(table.SourceName, table.SourceSchema, with)}");
                    if (!string.IsNullOrEmpty(table.WhereSQL))
                    {
                        if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                        {
                            sb.Append(" WHERE");
                        }
                        sb.Append($" {table.WhereSQL}");
                    }
                    sb.Append($") A WHERE A.[_RowNum_] BETWEEN {fromRow} AND {toRow}");
                }
            }
            else
            {
                // 此语法要求 whereSQL、orderSQL 包含表名前缀,如:MyTable.KeyField ASC
                // SELECT TOP <toRow - fromRow + 1> <tableName.fieldsSQL> FROM <tableNameWith>
                // LEFT JOIN (SELECT TOP <fromRow - 1> <keyFieldsSQL> FROM <tableNameWith>
                // {WHERE <whereSQL>}
                // ORDER BY <orderSQL>) B ON
                // <tableName.keyFields> = <B.keyFields>
                // WHERE <B.keyFields[0]> IS NULL
                // {AND <whereSQL>}
                string tableName     = ProcessTableName(table.SourceName, table.SourceSchema);
                string tableNameWith = ProcessTableName(table.SourceName, table.SourceSchema, with);
                string fieldsSQL     = ProcessFieldNames(table.SourceFields, tableName);
                string keyFieldsSQL  = ProcessFieldNames(table.KeyFields);
                string keyField      = ProcessFieldName(table.KeyFields[0]);

                sb.Append($"SELECT TOP {toRow - fromRow + 1} {fieldsSQL} FROM {tableNameWith}")
                .Append($" LEFT JOIN (SELECT TOP {fromRow - 1} {keyFieldsSQL} FROM {tableNameWith}");
                if (!string.IsNullOrEmpty(table.WhereSQL))
                {
                    if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                    {
                        sb.Append(" WHERE");
                    }
                    sb.Append($" {table.WhereSQL}");
                }
                sb.Append($" ORDER BY {table.OrderSQL}) B ON ").Append($"{tableName}.{keyField} = B.{keyField}");
                for (int i = 1; i < table.KeyFields.Length; i++)
                {
                    keyField = ProcessFieldName(table.KeyFields[i]);
                    sb.Append($" AND {tableName}.{keyField} = B.{keyField}");
                }
                if (!string.IsNullOrEmpty(table.WhereSQL))
                {
                    if (table.WhereSQL.IndexOf(" WHERE ", StringComparison.OrdinalIgnoreCase) < 0)
                    {
                        sb.Append(" WHERE");
                    }
                    sb.Append($" {table.WhereSQL} AND B.{keyField} IS NULL");
                }
                else
                {
                    sb.Append($" WHERE B.{keyField} IS NULL");
                }
            }

            return(Query(sb.ToString(), parms, out reader));
        }
        public bool QueryPage(Table table, uint fromRow, uint toRow, WithEnums with, Dictionary <string, object> parms,
                              out IDataWrapper reader)
        {
            StringBuilder sb        = new StringBuilder();
            string        tableName = ProcessTableName(table.SourceName, table.SourceSchema);

            // 语法格式形如:
            // select <fieldsSQL> from <tableName> {where <whereSQL>}
            // {order by <orderSQL>} limit <toRow - fromRow + 1> offset <fromRow - 1>
            //
            // 如果存在主键,可以优化为:
            // select <A.fieldsSQL> from <tableName> A join (select <keyFields> from <tableName> {where <whereSQL>}
            // {order by <orderSQL>} limit <toRow - fromRow + 1> offset <fromRow - 1>) B on <A.keyFields> = <B.keyFields>
            //
            // 如果主键字段只有一个,可以进一步优化为:
            // select <fieldsSQL> from <tableName> {where {<keyField> > @LastMaxKey} {and {<whereSQL>}}
            // order by <keyField> asc limit <toRow - fromRow + 1>
            // 其中
            // @LastMaxKey = select max(<keyField>) as "_MaxKey_" from (select <keyField> from <tableName>
            // {where {<keyField> > @LastMaxKey} {and {<whereSQL>}}} order by <keyField> asc
            // limit <toRow - fromRow + 1>) A
            if (table.KeyFields.Length == 1)
            {
                string keyField           = ProcessFieldName(table.KeyFields[0]);
                string keyFieldWithPrefix = ProcessFieldName(table.KeyFields[0], tableName);

                // 查询最大键值
                sb.Append($"select max({keyField}) as \"_MaxKey_\" from (select {keyFieldWithPrefix} from {tableName}");
                if (!string.IsNullOrEmpty(table.WhereSQL))
                {
                    if (table.WhereSQL.IndexOf(" where ", StringComparison.OrdinalIgnoreCase) < 0)
                    {
                        sb.Append(" where");
                    }
                    sb.Append(" ").Append(table.WhereSQL);
                    if (parms.ContainsKey("LastMaxKey"))
                    {
                        sb.Append($" and {keyFieldWithPrefix} > @LastMaxKey");
                    }
                }
                else if (parms.ContainsKey("LastMaxKey"))
                {
                    sb.Append($" where {keyFieldWithPrefix} > @LastMaxKey");
                }
                sb.Append($" order by {keyField} limit {toRow - fromRow + 1}) A");

                if (QueryMaxKey(sb.ToString(), parms, out object maxValue))
                {
                    string fieldsSQL = ProcessFieldNames(table.SourceFields, tableName);

                    sb.Length = 0;
                    sb.Append($"select {fieldsSQL} from {tableName}");
                    if (!string.IsNullOrEmpty(table.WhereSQL))
                    {
                        if (table.WhereSQL.IndexOf(" where ", StringComparison.OrdinalIgnoreCase) < 0)
                        {
                            sb.Append(" where");
                        }
                        sb.Append(" ").Append(table.WhereSQL);
                        if (parms.ContainsKey("LastMaxKey"))
                        {
                            sb.Append($" and {keyFieldWithPrefix} > @LastMaxKey");
                        }
                    }
                    else if (parms.ContainsKey("LastMaxKey"))
                    {
                        sb.Append($" where {keyFieldWithPrefix} > @LastMaxKey");
                    }
                    sb.Append($" order by {keyField} limit {toRow - fromRow + 1}");

                    bool rst = Query(sb.ToString(), parms, out reader);

                    parms["LastMaxKey"] = maxValue;

                    return(rst);
                }
                else
                {
                    reader = null;

                    return(false);
                }
            }
            else
            {
                if (table.KeyFields.Length > 0)
                {
                    string fieldsSQL = ProcessFieldNames(table.SourceFields, "A");
                    string keyField  = ProcessFieldName(table.KeyFields[0]);
                    string keyFields = ProcessFieldNames(table.KeyFields, tableName);

                    sb.Append($"select {fieldsSQL} from {tableName} A join (select {keyFields} from {tableName}");
                    if (!string.IsNullOrEmpty(table.WhereSQL))
                    {
                        if (table.WhereSQL.IndexOf(" where ", StringComparison.OrdinalIgnoreCase) < 0)
                        {
                            sb.Append(" where");
                        }
                        sb.Append($" {table.WhereSQL}");
                    }
                    if (!string.IsNullOrEmpty(table.OrderSQL))
                    {
                        sb.Append(" order by ").Append(table.OrderSQL);
                    }
                    sb.Append($" limit {toRow - fromRow + 1} offset {fromRow - 1}) B on A.{keyField} = B.{keyField}");
                    for (int i = 1; i < table.KeyFields.Length; i++)
                    {
                        keyField = ProcessFieldName(table.KeyFields[i]);
                        sb.Append($" and A.{keyField} = B.{keyField}");
                    }
                }
                else
                {
                    string fieldsSQL = ProcessFieldNames(table.SourceFields, tableName);

                    sb.Append($"select {fieldsSQL} from {tableName}");
                    if (!string.IsNullOrEmpty(table.WhereSQL))
                    {
                        if (table.WhereSQL.IndexOf(" where ", StringComparison.OrdinalIgnoreCase) < 0)
                        {
                            sb.Append(" where");
                        }
                        sb.Append($" {table.WhereSQL}");
                    }
                    if (!string.IsNullOrEmpty(table.OrderSQL))
                    {
                        sb.Append(" order by ").Append(table.OrderSQL);
                    }
                    sb.Append($" limit {toRow - fromRow + 1} offset {fromRow - 1}");
                }

                return(Query(sb.ToString(), parms, out reader));
            }
        }