예제 #1
0
            public SqlBuilder GetCountSql <TRecord>(IQuery aIQuery)
                where TRecord : class, IRecord, new()
            {
                //aQueryのDownキャスト
                Query <TRecord> aQuery = (Query <TRecord>)aIQuery;
                //TRecord型レコードとViewのマッピング情報を取得する
                RecordViewTableMap <TRecord> aRecordViewMap = _aRecordViewTableMapFactory.CreateRecordViewTableMap <TRecord>();
                //TRecordに対応するSqlPodを生成する
                SqlPod aSqlPod = _aSqlPodFactory.CreateSqlPod <TRecord>();

                //aQueryが持つ条件のプロパティ型リテラル値をDBデータ型に型変換する
                aQuery = aRecordViewMap.CastQuery(aQuery);

                //SQL文を作成する
                RecordViewTableMap <TRecord> aRecordViewTableMap = _aRecordViewTableMapFactory.CreateRecordViewTableMap <TRecord>();

                return(aSqlPod.GetCountSql(aQuery, aRecordViewTableMap));
            }
예제 #2
0
        public RecordViewTableMap <TRecord> CreateRecordViewTableMap <TRecord>()
            where TRecord : class, IRecord, new()
        {
            var recordName = RecordInfo <TRecord> .GetInstance().Name;

            // _mapHashへのデータ有無の判断と書込み読込みを不可分処理とする
            if (!_mapHash.ContainsKey(recordName))
            {
                lock (_mapHash) {
                    if (!_mapHash.ContainsKey(recordName))
                    {
                        var newMap = new RecordViewTableMap <TRecord>(_aDb);
                        _mapHash.Add(recordName, newMap);
                    }
                }
            }

            return((RecordViewTableMap <TRecord>)_mapHash[recordName]);
        }
예제 #3
0
        internal SqlBuilder GetCountSql <TRecord>(Query <TRecord> aQuery
                                                  , RecordViewTableMap <TRecord> aRecordViewTableMap = null)
            where TRecord : class, IRecord, new()
        {
            //サブクラスでSqlPod.CountSql()にSQLが定義されていなければ、
            //SELECT文にSELECT COUNT(*)を付加する
            if (this.CountSql() == null)
            {
                SqlBuilder selectSql = this.GetSelectSql(aQuery, aRecordViewTableMap);
                selectSql.ClearOrderBy();
                //Return "SELECT COUNT(*) FROM (" + selectSql + ") V1_"
                selectSql.SetCount();
                return(selectSql);
            }

            SqlBuilder sql = this.CountSql();

            //Query.RowRange()で抽出条件が指定されている場合
            if (aQuery.GetRowRange() != null & aRecordViewTableMap != null)
            {
                int begin = aQuery.GetRowRange().Item1;
                int end   = aQuery.GetRowRange().Item2;
                sql.SetRowLimit(begin, end);
            }

            //Pervasiveを除くDBMSではWHERE句などにAS別名は使用できない
            sql.WrapInSelectStar(aRecordViewTableMap.GetAllColumns(sql));

            //最大抽出件数の設定
            //OracleのRowNumによる指定は、SELECT * FROMに指定する
            if (aQuery.GetMaxRows() >= 0)
            {
                sql.SetMaxRows(aQuery.GetMaxRows());
            }

            //AND条件の追加
            if (sql.GetAutoWhere())
            {
                sql.AddAndPredicate(aQuery.GetWhereExp());
            }

            return(sql);
        }
예제 #4
0
            public SqlBuilder GetSelectSql <TRecord>(Query <TRecord> query
                                                     , LoadMode aLoadMode)
                where TRecord : class, IRecord, new()
            {
                //TRecord型レコードとViewのマッピング情報を取得する
                RecordViewTableMap <TRecord> aRecordViewMap = _aRecordViewTableMapFactory.CreateRecordViewTableMap <TRecord>();
                //TRecordに対応するSqlPodを生成する
                SqlPod aSqlPod = _aSqlPodFactory.CreateSqlPod <TRecord>();

                //aQueryが持つ条件のプロパティ型リテラル値をDBデータ型に型変換する
                query = aRecordViewMap.CastQuery(query);

                //SQL文を作成する
                //引数aLoadModeとaRecordTableMapを追加したのは苦渋の決断
                //(SqlBuilderがテーブルのメタ情報を扱うことを想定していなかったので、後付による拡張が綺麗にならない)
                RecordViewTableMap <TRecord> aRecordViewTableMap = _aRecordViewTableMapFactory.CreateRecordViewTableMap <TRecord>();

                return(aSqlPod.GetSelectSql(query, aRecordViewTableMap));
            }
