os/persistentdata/persistentstorage/dbms/utable/UT_DML.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
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
			}
sl@0
   101
		}
sl@0
   102
	}
sl@0
   103
sl@0
   104
void CSqlValues::WriteL(CDbDataSource& aSource,CDbTable& aTable) const
sl@0
   105
//
sl@0
   106
// Set the row buffer with the values
sl@0
   107
//
sl@0
   108
	{
sl@0
   109
	__ASSERT(iValues.Count()>0);
sl@0
   110
	CDbBlobSpace* blobstore=0;
sl@0
   111
	TInt columns=iValues.Count();
sl@0
   112
	for (TInt ii=0;ii<columns;++ii)
sl@0
   113
		{
sl@0
   114
		TDbColumn col(aSource.Column(ii+1));
sl@0
   115
		const TEntry& e=iValues[ii];
sl@0
   116
		if (TDbCol::IsLong(e.iType))
sl@0
   117
			{	// check if we need to delete a blob
sl@0
   118
			if (!blobstore)
sl@0
   119
				blobstore=aTable.BlobsL();
sl@0
   120
			__ASSERT(blobstore);
sl@0
   121
			const TDbBlob& blob=TDbColumnC(col).Blob();
sl@0
   122
			if (!blob.IsInline())
sl@0
   123
				blobstore->DeleteL(blob.Id());
sl@0
   124
			}
sl@0
   125
		if (e.iValue.IsNull())
sl@0
   126
			{	// null value
sl@0
   127
			col.SetNull();
sl@0
   128
			continue;
sl@0
   129
			}
sl@0
   130
		switch (e.iType)
sl@0
   131
			{
sl@0
   132
		default:
sl@0
   133
			__ASSERT(0);
sl@0
   134
		case EDbColBit:
sl@0
   135
		case EDbColUint8:
sl@0
   136
		case EDbColUint16:
sl@0
   137
		case EDbColUint32:
sl@0
   138
			col.SetL(e.iValue.Uint32());
sl@0
   139
			break;
sl@0
   140
		case EDbColInt8:
sl@0
   141
		case EDbColInt16:
sl@0
   142
		case EDbColInt32:
sl@0
   143
			col.SetL(e.iValue.Int32());
sl@0
   144
			break;
sl@0
   145
		case EDbColInt64:
sl@0
   146
			col.SetL(e.iValue.Int64());
sl@0
   147
			break;
sl@0
   148
		case EDbColReal32:
sl@0
   149
			col.SetL(e.iValue.Real32());
sl@0
   150
			break;
sl@0
   151
		case EDbColReal64:
sl@0
   152
			col.SetL(e.iValue.Real64());
sl@0
   153
			break;
sl@0
   154
		case EDbColDateTime:
sl@0
   155
			col.SetL(e.iValue.Time());
sl@0
   156
			break;
sl@0
   157
		case EDbColText8:
sl@0
   158
			col.SetL(e.iValue.Text8());
sl@0
   159
			break;
sl@0
   160
		case EDbColText16:
sl@0
   161
			col.SetL(e.iValue.Text16());
sl@0
   162
			break;
sl@0
   163
		case EDbColLongText8:
sl@0
   164
			{
sl@0
   165
			const TDesC8& val=e.iValue.Text8();
sl@0
   166
			const TUint8* ptr=val.Ptr();
sl@0
   167
			TInt size=val.Length();
sl@0
   168
			if (size>blobstore->InlineLimit())
sl@0
   169
				col.SetBlobL(blobstore->CreateL(EDbColLongText8,ptr,size),size);
sl@0
   170
			else
sl@0
   171
				col.SetBlobL(ptr,size);
sl@0
   172
			}
sl@0
   173
			break;
sl@0
   174
		case EDbColLongText16:
sl@0
   175
			{
sl@0
   176
			const TDesC16& val=e.iValue.Text16();
sl@0
   177
			const TUint8* ptr=REINTERPRET_CAST(const TUint8*,val.Ptr());
sl@0
   178
			TInt size=val.Length()<<1;
sl@0
   179
			if (size>blobstore->InlineLimit())
sl@0
   180
				col.SetBlobL(blobstore->CreateL(EDbColLongText16,ptr,size),size);
sl@0
   181
			else
sl@0
   182
				col.SetBlobL(ptr,size);
sl@0
   183
			}
sl@0
   184
			break;
sl@0
   185
			}
sl@0
   186
		}
sl@0
   187
	}
sl@0
   188
sl@0
   189
// Class CSqlDMLStatement
sl@0
   190
sl@0
   191
CSqlDMLStatement::~CSqlDMLStatement()
sl@0
   192
	{
sl@0
   193
	delete iValues;
sl@0
   194
	}
sl@0
   195
sl@0
   196
