Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

259 lines
8.9 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 2000.
  5. //
  6. // File: RowComp.cxx
  7. //
  8. // Contents: Compares two rows.
  9. //
  10. // Classes: CRowComparator
  11. //
  12. // History: 05-Jun-95 KyleP Created
  13. // 14-JAN-97 KrishnaN Undefined CI_INETSRV and related changes
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.cxx>
  17. #pragma hdrstop
  18. #include <compare.hxx>
  19. #include "rowcomp.hxx"
  20. //+---------------------------------------------------------------------------
  21. //
  22. // Member: CRowComparator::CRowComparator, public
  23. //
  24. // Synopsis: Constructor.
  25. //
  26. // History: 05-Jun-95 KyleP Created.
  27. // 02-Feb-2000 KLam Removed END_CONSTRUCTION
  28. //
  29. //----------------------------------------------------------------------------
  30. CRowComparator::CRowComparator()
  31. : _aCmp(0),
  32. _aoColumn(0)
  33. {}
  34. //+---------------------------------------------------------------------------
  35. //
  36. // Member: CRowComparator::~CRowComparator, public
  37. //
  38. // Synopsis: Destructor.
  39. //
  40. // History: 05-Jun-95 KyleP Created.
  41. //
  42. //----------------------------------------------------------------------------
  43. CRowComparator::~CRowComparator()
  44. {
  45. delete [] _aDir;
  46. delete [] _aCmp;
  47. delete [] _aoColumn;
  48. }
  49. //+---------------------------------------------------------------------------
  50. //
  51. // Member: CRowComparator::Init, public
  52. //
  53. // Synopsis: Initializes comparator.
  54. //
  55. // Arguments: [sort] -- Sort specification.
  56. // [aBinding] -- Binding filled in here. Must have one
  57. // element per column in sort.
  58. // [aColumnInfo] -- Column metadata
  59. // [cColumnInfo] -- Size of [aColumnInfo]
  60. //
  61. // Returns: Size of buffer needed to satisfy binding.
  62. //
  63. // History: 05-Jun-95 KyleP Created.
  64. //
  65. //----------------------------------------------------------------------------
  66. unsigned CRowComparator::Init( CSort const & sort,
  67. DBBINDING * aBinding,
  68. DBCOLUMNINFO const * aColumnInfo,
  69. DBORDINAL cColumnInfo )
  70. {
  71. _cColumn = sort.Count();
  72. _aDir = new int [_cColumn];
  73. _aoColumn = new unsigned [_cColumn];
  74. _aCmp = new FDBCmp [_cColumn];
  75. BYTE * pb = (BYTE *)0 + _cColumn * sizeof(CRowComparator::SColumnStatus);
  76. for ( unsigned i = 0; i < _cColumn; i++ )
  77. {
  78. // NTRAID#DB-NTBUG9-84053-2000/07/31-dlee Distributed queries could be faster if ordinals were used to reference columns
  79. for ( DBORDINAL j = 0; j < cColumnInfo; j++ )
  80. {
  81. if ( *(CFullPropSpec *)&aColumnInfo[j].columnid == sort.Get(i).GetProperty() )
  82. {
  83. RtlZeroMemory(&aBinding[i], sizeof (DBBINDING));
  84. aBinding[i].dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
  85. aBinding[i].iOrdinal = aColumnInfo[j].iOrdinal;
  86. aBinding[i].wType = aColumnInfo[j].wType;
  87. // (sizeof (CRowComparator::SColumnStatus) * i ) + offsetof (Status)
  88. aBinding[i].obStatus =
  89. (DBBYTEOFFSET) (ULONG_PTR)&((CRowComparator::SColumnStatus *)0)[i].Status;
  90. // (sizeof (CRowComparator::SColumnStatus) * i ) + offsetof (Length)
  91. aBinding[i].obLength =
  92. (DBBYTEOFFSET) (ULONG_PTR)&((CRowComparator::SColumnStatus *)0)[i].Length;
  93. //
  94. // Invert the meaning of _aCmp[i] for columns that are descending.
  95. //
  96. Win4Assert( QUERY_SORTDESCEND == 1 && QUERY_SORTXDESCEND == 3 );
  97. if ( sort.Get(i).GetOrder() & 1 )
  98. _aDir[i] = -1;
  99. else
  100. _aDir[i] = 1;
  101. _aCmp[i] = VariantCompare.GetDBComparator( (DBTYPEENUM)aColumnInfo[j].wType );
  102. if ( aColumnInfo[j].wType & DBTYPE_VECTOR )
  103. {
  104. _aoColumn[i] = (unsigned)((ULONG_PTR)AlignULONG( pb ));
  105. }
  106. else if ( aColumnInfo[j].wType & DBTYPE_ARRAY )
  107. {
  108. _aoColumn[i] = (unsigned)((ULONG_PTR)AlignULONG( pb ));
  109. }
  110. else
  111. {
  112. switch ( aColumnInfo[j].wType )
  113. {
  114. case DBTYPE_EMPTY:
  115. case DBTYPE_NULL:
  116. case DBTYPE_STR:
  117. case DBTYPE_BSTR:
  118. case DBTYPE_BYTES:
  119. _aoColumn[i] = (unsigned)((ULONG_PTR)pb);
  120. break;
  121. case DBTYPE_I2:
  122. case DBTYPE_UI2:
  123. case DBTYPE_BOOL:
  124. _aoColumn[i] = (unsigned)((ULONG_PTR)AlignUSHORT( pb ));
  125. break;
  126. case DBTYPE_I4:
  127. case DBTYPE_UI4:
  128. case DBTYPE_ERROR:
  129. _aoColumn[i] = (unsigned)((ULONG_PTR)AlignULONG( pb ));
  130. break;
  131. case DBTYPE_R4:
  132. _aoColumn[i] = (unsigned)((ULONG_PTR)AlignFloat( pb ));
  133. break;
  134. case DBTYPE_R8:
  135. case DBTYPE_DATE:
  136. _aoColumn[i] = (unsigned)((ULONG_PTR)AlignDouble( pb ));
  137. break;
  138. case DBTYPE_CY:
  139. case DBTYPE_I8:
  140. case DBTYPE_UI8:
  141. case DBTYPE_VARIANT:
  142. _aoColumn[i] = (unsigned)((ULONG_PTR)AlignLONGLONG( pb ));
  143. break;
  144. case DBTYPE_GUID:
  145. _aoColumn[i] = (unsigned)((ULONG_PTR)AlignGUID( pb ));
  146. break;
  147. case DBTYPE_WSTR:
  148. _aoColumn[i] = (unsigned)((ULONG_PTR)AlignWCHAR( pb ));
  149. break;
  150. default:
  151. vqDebugOut(( DEB_WARN,
  152. "Can't determine alignment for type %d\n",
  153. aColumnInfo[j].wType ));
  154. _aoColumn[i] = (unsigned)((ULONG_PTR)pb);
  155. break;
  156. }
  157. }
  158. aBinding[i].obValue = _aoColumn[i];
  159. aBinding[i].cbMaxLen = aColumnInfo[j].ulColumnSize;
  160. pb = (BYTE *) ULongToPtr( _aoColumn[i] ) + aColumnInfo[j].ulColumnSize;
  161. break;
  162. }
  163. }
  164. if ( j == cColumnInfo )
  165. {
  166. vqDebugOut(( DEB_ERROR, "Can't bind to sort column.\n" ));
  167. Win4Assert( !"Can't bind to sort column." );
  168. THROW( CException(E_FAIL) );
  169. }
  170. }
  171. vqDebugOut(( DEB_ITRACE, "CRowComparator: Allocated %d byte buffer for comparisons\n", pb ));
  172. return (unsigned)((ULONG_PTR)pb);
  173. }
  174. //+---------------------------------------------------------------------------
  175. //
  176. // Member: CRowComparator::IsLT, public
  177. //
  178. // Synopsis: Less-than comparator
  179. //
  180. // Arguments: [pbRow1] -- Data for row 1.
  181. // [cbRow1] -- Size of [pbRow1]
  182. // [IndexRow1] -- Used to break ties.
  183. // [pbRow2] -- Data for row 2.
  184. // [cbRow2] -- Size of [pbRow2]
  185. // [IndexRow2] -- Used to break ties.
  186. //
  187. // Returns: TRUE of row1 < row2.
  188. //
  189. // History: 05-Jun-95 KyleP Created.
  190. //
  191. //----------------------------------------------------------------------------
  192. BOOL CRowComparator::IsLT( BYTE * pbRow1,
  193. ULONG cbRow1,
  194. int IndexRow1,
  195. BYTE * pbRow2,
  196. ULONG cbRow2,
  197. int IndexRow2 )
  198. {
  199. int iCmp = 0;
  200. CRowComparator::SColumnStatus * aColStatus1 = (CRowComparator::SColumnStatus *)pbRow1;
  201. CRowComparator::SColumnStatus * aColStatus2 = (CRowComparator::SColumnStatus *)pbRow2;
  202. for ( unsigned i = 0; i < _cColumn; i++ )
  203. {
  204. //
  205. // Verify field was successfully retrieved.
  206. //
  207. if ( FAILED(aColStatus1[i].Status) || FAILED(aColStatus2[i].Status) )
  208. break;
  209. iCmp = _aDir[i] * _aCmp[i]( pbRow1 + _aoColumn[i],
  210. (ULONG) aColStatus1[i].Length, // Length will never be 4Gb
  211. pbRow2 + _aoColumn[i],
  212. (ULONG)aColStatus2[i].Length ); // Length will never be 4Gb
  213. if ( 0 != iCmp )
  214. break;
  215. }
  216. if ( 0 == iCmp )
  217. return( IndexRow1 < IndexRow2 );
  218. else
  219. return( iCmp < 0 );
  220. }