예제 #5
0
        private LockData CreateLockDataSub <TRecord>(RecordViewTableMap <TRecord> aRecordViewTableMap
                                                     , long apTranId
                                                     , string recordName
                                                     , string tableName
                                                     , Dictionary <string, string> cnf)
            where TRecord : class, IRecord, new()
        {
            //主キーを含む全ての一致条件を格納するオブジェクト
            CNFofEquation cnfOfEquation = new CNFofEquation();
            //主キーに対する一致条件のみを格納するオブジェクト
            CNFofEquation cnfOfPKey = new CNFofEquation();

            //乗法標準形を用意する
            foreach (KeyValuePair <string, string> eqPredicate in cnf)
            {
                string varName = eqPredicate.Key;
                //SQLリテラル表記で値を取得する
                string value = eqPredicate.Value;

                //valueがIsNullPropertyValue()でNULL値と判定された場合、Predicateに含まれない(暫定実装)
                TableInfo  aTableInfo  = aRecordViewTableMap.GetTableInfo(tableName);
                ColumnInfo aColumnInfo = aTableInfo[varName];

                //一致条件を述語に追加する
                cnfOfEquation.Add(new Equation(varName, value));

                //主キーに対する一致条件であればcnfOfPKeyにも格納する
                if (aColumnInfo.PrimaryKey.HasValue && aColumnInfo.PrimaryKey.Value)
                {
                    cnfOfPKey.Add(new Equation(varName, value));
                    //テーブルの全ての主キーに対する一致条件が取得できれば、
                    //主キーに対する一致条件のみの述語だけで必要十分である
                    if (cnfOfPKey.Count == aTableInfo.GetPrimaryKeys().Count)
                    {
                        return(new LockData(apTranId, recordName, "", tableName, cnfOfPKey));
                    }
                }
            }

            return(new LockData(apTranId, recordName, "", tableName, cnfOfEquation));
        }
예제 #6
0
        /// <summary>
        /// SQL文の抽出条件からロックを作成する
        /// </summary>
        /// <typeparam name="TRecord"></typeparam>
        /// <param name="apTranId">APトランザクションID</param>
        /// <param name="sql">SQL文</param>
        /// <returns>作成したロックデータ</returns>
        /// <remarks></remarks>
        private List <LockData> CreateLockData <TRecord>(long apTranId
                                                         , SqlBuilder sql)
            where TRecord : class, IRecord, new()
        {
            List <LockData> ret = new List <LockData>();

            //TRecord型レコードとテーブルのマッピング情報を取得する
            RecordViewTableMap <TRecord> aRecordViewTableMap = _aRecordViewTableMapFactory.CreateRecordViewTableMap <TRecord>();
            //TRecord型レコードのメタ情報を取得する
            RecordInfo <TRecord> aRecordInfo = aRecordViewTableMap.GetRecordInfo();

            //テーブル列リストを作成する
            Dictionary <string, IEnumerable <string> > tableColumns = new Dictionary <string, IEnumerable <string> >();

            foreach (string srcTableName in sql.GetSrcTableNames())
            {
                //相関テーブルの主キーリストを作成する
                List <string> allColumnNames = new List <string>();
                foreach (ColumnInfo column in aRecordViewTableMap.GetTableInfo(srcTableName).GetAllColumns())
                {
                    allColumnNames.Add(column.ColumnName);
                }
                tableColumns.Add(srcTableName, allColumnNames);
            }

            //SQL文の抽出条件からロック情報を作成する
            foreach (KeyValuePair <SqlTable, Dictionary <string, string> > tableNameCnfPair in sql.GetCNF(tableColumns))
            {
                string srcTableName             = tableNameCnfPair.Key.Name;
                Dictionary <string, string> cnf = tableNameCnfPair.Value;
                LockData aLockData = this.CreateLockDataSub(aRecordViewTableMap
                                                            , apTranId
                                                            , aRecordInfo.Name
                                                            , srcTableName
                                                            , cnf);
                ret.Add(aLockData);
            }

            return(ret);
        }