CSqlValues& CSqlDMLStatement::ValuesL()
sl@0
   197
	{
sl@0
   198
	CSqlValues* v=iValues;
sl@0
   199
	if (!v)
sl@0
   200
		iValues=v=new(ELeave) CSqlValues;
sl@0
   201
	return *v;
sl@0
   202
	}
sl@0
   203
sl@0
   204
// Class CSqlInsertStatement
sl@0
   205
sl@0
   206
CSqlInsertStatement* CSqlInsertStatement::NewLC()
sl@0
   207
	{
sl@0
   208
	CSqlInsertStatement* self=new(ELeave) CSqlInsertStatement;
sl@0
   209
	CleanupStack::PushL(self);
sl@0
   210
	return self;
sl@0
   211
	}
sl@0
   212
sl@0
   213
CDbIncremental* CSqlInsertStatement::ExecuteL(CDbTableDatabase& aDatabase,TDbTextComparison aComparison,TInt& aRows)
sl@0
   214
//
sl@0
   215
// Execute an insert-statement. This does not requre incremental work, so return 0
sl@0
   216
//
sl@0
   217
	{
sl@0
   218
	aRows=1;	// 1 row changed after insertion
sl@0
   219
	CSqlQuery* query=&Query();
sl@0
   220
	RDbAccessPlan plan(query,aComparison);
sl@0
   221
	plan.BuildLC(aDatabase,RDbRowSet::EInsertOnly,TDbWindow());
sl@0
   222
	CDbDataSource& src=plan.Source();
sl@0
   223
	Values().BindL(src);
sl@0
   224
	src.NewRowL(KDbNullRecordId);
sl@0
   225
	RDbTransaction& t=plan.Table().Database().Transaction();
sl@0
   226
	t.DMLBeginLC();
sl@0
   227
	Values().WriteL(src,plan.Table());
sl@0
   228
	src.PrepareToWriteRowL(src.EAppend);
sl@0
   229
	src.WriteRowL(src.EAppend,src.ENoSynch);
sl@0
   230
	t.DMLCommitL();
sl@0
   231
	CleanupStack::Pop();				// transaction complete
sl@0
   232
	CleanupStack::PopAndDestroy();		// plan
sl@0
   233
	return 0;	// no incremental work to be done
sl@0
   234
	}
sl@0
   235
sl@0
   236
// Class CDbIncrementalDML
sl@0
   237
sl@0
   238
CDbIncrementalDML* CDbIncrementalDML::NewL(CSqlModifyStatement& aStatement,CDbTableDatabase& aDatabase,TDbTextComparison aComparison)
sl@0
   239
	{
sl@0
   240
	CSqlQuery* query=&aStatement.Query();
sl@0
   241
	RDbAccessPlan plan(query,aComparison);
sl@0
   242
	plan.BuildLC(aDatabase,RDbRowSet::EUpdatable,TDbWindow());
sl@0
   243
	CDbIncrementalDML* self=new(ELeave) CDbIncrementalDML(plan);
sl@0
   244
	CleanupStack::PopAndDestroy();	// plan
sl@0
   245
	if (aStatement.IsUpdate())
sl@0
   246
		{
sl@0
   247
		CleanupStack::PushL(self);
sl@0
   248
		self->iValues=aStatement.AdoptValues();
sl@0
   249
		self->iValues->BindL(*self->iSource);
sl@0
   250
		CleanupStack::Pop();	// self
sl@0
   251
		}
sl@0
   252
	self->iSource->Reset();
sl@0
   253
	self->Transaction().DMLBegin();
sl@0
   254
	self->SetState(EEvaluating);
sl@0
   255
	return self;
sl@0
   256
	}
sl@0
   257
sl@0
   258
CDbIncrementalDML::~CDbIncrementalDML()
sl@0
   259
	{
sl@0
   260
	if (iState!=ECommitted && iState!=EInitialising)
sl@0
   261
		Transaction().DMLRollback();
sl@0
   262
	delete iSource;
sl@0
   263
	delete iValues;
sl@0
   264
	}
sl@0
   265
sl@0
   266
