os/persistentdata/persistentstorage/dbms/pcdbms/utable/UT_DML.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// SQL DML statements for Table framework
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include "UT_STD.H"
sl@0
    19
sl@0
    20
// Class CSqlValues
sl@0
    21
sl@0
    22
inline CSqlValues::TEntry::TEntry(const RSqlLiteral& aValue)
sl@0
    23
	:iValue(aValue)
sl@0
    24
	{}
sl@0
    25
sl@0
    26
CSqlValues::CSqlValues()
sl@0
    27
	:iValues(EGranularity)
sl@0
    28
	{}
sl@0
    29
sl@0
    30
CSqlValues::~CSqlValues()
sl@0
    31
//
sl@0
    32
// close all the literal objects
sl@0
    33
//
sl@0
    34
	{
sl@0
    35
	for (TInt ii=iValues.Count();--ii>=0;)
sl@0
    36
		iValues[ii].iValue.Close();
sl@0
    37
	iValues.Close();
sl@0
    38
	}
sl@0
    39
sl@0
    40
void CSqlValues::AddL(const RSqlLiteral& aLiteral)
sl@0
    41
	{
sl@0
    42
	TEntry e(aLiteral);
sl@0
    43
	__DEBUG(e.iType=TDbColType(-1);)
sl@0
    44
	__LEAVE_IF_ERROR(iValues.Append(e));
sl@0
    45
	}
sl@0
    46
sl@0
    47
void CSqlValues::BindL(const CDbDataSource& aSource)
sl@0
    48
//
sl@0
    49
// Bind the values to a column set and optional column name list
sl@0
    50
//
sl@0
    51
	{
sl@0
    52
	iValues.Compress();				// we have finished adding values
sl@0
    53
	TInt columns=iValues.Count();
sl@0
    54
	__ASSERT(columns>0);
sl@0
    55
	if (aSource.ColumnCount()<columns)
sl@0
    56
		__LEAVE(KErrArgument);		// insert-statement is bad
sl@0
    57
	for (TInt ii=0;ii<columns;++ii)
sl@0
    58
		{
sl@0
    59
		TEntry& e=iValues[ii];
sl@0
    60
		__ASSERT(e.iType==-1);
sl@0
    61
		e.iType=aSource.ColumnDef(ii+1).Type();
sl@0
    62
		if (e.iValue.IsNull())
sl@0
    63
			continue;
sl@0
    64
		switch (e.iType)
sl@0
    65
			{
sl@0
    66
		default:	// cannot set this kind of column from SQL
sl@0
    67
			__LEAVE(KErrGeneral);
sl@0
    68
			break;
sl@0
    69
		case EDbColBit:
sl@0
    70
		case EDbColUint8:
sl@0
    71
		case EDbColUint16:
sl@0
    72
		case EDbColUint32:
sl@0
    73
			e.iValue.ToUint32L();
sl@0
    74
			break;
sl@0
    75
		case EDbColInt8:
sl@0
    76
		case EDbColInt16:
sl@0
    77
		case EDbColInt32:
sl@0
    78
			e.iValue.ToInt32L();
sl@0
    79
			break;
sl@0
    80
		case EDbColInt64:
sl@0
    81
			e.iValue.ToInt64L();
sl@0
    82
			break;
sl@0
    83
		case EDbColReal32:
sl@0
    84
			e.iValue.ToReal32L();
sl@0
    85
			break;
sl@0
    86
		case EDbColReal64:
sl@0
    87
			e.iValue.ToReal64L();
sl@0
    88
			break;
sl@0
    89
		case EDbColDateTime:
sl@0
    90
			e.iValue.ToTimeL();
sl@0
    91
			break;
sl@0
    92
		case EDbColText8:
sl@0
    93
		case EDbColLongText8:
sl@0
    94
			e.iValue.ToText8L();
sl@0
    95
			break;
sl@0
    96
		case EDbColText16:
sl@0
    97
		case EDbColLongText16:
sl@0
    98
			e.iValue.ToText16L();
sl@0
    99
			break;
sl@0
   100
		case EDbColBinary:
sl@0
   101
		case EDbColLongBinary:
sl@0
   102
			e.iValue.ToBlobL();
sl@0
   103
			break;
sl@0
   104
			}
sl@0
   105
		}
sl@0
   106
	}
