persistentstorage/dbms/pcdbms/usql/UQ_MULTI.CPP
changeset 0 08ec8eefde2f
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // SQL AND and OR node class
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "UQ_STD.H"
       
    19 
       
    20 // class CSqlMultiNode
       
    21 
       
    22 inline CSqlMultiNode::CSqlMultiNode( TType aType )
       
    23  :	CSqlSearchCondition( aType )
       
    24 	{ __ASSERT( aType == EOr || aType == EAnd ); }
       
    25 
       
    26 inline TInt CSqlMultiNode::Size() const
       
    27 	{ return ( const TUint8* )iEnd - ( const TUint8* )this; }
       
    28 
       
    29 inline TBool CSqlMultiNode::IsFull() const
       
    30 	{ return ( Size() & ( EGranularity - 1 ) ) == 0; }
       
    31 
       
    32 inline TInt CSqlMultiNode::Size( TInt aLeaves )
       
    33 	{ return _FOFF( CSqlMultiNode, iLeaves[ aLeaves ] ); }
       
    34 
       
    35 CSqlMultiNode::~CSqlMultiNode()
       
    36 	{
       
    37 	TEntry* p = iLeaves;
       
    38 	TEntry* e = iEnd;
       
    39 	while ( p < e )
       
    40 		delete *p++;
       
    41 	}
       
    42 
       
    43 CSqlMultiNode* CSqlMultiNode::New( TType aType, TInt aSize )
       
    44 	{
       
    45 	aSize = ( aSize + ( EGranularity - 1 ) ) & ~( EGranularity - 1 );
       
    46 	__ASSERT( aSize >= static_cast<TInt>( sizeof( CSqlMultiNode ) ) );
       
    47 	aSize -= sizeof( CSqlMultiNode );
       
    48 	return new( aSize )  CSqlMultiNode( aType );	// get the extra size for the entries
       
    49 	}
       
    50 
       
    51 CSqlMultiNode* CSqlMultiNode::Grow( CSqlMultiNode* aNode, TInt aExtraSize )
       
    52 	{
       
    53 	TInt size = aNode->Size();
       
    54 	CSqlMultiNode* self = New( aNode->NodeType(), size + aExtraSize );
       
    55 	if ( self )
       
    56 		{
       
    57 		aNode->iEnd = aNode->iLeaves;
       
    58 		self->iEnd = ( TEntry* )Mem::Copy( self->iLeaves, aNode->iLeaves, size - Size( 0 ) );
       
    59 		}
       
    60 	delete aNode;
       
    61 	return self;
       
    62 	}
       
    63 
       
    64 CSqlMultiNode* CSqlMultiNode::Concatenate( CSqlMultiNode* aLeft, CSqlMultiNode* aRight )
       
    65 	{
       
    66 	TInt lsize = aLeft->Size();
       
    67 	TInt rsize = aRight->Size();
       
    68 	if ( rsize > lsize )
       
    69 		return Concatenate( aRight, aLeft );	// right node larger--flip over
       
    70 	rsize -= Size( 0 );
       
    71 	if ( (aLeft->IsFull()) ||											// if left node is already full 
       
    72 		 (( lsize & ( EGranularity - 1 ) ) + rsize > EGranularity ) )	// or available space in the left node is not enough for a new data
       
    73 			aLeft = Grow( aLeft, rsize );								// then increase left node to accomadate right node
       
    74 	if ( aLeft )
       
    75 		{
       
    76 		aRight->iEnd = aRight->iLeaves;
       
    77 		aLeft->iEnd = ( TEntry* )Mem::Copy( aLeft->iEnd, aRight->iLeaves, rsize );
       
    78 		}
       
    79 	delete aRight;
       
    80 	return aLeft;
       
    81 	}
       
    82 
       
    83 CSqlSearchCondition* CSqlMultiNode::New( TType aType, CSqlSearchCondition* aLeft, CSqlSearchCondition* aRight )
       
    84 //
       
    85 // Full NULL propagation, cleaning up any of either node on failure
       
    86 //
       
    87 	{
       
    88 	if ( aLeft && aRight )
       
    89 		{
       
    90 		if ( aLeft->NodeType() == aType )
       
    91 			{	// we can merge into aLeft
       
    92 			CSqlMultiNode* left = aLeft->MultiNode();
       
    93 			if ( aRight->NodeType() == aType )
       
    94 				return Concatenate( left, aRight->MultiNode() );
       
    95 			
       
    96 			// append right subnode onto left
       
    97 			if ( left->IsFull() )
       
    98 				{
       
    99 				left = Grow( left, sizeof( TEntry ) );
       
   100 				if ( !left )
       
   101 					goto grow_failed;
       
   102 				}
       
   103 			TEntry* e = left->iEnd;
       
   104 			*e++ = aRight;
       
   105 			left->iEnd = e;
       
   106 			return left;
       
   107 			}
       
   108 		else if ( aRight->NodeType() == aType )
       
   109 			return New( aType, aRight, aLeft );	// swap left and right
       
   110 		else
       
   111 			{	// neither node is not of the required type
       
   112 			CSqlMultiNode* self = New( aType, Size( 2 ) );
       
   113 			if ( self )
       
   114 				{
       
   115 				TEntry* e = self->iLeaves;
       
   116 				*e++ = aLeft;
       
   117 				*e++ = aRight;
       
   118 				self->iEnd = e;
       
   119 				return self;
       
   120 				}
       
   121 			}
       
   122 		}
       
   123 	delete aLeft;
       
   124 grow_failed:
       
   125 	delete aRight;
       
   126 	return 0;
       
   127 	}
       
   128 
       
   129 void CSqlMultiNode::Remove( CSqlSearchCondition* aSubNode )
       
   130 //
       
   131 // Remove the subnode from the leaf-set
       
   132 //
       
   133 	{
       
   134 	TEntry* p = iLeaves - 1;
       
   135 	TEntry* e = --iEnd;
       
   136 	do
       
   137 		{
       
   138 		__ASSERT( p < e );
       
   139 		} while ( *++p != aSubNode );
       
   140 	while ( p<e )
       
   141 		{
       
   142 		TEntry e = *++p;
       
   143 		p[ -1 ] = e;
       
   144 		}
       
   145 	delete aSubNode;
       
   146 	}
       
   147 
       
   148 CSqlSearchCondition* CSqlMultiNode::Reduce (CSqlMultiNode* aNode )
       
   149 //
       
   150 // If we have less than two leaves, then simplify the expression
       
   151 //
       
   152 	{
       
   153 	CSqlSearchCondition* node = aNode;
       
   154 	if ( aNode->iEnd - aNode->iLeaves <= 1 )
       
   155 		{
       
   156 		if ( aNode->iEnd - aNode->iLeaves == 1 )
       
   157 			{
       
   158 			aNode->iEnd = aNode->iLeaves;
       
   159 			node = aNode->iLeaves[ 0 ];
       
   160 			}
       
   161 		else
       
   162 			node = 0;
       
   163 		delete aNode;
       
   164 		}
       
   165 	return node;
       
   166 	}
       
   167 
       
   168 void CSqlMultiNode::BindL( const RDbTableRow& aSource )
       
   169 	{
       
   170 	__ASSERT( iEnd - iLeaves > 1 );
       
   171 	const TEntry* p = iLeaves;
       
   172 	const TEntry* e = iEnd;
       
   173 	do ( *p++ )->BindL( aSource );
       
   174 		while ( p < e );
       
   175 	}
       
   176 
       
   177 TBool CSqlMultiNode::EvaluateL( const TTextOps& aTextOp ) const
       
   178 	{
       
   179 	__ASSERT( iEnd - iLeaves > 1 );
       
   180 	const TEntry* p = iLeaves;
       
   181 	const TEntry* e = iEnd - 1;			// all except the last sub-node
       
   182 	do
       
   183 		{
       
   184 		TBool b = ( *p++ )->EvaluateL( aTextOp );
       
   185 		if ( NodeType() == EOr )
       
   186 			{
       
   187 			if ( b )
       
   188 				return b;
       
   189 			}
       
   190 		else
       
   191 			{
       
   192 			if ( !b )
       
   193 				return b;
       
   194 			}
       
   195 		} while ( p < e );
       
   196 	return ( *p )->EvaluateL( aTextOp );	// the last subnode
       
   197 	}