예제 #7
0
        private List <LockData> CreateLockDataFromRecord_new <TRecord>(long apTranId
                                                                       , TRecord aRecord
                                                                       , IEnumerable <SqlTable> usedTableNames)
            where TRecord : class, IRecord, new()
        {
            List <LockData> ret = new List <LockData>();

            //TRecord型レコードとテーブルのマッピング情報を取得する
            RecordViewTableMap <TRecord> aRecordViewTableMap = _aRecordViewTableMapFactory.CreateRecordViewTableMap <TRecord>();
            //TRecord型レコードのメタ情報を取得する
            RecordInfo <TRecord> aRecordInfo = aRecordViewTableMap.GetRecordInfo();

            foreach (KeyValuePair <SqlTable, Dictionary <string, SqlExpr> > kv in aRecordViewTableMap.GetCNFExpression(aRecord
                                                                                                                       , usedTableNames))
            {
                string tableName = kv.Key.Name;
                //CNFを作成する
                Dictionary <string, string> cnf = new Dictionary <string, string>();
                foreach (KeyValuePair <string, SqlExpr> eq in kv.Value)
                {
                    //CNFの素論理式はリテラル値への一致条件のみとする
                    if (eq.Value.IsLiteral)
                    {
                        cnf.Add(eq.Key, eq.Value.ToString());
                    }
                }

                //ロック情報を作成する
                LockData aLockData = this.CreateLockDataSub(aRecordViewTableMap
                                                            , apTranId
                                                            , aRecordInfo.Name
                                                            , tableName
                                                            , cnf);
                ret.Add(aLockData);
            }

            return(ret);
        }
예제 #8
0
        /// <summary>
        /// SELECT文を取得する
        /// </summary>
        /// <param name="aQuery">最大抽出件数,AND条件,OrderBy句,プレースホルダ値をQueryオブジェクトで指定する</param>
        /// <returns></returns>
        /// <remarks>PervasiveはWhere句などにAS別名が使用できるので、
        /// SelectSql()で生成したSQLを抱合するSELECT文は必要ない。(Oracleでは必要)</remarks>
        internal SqlBuilder GetSelectSql <TRecord>(Query <TRecord> aQuery
                                                   , RecordViewTableMap <TRecord> aRecordViewTableMap)
            where TRecord : class, IRecord, new()
        {
            SqlBuilder sql = this.SelectSql();

            // OrderBy句の追加
            // (WrapInSelectStar()でOrderBy句の変換処理を行うのでWrapInSelectStar()の前に処理する)
            sql.AddOrderBy(aQuery.GetOrderByExp());

            // AS別名とテーブル列名が重複する場合にSQL実行エラーになることがあるため
            // 全てのSELECT文についてSELECT * で囲む
            sql.WrapInSelectStar(aRecordViewTableMap.GetAllColumns(sql));

            //最大抽出件数の設定
            //OracleのRowNumによる指定は、SELECT * FROMに指定する
            if (aQuery.GetMaxRows() >= 0)
            {
                sql.SetMaxRows(aQuery.GetMaxRows());
            }

            if (sql.GetAutoWhere())
            {
                //AND条件の追加
                sql.AddAndPredicate(aQuery.GetWhereExp());
            }

            //Query.RowRange()で抽出条件が指定されている場合
            if (aQuery.GetRowRange() != null)
            {
                int begin = aQuery.GetRowRange().Item1;
                int end   = aQuery.GetRowRange().Item2;
                sql.SetRowLimit(begin, end);
            }

            return(sql);
        }