00001 // $Id: reference.h,v 1.8 2005/12/18 16:15:16 dvermeir Exp $ 00002 #ifndef DVMYSQL_REFERENCE_H 00003 #define DVMYSQL_REFERENCE_H 00004 00005 #include <dvmysql/table.h> 00006 #include <dvmysql/select_exp.h> 00007 #include <dvmysql/column.h> 00008 00009 namespace Dv { 00010 namespace Sql { 00011 class Object; 00012 /** A reference represents a semantic connection between tables. 00013 * It consists of two tables, a source and target table 00014 * and a list of columns in each table. Both lists should 00015 * have equal length and the corresponding data types of the 00016 * columns in both lists should agree. 00017 * 00018 * A reference can be followed, e.g. if an object corresponds to a 00019 * row in the source table, then an object(s) in the target 00020 * table may be obtained by copying the column values from the 00021 * source object to a target object and then find all objects in 00022 * the target table matching the target object. Similarly, 00023 * a reference can be followed in the "reverse" direction. 00024 * Note that there is no requirement that a reference is single 00025 * valued, e.g. there may be many target table rows corresponding 00026 * to a single source table row. 00027 * 00028 * References are supported by Object and Row as 00029 * well as by the Object::Set and Row::Set classes. 00030 * 00031 * @par Example 00032 * @code 00033 * const Dv::Sql::Reference acct_cust( 00034 * Database::account, (cols = &Account::customer_id), 00035 * Database::customer, (cols = &Customer::id) 00036 * ); 00037 * Object cust(..); 00038 * // all accounts of this customer 00039 * Object::Set::Ref accounts = cust.references(acct_cust); 00040 * @endcode 00041 * 00042 * In addition, reference can be used to generate 00043 * Dv::Sql::SelectExp objects and queries using the member 00044 * functions 00045 * Dv::Sql::Reference::match 00046 * Dv::Sql::Reference::match_source and 00047 * Dv::Sql::Reference::match_target . 00048 * @par Example 00049 * @code 00050 * const Dv::Sql::Reference acct_cust( 00051 * Database::account, (cols = &Account::customer_id), 00052 * Database::customer, (cols = &Customer::id) 00053 * ); 00054 * const Dv::Sql::Reference trans_acct( 00055 * Database::transaction, (cols = &Transaction::account_code), 00056 * Database::account, (cols = &Account::code) 00057 * ); 00058 * 00059 * Dv::Sql::SelectExp e = 00060 * acct_cust.match_target(cust) && acct_cust.match() && trans_acct.match(); 00061 * // transs contains all transactions associated with accounts from customer @p cust 00062 * Transaction::Set transs(e); 00063 * @endcode 00064 * 00065 * @see Dv::Sql::Object::references 00066 * @see Dv::Sql::Object::Set::Set(const Source&,const Dv::Sql::Reference&) 00067 * @see Dv::Sql::Row::Row(const Dv::Sql::Object&, const Dv::Sql::Reference&) 00068 * @see Dv::Sql::Row::Set::Set(const Source&,const Dv::Sql::Reference&) 00069 * @see Dv::Sql::Reference::match 00070 * @see Dv::Sql::Reference::match_source 00071 * @see Dv::Sql::Reference::match_target 00072 */ 00073 class Reference { 00074 public: 00075 typedef std::vector<const Reference*> List; 00076 /** Constructor. 00077 * @param from_table source table of the reference 00078 * @param from_columns list of columns in from_table 00079 * @param to_table target table of the reference 00080 * @param to_columns list of columns in the target table 00081 * @exception std::logic_error if from_columns has a different 00082 * size from to_columns 00083 * @exception std::logic_error if from_columns has size 0 00084 * @warning References should only be used after the 00085 * parameter Dv::Sql::Table::Ref objects have been properly 00086 * initialized. E.g. db2cpp generates static 00087 * Dv::Sql::Table::Ref (and 00088 * Dv::Sql::Row<Dv::Sql::Table::Ref>::Column) definitions which are only 00089 * initialized after the database has been opened. 00090 * A Reference object may use these definitions as 00091 * constructor arguments, even in static storage. 00092 * However, the Reference should be used only after 00093 * all its parameters (which are references or pointers) 00094 * have been initialized. 00095 * 00096 * In the example below: the constructor will succeed even 00097 * before Database::account and Account::customer_id have been 00098 * initialized, but the resulting @p acct_cust should not 00099 * be used until they have been initialized. 00100 * @par Example 00101 * @code 00102 * const Dv::Sql::Reference acct_cust( 00103 * Database::account, (cols = &Account::customer_id), 00104 * Database::customer, (cols = &Customer::id) 00105 * ); 00106 * @endcode 00107 */ 00108 Reference(const Table::Ref& from_table, std::vector<const Dv::Sql::Column*> from_columns, 00109 const Table::Ref& to_table, std::vector<const Dv::Sql::Column*> to_columns) 00110 throw (std::logic_error); 00111 /** Destructor. */ 00112 ~Reference(); 00113 00114 /** The source table of the reference. */ 00115 const Table::Ref& from_table; 00116 /** The target table of the reference. */ 00117 const Table::Ref& to_table; 00118 00119 /** The index of the i'th column in the list of target table 00120 * columns. 00121 * @param i the position in the list of target table columns. 00122 * @return the index of the i'th column in the list of target table columns. 00123 */ 00124 size_t to(size_t i) const { return to_[i]->index(); } 00125 /** The index of the i'th column in the list of source table 00126 * columns. 00127 * @param i the position in the list of source table columns. 00128 * @return the index of the i'th column in the list of source table columns. 00129 */ 00130 size_t from(size_t i) const { return from_[i]->index(); } 00131 /** The number of columns in each list. 00132 * @return the number of columns in the source and target 00133 * list. 00134 */ 00135 size_t size() const { return from_.size(); } 00136 /** Return an SQL "where" condition expressing that 00137 * corresponding column values should match. 00138 * @par Example 00139 * @code 00140 * const Dv::Sql::Reference acct_cust( 00141 * Database::account, (cols = &Account::customer_id), 00142 * Database::customer, (cols = &Customer::id) 00143 * ); 00144 * const Dv::Sql::Reference trans_acct( 00145 * Database::transaction, (cols = &Transaction::account_code), 00146 * Database::account, (cols = &Account::code) 00147 * ); 00148 * 00149 * Dv::Sql::SelectExp e = 00150 * acct_cust.match_target(cust) && acct_cust.match() && trans_acct.match(); 00151 * // transs contains all transactions associated with accounts from customer @p cust 00152 * Transaction::Set transs(e); 00153 * @endcode 00154 * @see Dv::Sql::Reference::match_target 00155 */ 00156 const SelectExp& match() const; 00157 00158 operator SelectExp() const { return match(); } 00159 00160 /** Return an SQL "where" condition expressing that the source column 00161 * values of the source table should match those of the 00162 * parameter object. 00163 * @param source object whose column values will be used to 00164 * restrict the column values of source table objects. This 00165 * object should represent a row in the source table. 00166 * @return condition expressing the match 00167 * @see Dv::Sql::Reference::match 00168 * @see Dv::Sql::Reference::match_target 00169 * @exception std::logic_error if the source object's arity 00170 * does not match the from_table's. 00171 */ 00172 SelectExp match_source(const Object& source) const throw (std::logic_error); 00173 /** Return an SQL "where" condition expressing that the target column 00174 * values of the target table should match those of the 00175 * parameter object. 00176 * @param target object whose column values will be used to 00177 * restrict the column values of target table objects. This 00178 * object should represent a row in the target table. 00179 * @return condition expressing the match 00180 * @see Dv::Sql::Reference::match 00181 * @see Dv::Sql::Reference::match_source 00182 * @exception std::logic_error iff the target object's arity 00183 * does not match the to_table's. 00184 */ 00185 SelectExp match_target(const Object& target) const throw (std::logic_error); 00186 00187 private: 00188 /** The columns in the source table of the reference. */ 00189 std::vector<const Dv::Sql::Column*> from_; 00190 /** The columns in the target table of the reference. */ 00191 std::vector<const Dv::Sql::Column*> to_; 00192 SelectExp* select_exp; 00193 }; 00194 00195 /** Type of a tag that allows one to define vectors of Reference 00196 * objects in an expression. 00197 * @par Example 00198 * @code 00199 * Dv::Sql::ReferenceListTag refs; 00200 * int f(const std::string& s, Reference::List) 00201 * .. 00202 * } 00203 * Reference r1; 00204 * Reference r2; 00205 * Reference r3; 00206 * f("name", (refs = &r1, &r2, &r3)); 00207 * @endcode 00208 */ 00209 typedef Dv::Util::CsListTag<std::vector<const Reference*> > ReferenceListTag; 00210 00211 } 00212 } 00213 #endif
dvmysql-1.0.3 | [17 November, 2010] |