sl@0
   107
sl@0
   108
void CSqlValues::WriteL(CDbDataSource& aSource,CDbTable& aTable) const
sl@0
   109
//
sl@0
   110
// Set the row buffer with the values
sl@0
   111
//
sl@0
   112
	{
sl@0
   113
	__ASSERT(iValues.Count()>0);
sl@0
   114
	CDbBlobSpace* blobstore=0;
sl@0
   115
	TInt columns=iValues.Count();
sl@0
   116
	for (TInt ii=0;ii<columns;++ii)
sl@0
   117
		{
sl@0
   118
		TDbColumn col(aSource.Column(ii+1));
sl@0
   119
		const TEntry& e=iValues[ii];
sl@0
   120
		if (TDbCol::IsLong(e.iType))
sl@0
   121
			{	// check if we need to delete a blob
sl@0
   122
			if (!blobstore)
sl@0
   123
				blobstore=aTable.BlobsL();
sl@0
   124
			__ASSERT(blobstore);
sl@0
   125
			const TDbBlob& blob=TDbColumnC(col).Blob();
sl@0
   126
			if (!blob.IsInline())
sl@0
   127
				blobstore->DeleteL(blob.Id());
sl@0
   128
			}
sl@0
   129
		if (e.iValue.IsNull())
sl@0
   130
			{	// null value
sl@0
   131
			col.SetNull();
sl@0
   132
			continue;
sl@0
   133
			}
sl@0
   134
		switch (e.iType)
sl@0
   135
			{
sl@0
   136
		default:
sl@0
   137
			__ASSERT(0);
sl@0
   138
		case EDbColBit:
sl@0
   139
		case EDbColUint8:
sl@0
   140
		case EDbColUint16:
sl@0
   141
		case EDbColUint32:
sl@0
   142
			col.SetL(e.iValue.Uint32());
sl@0
   143
			break;
sl@0
   144
		case EDbColInt8:
sl@0
   145
		case EDbColInt16:
sl@0
   146
		case EDbColInt32:
sl@0
   147
			col.SetL(e.iValue.Int32());
sl@0
   148
			break;
sl@0
   149
		case EDbColInt64:
sl@0
   150
			col.SetL(e.iValue.Int64());
sl@0
   151
			break;
sl@0
   152
		case EDbColReal32:
sl@0
   153
			col.SetL(e.iValue.Real32());
sl@0
   154
			break;
sl@0
   155
		case EDbColReal64:
sl@0
   156
			col.SetL(e.iValue.Real64());
sl@0
   157
			break;
sl@0
   158
		case EDbColDateTime:
sl@0
   159
			col.SetL(e.iValue.Time());
sl@0
   160
			break;
sl@0
   161
		case EDbColText8:
sl@0
   162
			col.SetL(e.iValue.Text8());
sl@0
   163
			break;
sl@0
   164
		case EDbColText16:
sl@0
   165
			col.SetL(e.iValue.Text16());
sl@0
   166
			break;
sl@0
   167
		case EDbColLongText8:
sl@0
   168
			{
sl@0
   169
			const TDesC8& val=e.iValue.Text8();
sl@0
   170
			const TUint8* ptr=val.Ptr();
sl@0
   171
			TInt size=val.Length();
sl@0
   172
			if (size>blobstore->InlineLimit())
sl@0
   173
				col.SetBlobL(blobstore->CreateL(EDbColLongText8,ptr,size),size);
sl@0
   174
			else
sl@0
   175
				col.SetBlobL(ptr,size);
sl@0
   176
			}
sl@0
   177
			break;
sl@0
   178
		case EDbColLongText16:
sl@0
   179
			{
sl@0
   180
			const TDesC16& val=e.iValue.Text16();
sl@0
   181
			const TUint8* ptr=REINTERPRET_CAST(const TUint8*,val.Ptr());
sl@0
   182
			TInt size=val.Length()<<1;
sl@0
   183
			if (size>blobstore->InlineLimit())
sl@0
   184
				col.SetBlobL(blobstore->CreateL(EDbColLongText16,ptr,size),size);
sl@0
   185
			else
sl@0
   186
				col.SetBlobL(ptr,size);
sl@0
   187
			}
sl@0
   188
			break;
sl@0
   189
		case EDbColBinary:
sl@0
   190
			{
sl@0
   191
			const TDesC8& val=e.iValue.Blob();
sl@0
   192
//			const TUint8* ptr=REINTERPRET_CAST(const TUint8*,val.Ptr());
sl@0
   193
//			TInt size=val.Length();
sl@0
   194
			col.SetL(val);
sl@0
   195
//			col.SetBlobL(ptr,size);
sl@0
   196
			}
sl@0
   197
			break;
sl@0
   198
		case EDbColLongBinary:
sl@0
   199
			{
sl@0
   200
			const TDesC8& val=e.iValue.Blob();
sl@0
   201
			const TUint8* ptr=REINTERPRET_CAST(const TUint8*,val.Ptr());
sl@0
   202
			TInt size=val.Length();
sl@0
   203
			col.SetBlobL(blobstore->CreateL(EDbColLongBinary,ptr,size),size);
sl@0
   204
			}
sl@0
   205
			break;
sl@0
   206
			}
sl@0
   207
		}
sl@0
   208
	}