TBool CDbIncrementalDML::NextL(TInt& aRows)
sl@0
   267
	{
sl@0
   268
	__ASSERT(iState!=ECommitted);
sl@0
   269
	if (iState==EFailed)
sl@0
   270
		__LEAVE(KErrDied);
sl@0
   271
	TState s=iState;
sl@0
   272
	iState=EFailed;
sl@0
   273
	TInt work=256;
sl@0
   274
	TDbPosition next=EDbNext;
sl@0
   275
	if (s==EEvaluating)
sl@0
   276
		{	// evaluate the data source
sl@0
   277
		TBool atrow=EFalse;
sl@0
   278
		if (iSource->EvaluateL(work,iRecord,atrow))
sl@0
   279
			{
sl@0
   280
			iState=EEvaluating;
sl@0
   281
			return ETrue;	// more to do
sl@0
   282
			}
sl@0
   283
		iRecord=KDbNullRecordId;
sl@0
   284
		next=EDbFirst;
sl@0
   285
		s=EUpdating;
sl@0
   286
		}
sl@0
   287
	// iterate across the data source
sl@0
   288
	for (;;)
sl@0
   289
		{
sl@0
   290
		if (s==EDeleting)
sl@0
   291
			{
sl@0
   292
			Transaction().DMLBeginLC();
sl@0
   293
			CDbDataSource::TDelete del=iSource->DeleteRowL(iRecord,CDbDataSource::ESynch);
sl@0
   294
			Transaction().DMLCommitL();
sl@0
   295
			CleanupStack::Pop();				// transaction complete
sl@0
   296
			++aRows;
sl@0
   297
			work-=4;
sl@0
   298
			switch (del)
sl@0
   299
				{
sl@0
   300
			case CDbDataSource::EDeletedAtEnd:
sl@0
   301
				Transaction().DMLTouch();
sl@0
   302
				Transaction().DMLCommitL();
sl@0
   303
				iState=ECommitted;
sl@0
   304
				return EFalse;
sl@0
   305
			case CDbDataSource::EDeletedInLimbo:
sl@0
   306
				s=EUpdating;
sl@0
   307
				// coverity[fallthrough]
sl@0
   308
			case CDbDataSource::EDeletedAtNext:
sl@0
   309
				if (work<0)
sl@0
   310
					{	// exhausted
sl@0
   311
					iState=s;
sl@0
   312
					return ETrue;
sl@0
   313
					}
sl@0
   314
				}
sl@0
   315
			}
sl@0
   316
		else
sl@0
   317
			{
sl@0
   318
			switch (iSource->GotoL(work,next,iRecord))
sl@0
   319
				{
sl@0
   320
			default:
sl@0
   321
				__ASSERT(0);
sl@0
   322
			case CDbDataSource::ESuccess:
sl@0
   323
				next=EDbNext;
sl@0
   324
				if (!IsUpdate())
sl@0
   325
					{
sl@0
   326
					s=EDeleting;
sl@0
   327
					break;
sl@0
   328
					}
sl@0
   329
				iSource->ReadRowL(iRecord);
sl@0
   330
				iValues->WriteL(*iSource,iTable);
sl@0
   331
				iSource->PrepareToWriteRowL(CDbDataSource::EReplace);
sl@0
   332
				Transaction().DMLBeginLC();
sl@0
   333
				iSource->WriteRowL(CDbDataSource::EReplace,CDbDataSource::ESynch);
sl@0
   334
				Transaction().DMLCommitL();
sl@0
   335
				CleanupStack::Pop();				// transaction complete
sl@0
   336
				++aRows;
sl@0
   337
				work-=8;
sl@0
   338
				break;
sl@0
   339
			case CDbDataSource::ESynchFailure:
sl@0
   340
				// dead
sl@0
   341
				__LEAVE(KErrDied);
sl@0
   342
			case CDbDataSource::EExhausted:
sl@0
   343
				// more to do
sl@0
   344
				iState=EUpdating;
sl@0
   345
				return ETrue;
sl@0
   346
			case CDbDataSource::ENoRow:
sl@0
   347
				// completed the operation!
sl@0
   348
				Transaction().DMLTouch();
sl@0
   349
				Transaction().DMLCommitL();
sl@0
   350
				iState=ECommitted;
sl@0
   351
				return EFalse;
sl@0
   352
				}
sl@0
   353
			}
sl@0
   354
		}
sl@0
   355
	}
sl@0
   356
sl@0
   357
sl@0
   358
// Class CSqlModifyStatement
sl@0
   359
sl@0
   360
CSqlModifyStatement* CSqlModifyStatement::NewLC()
sl@0
   361
	{
sl@0
   362
	CSqlModifyStatement* self=new(ELeave) CSqlModifyStatement;
sl@0
   363
	CleanupStack::PushL(self);
sl@0
   364
	return self;
sl@0
   365
	}
sl@0
   366
sl@0
   367
CDbIncremental* CSqlModifyStatement::ExecuteL(CDbTableDatabase& aDatabase,TDbTextComparison aComparison,TInt& aRows)
sl@0
   368
//
sl@0
   369
// Execute an update/delete-statement, returning the incremental object that does the work
sl@0
   370
//
sl@0
   371
	{
sl@0
   372
	aRows=0;		// no rows affected initially
sl@0
   373
	return CDbIncrementalDML::NewL(*this,aDatabase,aComparison);
sl@0
   374
	}