00001 #ifndef _DATAVALUE_H_ 00002 #define _DATAVALUE_H_ 00003 // 00004 00005 // 00006 // Copyright (C) 2004-2007 Autodesk, Inc. 00007 // 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of version 2.1 of the GNU Lesser 00010 // General Public License as published by the Free Software Foundation. 00011 // 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 // Lesser General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU Lesser General Public 00018 // License along with this library; if not, write to the Free Software 00019 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 // 00021 00022 #ifdef _WIN32 00023 #pragma once 00024 #endif 00025 00026 #include <FdoStd.h> 00027 #include <Fdo/Expression/LiteralValue.h> 00028 #include <Fdo/Schema/DataType.h> 00029 #include <Fdo/Expression/ExpressionException.h> 00030 00031 /// \brief 00032 /// The FdoDataValue class derives from FdoLiteralValue and represents a literal 00033 /// value such as a string or a number. 00034 class FdoDataValue : public FdoLiteralValue 00035 { 00036 /// \cond DOXYGEN-IGNORE 00037 friend class FdoInternalDataValue; 00038 friend class FdoByteValue; 00039 friend class FdoDecimalValue; 00040 friend class FdoDoubleValue; 00041 friend class FdoInt16Value; 00042 friend class FdoInt32Value; 00043 friend class FdoInt64Value; 00044 friend class FdoSingleValue; 00045 protected: 00046 /// \brief 00047 /// Constructs a default instance of an FdoDataValue with data type string and a 00048 /// value of null. 00049 /// 00050 /// \return 00051 /// Returns nothing 00052 /// 00053 FdoDataValue(); 00054 /// \endcond 00055 00056 public: 00057 /// \brief 00058 /// Constructs an instance of a null FdoDataValue using the specified arguments. 00059 /// 00060 /// \param dataType 00061 /// Input data type 00062 /// 00063 /// \return 00064 /// Returns nothing 00065 /// 00066 FDO_API static FdoDataValue* Create(FdoDataType dataType); 00067 00068 /// \brief 00069 /// Constructs an instance of an FdoBooleanValue using the specified argument. 00070 /// 00071 /// \param value 00072 /// Input a Boolean value 00073 /// 00074 /// \return 00075 /// Returns an FdoBooleanValue 00076 /// 00077 FDO_API static FdoDataValue* Create(bool value); 00078 00079 /// \brief 00080 /// Constructs an instance of an FdoByteValue using the specified argument. 00081 /// 00082 /// \param value 00083 /// Input a byte 00084 /// 00085 /// \return 00086 /// Returns an FdoByteValue 00087 /// 00088 FDO_API static FdoDataValue* Create(FdoByte value); 00089 00090 /// \brief 00091 /// Constructs an instance of an FdoDateTimeValue using the specified argument. 00092 /// 00093 /// \param value 00094 /// Input a FdoDateTime 00095 /// 00096 /// \return 00097 /// Returns an FdoDateTimeValue 00098 /// 00099 FDO_API static FdoDataValue* Create(FdoDateTime value); 00100 00101 /// \brief 00102 /// Constructs an instance of an FdoDecimalValue or FdoDoubleValue using 00103 /// the specified arguments. 00104 /// 00105 /// \param value 00106 /// Input a double 00107 /// \param dataType 00108 /// Input a data type 00109 /// 00110 /// \return 00111 /// Returns an FdoDecimalValue or FdoDoubleValue 00112 /// 00113 FDO_API static FdoDataValue* Create(double value, FdoDataType dataType); 00114 00115 /// \brief 00116 /// Constructs an instance of an FdoInt16Value using the specified argument. 00117 /// 00118 /// \param value 00119 /// Input a 16 bit integer 00120 /// 00121 /// \return 00122 /// Returns an FdoInt16Value 00123 /// 00124 FDO_API static FdoDataValue* Create(FdoInt16 value); 00125 00126 /// \brief 00127 /// Constructs an instance of an FdoInt32Value using the specified argument. 00128 /// 00129 /// \param value 00130 /// Input a 32 bit integer 00131 /// 00132 /// \return 00133 /// Returns an FdoInt32Value 00134 /// 00135 FDO_API static FdoDataValue* Create(FdoInt32 value); 00136 00137 /// \brief 00138 /// Constructs an instance of an FdoInt64Value using the specified argument. 00139 /// 00140 /// \param value 00141 /// Input a 64 bit integer 00142 /// 00143 /// \return 00144 /// Returns an FdoInt64Value 00145 /// 00146 FDO_API static FdoDataValue* Create(FdoInt64 value); 00147 00148 /// \brief 00149 /// Constructs an instance of an FdoSingleValue using the specified argument. 00150 /// 00151 /// \param value 00152 /// Input a single precision floating point value 00153 /// 00154 /// \return 00155 /// Returns an FdoSingleValue 00156 /// 00157 FDO_API static FdoDataValue* Create(float value); 00158 00159 /// \brief 00160 /// Constructs an instance of an FdoStringValue using the specified argument. 00161 /// 00162 /// \param value 00163 /// Input a character string 00164 /// 00165 /// \return 00166 /// Returns an FdoStringValue 00167 /// 00168 FDO_API static FdoDataValue* Create(FdoString* value); 00169 00170 /// \brief 00171 /// Constructs an instance of an FdoBLOBValue or FdoCLOBValue using the specified arguments. 00172 /// 00173 /// \param value 00174 /// Input a byte array 00175 /// \param length 00176 /// Input the length of the byte array 00177 /// \param dataType 00178 /// Input the type of value to create 00179 /// 00180 /// \return 00181 /// Returns an FdoBLOBValue or an FdoCLOBValue 00182 /// 00183 FDO_API static FdoDataValue* Create(FdoByte* value, FdoInt32 length, FdoDataType dataType); 00184 00185 /// \brief 00186 /// Constructs an instance of an FdoBLOBValue or FdoCLOBValue using the specified arguments. 00187 /// 00188 /// \param value 00189 /// Input a byte array 00190 /// \param dataType 00191 /// Input the type of value to create 00192 /// 00193 /// \return 00194 /// Returns an FdoBLOBValue or an FdoCLOBValue 00195 /// 00196 FDO_API static FdoDataValue* Create(FdoByteArray* value, FdoDataType dataType); 00197 00198 /// \brief 00199 /// Gets the data type of the FdoDataValue. 00200 /// 00201 /// \return 00202 /// Returns an FdoDataType 00203 /// 00204 FDO_API virtual FdoDataType GetDataType() = 0; 00205 00206 /// \brief 00207 /// Returns true if the FdoDataValue represents a null value. 00208 /// 00209 /// \return 00210 /// Returns true if the FdoDataValue represents a null value 00211 /// 00212 FDO_API virtual bool IsNull(); 00213 00214 /// \brief 00215 /// Sets the FdoDataValue to a null value of the specified type. 00216 /// 00217 /// \return 00218 /// Returns nothing 00219 /// 00220 FDO_API virtual void SetNull(); 00221 00222 /// \brief 00223 /// Gets the literal value type of the FdoDataValue. 00224 /// 00225 /// \return 00226 /// Returns an FdoLiteralValueType 00227 /// 00228 FDO_API virtual FdoLiteralValueType GetLiteralValueType () const; 00229 00230 static FdoDataValue* Create(FdoString* value, FdoDataType dataType); 00231 00232 // Get the value as an XML format string. 00233 FdoString* GetXmlValue(); 00234 00235 /// \cond DOXYGEN-IGNORE 00236 protected: 00237 /// \brief 00238 /// Compares this data value with another data value 00239 /// 00240 /// \param other 00241 /// Input the other data value 00242 /// 00243 /// \return 00244 /// Returns: 00245 /// FdoCompareType_Equal when this and the other value are equal or both null. 00246 /// FdoCompareType_Greater when this value is greater than the other value 00247 /// FdoCompareType_Less when this value is less than the other value 00248 /// FdoCompareType_Undefined when these two values cannot be compared. Cases where this happens 00249 /// are: 00250 /// - one value is null and the other is not null 00251 /// - the values have incompatible types (e.g. Int32 and DateTime). 00252 /// 00253 /// 00254 FdoCompareType Compare( FdoDataValue* other ); 00255 00256 // ReverseCompare is the same as Compare except for two of the return values: 00257 /// FdoCompareType_Greater when the other value is greater than this value 00258 /// FdoCompareType_Less when the other value is less than this value 00259 FdoCompareType ReverseCompare( FdoDataValue* other ); 00260 00261 /// \brief 00262 /// Type-specific comparison function. Each sub-class has its own implementation. 00263 /// 00264 /// \param other 00265 /// Input the other data value 00266 /// 00267 /// \return 00268 /// Returns: 00269 /// FdoCompareType_Equal when this and the other value are equal or both null. 00270 /// FdoCompareType_Greater when this value is greater than the other value 00271 /// FdoCompareType_Less when this value is less than the other value 00272 /// FdoCompareType_Undefined when these two values cannot be compared. Cases where this happens 00273 /// are: 00274 /// - one value is null and the other is not null 00275 /// - the values have incompatible types (e.g. Int32 and DateTime). 00276 /// 00277 /// Base implementation always returns FdoCompareType_Undefined. 00278 /// 00279 /// 00280 virtual FdoCompareType DoCompare( FdoDataValue* other ); 00281 00282 /// \brief 00283 /// Constructs an instance of an FdoDoubleValue from a double 00284 /// 00285 /// \param value 00286 /// Input the double value 00287 /// \return 00288 /// Returns an FdoDoubleValue 00289 /// 00290 static FdoDataValue* Create( FdoDouble value ); 00291 00292 /// \brief 00293 /// Constructs an instance of an FdoDataValue from another FdoDataValue. 00294 /// 00295 /// \param dataType 00296 /// Input the destination type. An FdoDataValue of this type is created. 00297 /// For more information on how the FdoDataValue is created, see the specific 00298 /// Create(FdoDataValue* FdoBoolean, FdoBoolean, FdoBoolean ) function for 00299 /// each dataType. For example, if dataType=FdoDataType_Int16, see 00300 /// FdoInt16Value::Create(FdoDataValue* FdoBoolean, FdoBoolean, FdoBoolean ) 00301 /// \param src 00302 /// Input the source (other) FdoDataValue 00303 /// \param nullIfIncompatible 00304 /// Input will determine what to do if source value type is not compatible with the 00305 /// this type: 00306 /// true - return NULL. 00307 /// false - throw an exception 00308 /// 00309 /// \param shift 00310 /// Input will determine what to do if the src value is within the range of 00311 /// valid values for the destination type but still must be shifted to be a 00312 /// valid destination type value (e.g. 3.5 must be shifted to convert it from 00313 /// FdoDoubleValue to FdoInt32Value): 00314 /// true - perform the shift. 00315 /// false - behaviour depends on nullIfIncompatible: 00316 /// true - return NULL. 00317 /// false - throw an exception 00318 /// 00319 /// \param truncate 00320 /// Input in the future will determine what to do if source value is outside the 00321 /// range of valid values for the destination type: 00322 /// true - convert values less than the minimum to the minimum, 00323 /// convert values greater than maximum to the maximum 00324 /// false - behaviour depends on nullIfIncompatible: 00325 /// true - return NULL. 00326 /// false - throw an exception 00327 /// \return 00328 /// Returns an FdoDataValue, whose value is converted from the src value. 00329 static FdoDataValue* Create( 00330 FdoDataType dataType, 00331 FdoDataValue* src, 00332 FdoBoolean nullIfIncompatible = false, 00333 FdoBoolean shift = true, 00334 FdoBoolean truncate = false 00335 ); 00336 00337 /* Helper Templates for FdoDataValue::Create( FdoDataType, FdoDataValue*, FdoBoolean, FdoBoolean, FdoBoolean ) */ 00338 00339 // Converts values that may need shifting to other values. 00340 template <class CI, // input FdoDataValue 00341 class CO, // output FdoDataValue 00342 class TI, // input FDO type - must correspond to CI 00343 class TO // output FDO type - must correspond to CO 00344 > 00345 static CO* Convert( 00346 CI* obj, // input FdoDataValue 00347 TI val, // input scalar value for obj 00348 TO min, // minimum value for TO type 00349 TO max, // maximum value for TO type 00350 TI round, // amount for rounding 00351 FdoBoolean nullIfIncompatible, // see FdoDataValue::Create() 00352 FdoBoolean shift, // see FdoDataValue::Create() 00353 FdoBoolean truncate, // see FdoDataValue::Create() 00354 FdoString* sTO // TO in string format; for exception messages. 00355 ) 00356 { 00357 CO* ret = NULL; 00358 FdoBoolean isNull = false; 00359 TO out; 00360 00361 // First, truncate the value to be between output type min and max. 00362 Truncate<TI,TO>( val, out, isNull, min, max, nullIfIncompatible, truncate, sTO ); 00363 00364 if ( isNull ) 00365 { 00366 // Output determined to be null 00367 ret = CO::Create(); 00368 } 00369 else if ( (val < min) || (val > max) ) 00370 { 00371 // value was truncated. Wrap it in FdoDataValue. 00372 ret = CO::Create(out); 00373 } 00374 else 00375 { 00376 // Round the value and convert it 00377 ret = CO::Create( (TO) ((val < 0) ? (val - round) : (val + round)) ); 00378 // Prevent value shifting when shifting not allowed. 00379 VldShift( obj, ret, nullIfIncompatible, shift ); 00380 } 00381 00382 return ret; 00383 }; 00384 00385 // Converts values that don't need shifting, but may need truncation, 00386 // to other values. 00387 template < 00388 class C, // output FdoDataValue 00389 class TI, // input FDO type 00390 class TO // output FDO type - must correspond to CO 00391 > 00392 static C* Convert( 00393 TI val, // input scalar value for obj 00394 TO min, // minimum value for TO type 00395 TO max, // maximum value for TO type 00396 FdoBoolean nullIfIncompatible, // see FdoDataValue::Create() 00397 FdoBoolean truncate, // see FdoDataValue::Create() 00398 FdoString* sTO // TO in string format; for exception messages. 00399 ) 00400 { 00401 C* ret = NULL; 00402 FdoBoolean isNull = false; 00403 TO out; 00404 00405 // First, truncate the value to be between output type min and max. 00406 Truncate<TI, TO>( val, out, isNull, min, max, nullIfIncompatible, truncate, sTO ); 00407 00408 if ( isNull ) 00409 // Output determined to be null 00410 ret = C::Create(); 00411 else 00412 // Wrap output in an FdoDataValue. 00413 ret = C::Create( out ); 00414 00415 return ret; 00416 }; 00417 00418 // Truncates a value to be between a minimum and maximum value. 00419 template < 00420 class TI, // input FDO type 00421 class TO // output FDO type 00422 > 00423 static bool Truncate( 00424 TI in, // original value 00425 TO& out, // truncated value 00426 bool& isNull, // set to true if value truncated and 00427 // truncate=false and nullIfIncompatible=true 00428 TO min, // minimum value for TO type 00429 TO max, // maximum value for TO type 00430 bool nullIfIncompatible, // see FdoDataValue::Create() 00431 bool truncate, // see FdoDataValue::Create() 00432 FdoString* sTO // TO in string format; for exception messages. 00433 ) 00434 { 00435 bool success = true; 00436 00437 // no truncation by default. However, it is up to the caller to 00438 // determine if casting shifted the value. 00439 out = (TO) in; 00440 00441 if ( in < min ) 00442 success = Truncate<TI, TO>( in, out, isNull, min, nullIfIncompatible, truncate ); 00443 else if ( in > max ) 00444 success = Truncate<TI, TO>( in, out, isNull, max, nullIfIncompatible, truncate ); 00445 00446 if ( !success ) 00447 throw FdoExpressionException::Create( 00448 FdoException::NLSGetMessage( 00449 FDO_NLSID(EXPRESSION_21_VALUETRUNCATED), 00450 FdoPtr<FdoDataValue>(FdoDataValue::Create(in))->ToString(), 00451 sTO, 00452 FdoPtr<FdoDataValue>(FdoDataValue::Create(min))->ToString(), 00453 FdoPtr<FdoDataValue>(FdoDataValue::Create(max))->ToString() 00454 ) 00455 ); 00456 00457 return true; 00458 }; 00459 00460 // Truncates a value to a range endpoint 00461 template < 00462 class TI, // input FDO type 00463 class TO // output FDO type 00464 > 00465 static bool Truncate( 00466 TI in, // input value 00467 TO& out, // output value 00468 bool& isNull, // set to true truncate=false and 00469 // nullIfIncompatible=true 00470 TO bound, // the range endpoint 00471 bool nullIfIncompatible, // see FdoDataValue::Create() 00472 bool truncate // see FdoDataValue::Create() 00473 ) 00474 { 00475 bool ret = true; 00476 00477 if ( truncate ) 00478 { 00479 // Truncation allowed so set output to the range endpoint 00480 out = bound; 00481 } 00482 else 00483 { 00484 if ( nullIfIncompatible ) 00485 // Truncation not allowed so set output to null 00486 isNull = true; 00487 else 00488 // Truncation not allowed so raise an error 00489 ret = false; 00490 } 00491 00492 return ret; 00493 }; 00494 00495 // Helper function for FdoDataValue::Create( FdoDataType, FdoDataValue*, FdoBoolean, FdoBoolean, FdoBoolean ) 00496 // Adjusts shifted values depending on whether shift is allowd 00497 static void VldShift( 00498 FdoDataValue* origValue, // original value 00499 FdoDataValue* newValue, // converted value 00500 bool nullIfIncompatible, // Determines what happens when shift=false 00501 // and origValue != newValue (shift occurred 00502 // when origValue was converted to newValue but 00503 // shifting not allowed ): 00504 // true: set newValue to null. 00505 // false: throw an exception 00506 bool shift // determines whether value allowed to shift. 00507 ); 00508 00509 static FdoStringP DataTypeToString( FdoDataType dataType ); 00510 00511 bool m_isNull; 00512 FdoStringP m_XmlValue; // Manages GetXmlValue return string when datatype is datetime. 00513 /// \endcond 00514 00515 }; 00516 00517 /// \ingroup (typedefs) 00518 /// \brief 00519 /// FdoDataValueP is a FdoPtr on FdoDataValue, provided for convenience. 00520 typedef FdoPtr<FdoDataValue> FdoDataValueP; 00521 00522 #endif 00523 00524