sl@0
   209
sl@0
   210
// Class CSqlDMLStatement
sl@0
   211
sl@0
   212
CSqlDMLStatement::~CSqlDMLStatement()
sl@0
   213
	{
sl@0
   214
	delete iValues;
sl@0
   215
	}
sl@0
   216
sl@0
   217
CSqlValues& CSqlDMLStatement::ValuesL()
sl@0
   218
	{
sl@0
   219
	CSqlValues* v=iValues;
sl@0
   220
	if (!v)
sl@0
   221
		iValues=v=new(ELeave) CSqlValues;
sl@0
   222
	return *v;
sl@0
   223
	}
sl@0
   224
sl@0
   225
// Class CSqlInsertStatement
sl@0
   226
sl@0
   227
CSqlInsertStatement* CSqlInsertStatement::NewLC()
sl@0
   228
	{
sl@0
   229
	CSqlInsertStatement* self=new(ELeave) CSqlInsertStatement;
sl@0
   230
	CleanupStack::PushL(self);
sl@0
   231
	return self;
sl@0
   232
	}
sl@0
   233
sl@0
   234
CDbIncremental* CSqlInsertStatement::ExecuteL(CDbTableDatabase& aDatabase,TDbTextComparison aComparison,TInt& aRows)
sl@0
   235
//
sl@0
   236
// Execute an insert-statement. This does not requre incremental work, so return 0
sl@0
   237
//
sl@0
   238
	{
sl@0
   239
	aRows=1;	// 1 row changed after insertion
sl@0
   240
	CSqlQuery* query=&Query();
sl@0
   241
	RDbAccessPlan plan(query,aComparison);
sl@0
   242
	plan.BuildLC(aDatabase,RDbRowSet::EInsertOnly,TDbWindow());
sl@0
   243
	CDbDataSource& src=plan.Source();
sl@0
   244
	Values().BindL(src);
sl@0
   245
	src.NewRowL(KDbNullRecordId);
sl@0
   246
	RDbTransaction& t=plan.Table().Database().Transaction();
sl@0
   247
	t.DMLBeginLC();
sl@0
   248
	Values().WriteL(src,plan.Table());
sl@0
   249
	src.PrepareToWriteRowL(src.EAppend);
sl@0
   250
	src.WriteRowL(src.EAppend,src.ENoSynch);
sl@0
   251
	t.DMLCommitL();
sl@0
   252
	CleanupStack::Pop();				// transaction complete
sl@0
   253
	CleanupStack::PopAndDestroy();		// plan
sl@0
   254
	return 0;	// no incremental work to be done
sl@0
   255
	}
sl@0
   256
sl@0
   257
// Class CDbIncrementalDML
sl@0
   258
sl@0
   259
CDbIncrementalDML* CDbIncrementalDML::NewL(CSqlModifyStatement& aStatement,CDbTableDatabase& aDatabase,TDbTextComparison aComparison)
sl@0
   260
	{
sl@0
   261
	CSqlQuery* query=&aStatement.Query();
sl@0
   262
	RDbAccessPlan plan(query,aComparison);
sl@0
   263
	plan.BuildLC(aDatabase,RDbRowSet::EUpdatable,TDbWindow());
sl@0
   264
	CDbIncrementalDML* self=new(ELeave) CDbIncrementalDML(plan);
sl@0
   265
	CleanupStack::PopAndDestroy();	// plan
sl@0
   266
	if (aStatement.IsUpdate())
sl@0
   267
		{
sl@0
   268
		CleanupStack::PushL(self);
sl@0
   269
		self->iValues=aStatement.AdoptValues();
sl@0
   270
		self->iValues->BindL(*self->iSource);
sl@0
   271
		CleanupStack::Pop();	// self
sl@0
   272
		}
sl@0
   273
	self->iSource->Reset();
sl@0
   274
	self->Transaction().DMLBegin();
sl@0
   275
	self->SetState(EEvaluating);
sl@0
   276
	return self;
sl@0
   277
	}
sl@0
   278
sl@0
   279
CDbIncrementalDML::~CDbIncrementalDML()
sl@0
   280
	{
sl@0
   281
	if (iState!=ECommitted && iState!=EInitialising)
sl@0
   282
		Transaction().DMLRollback();
sl@0
   283
	delete iSource;
sl@0
   284
	delete iValues;
sl@0
   285
	}
sl@0
   286
sl@0
   287
TBool CDbIncrementalDML::NextL(TInt& aRows)
sl@0
   288
	{
sl@0
   289
	__ASSERT(iState!=ECommitted);
sl@0
   290
	if (iState==EFailed)
sl@0
   291
		__LEAVE(KErrDied);
sl@0
   292
	TState s=iState;
sl@0
   293
	iState=EFailed;
sl@0
   294
	TInt work=256;
sl@0
   295
	TDbPosition next=EDbNext;
sl@0
   296
	if (s==EEvaluating)
sl@0
   297
		{	// evaluate the data source
sl@0
   298
		TBool atrow=EFalse;
sl@0
   299
		if (iSource->EvaluateL(work,iRecord,atrow))
sl@0
   300
			{
sl@0
   301
			iState=EEvaluating;
sl@0
   302
			return ETrue;	// more to do
sl@0
   303
			}
sl@0
   304
		iRecord=KDbNullRecordId;
sl@0
   305
		next=EDbFirst;
sl@0
   306
		s=EUpdating;
sl@0
   307
		}
sl@0
   308
	// iterate across the data source
sl@0
   309
	for (;;)
sl@0
   310
		{
sl@0
   311
		if (s==EDeleting)
sl@0
   312
			{
sl@0
   313
			Transaction().DMLBeginLC();
sl@0
   314
			CDbDataSource::TDelete del=iSource->DeleteRowL(iRecord,CDbDataSource::ESynch);
sl@0
   315
			Transaction().DMLCommitL();
sl@0
   316
			CleanupStack::Pop();				// transaction complete
sl@0
   317
			++aRows;
sl@0
   318
			work-=4;
sl@0
   319
			switch (del)
sl@0
   320
				{
sl@0
   321
			case CDbDataSource::EDeletedAtEnd:
sl@0
   322
				Transaction().DMLTouch();
sl@0
   323
				Transaction().DMLCommitL();
sl@0
   324
				iState=ECommitted;
sl@0
   325
				return EFalse;
sl@0
   326
			case CDbDataSource::EDeletedInLimbo:
sl@0
   327
				s=EUpdating;
sl@0
   328
			case CDbDataSource::EDeletedAtNext:
sl@0
   329
				if (work<0)
sl@0
   330
					{	// exhausted
sl@0
   331
					iState=s;
sl@0
   332
					return ETrue;
sl@0
   333
					}
sl@0
   334
				}
sl@0
   335
			}
sl@0
   336
		else
sl@0
   337
			{
sl@0
   338
			switch (iSource->GotoL(work,next,iRecord))
sl@0
   339
				{
sl@0
   340
			default:
sl@0
   341
				__ASSERT(0);
sl@0
   342
			case CDbDataSource::ESuccess:
sl@0
   343
				next=EDbNext;
sl@0
   344
				if (!IsUpdate())
sl@0
   345
					{
sl@0
   346
					s=EDeleting;
sl@0
   347
					break;
sl@0
   348
					}
sl@0
   349
				iSource->ReadRowL(iRecord);
sl@0
   350
				iValues->WriteL(*iSource,iTable);
sl@0
   351
				iSource->PrepareToWriteRowL(CDbDataSource::EReplace);
sl@0
   352
				Transaction().DMLBeginLC();
sl@0
   353
				iSource->WriteRowL(CDbDataSource::EReplace,CDbDataSource::ESynch);
sl@0
   354
				Transaction().DMLCommitL();
sl@0
   355
				CleanupStack::Pop();				// transaction complete
sl@0
   356
				++aRows;
sl@0
   357
				work-=8;
sl@0
   358
				break;
sl@0
   359
			case CDbDataSource::ESynchFailure:
sl@0
   360
				// dead
sl@0
   361
				__LEAVE(KErrDied);
sl@0
   362
			case CDbDataSource::EExhausted:
sl@0
   363
				// more to do
sl@0
   364
				iState=EUpdating;
sl@0
   365
				return ETrue;
sl@0
   366
			case CDbDataSource::ENoRow:
sl@0
   367
				// completed the operation!
sl@0
   368
				Transaction().DMLTouch();
sl@0
   369
				Transaction().DMLCommitL();
sl@0
   370
				iState=ECommitted;
sl@0
   371
				return EFalse;
sl@0
   372
				}
sl@0
   373
			}
sl@0
   374
		}
sl@0
   375
	}
sl@0
   376
sl@0
   377
sl@0
   378
// Class CSqlModifyStatement
sl@0
   379
sl@0
   380
CSqlModifyStatement* CSqlModifyStatement::NewLC()
sl@0
   381
	{
sl@0
   382
	CSqlModifyStatement* self=new(ELeave) CSqlModifyStatement;
sl@0
   383
	CleanupStack::PushL(self);
sl@0
   384
	return self;
sl@0
   385
	}
sl@0
   386
sl@0
   387
CDbIncremental* CSqlModifyStatement::ExecuteL(CDbTableDatabase& aDatabase,TDbTextComparison aComparison,TInt& aRows)
sl@0
   388
//
sl@0
   389
// Execute an update/delete-statement, returning the incremental object that does the work
sl@0
   390
//
sl@0
   391
	{
sl@0
   392
	aRows=0;		// no rows affected initially
sl@0
   393
	return CDbIncrementalDML::NewL(*this,aDatabase,aComparison);
sl@0
   394
	}