Backup of edited records

I need backup edited records, so I do:

var editedRecs = databaseManager.getEditedRecords( foundset[ relation ] );

After that I call:

databaseManager.revertEditedRecords( foundset[ relation ] );

The problem is, that also the contents of the backup array editedRecs is reverted. This also occurs if I copy the array to another array. Cause the array contains jsrecords, it seems that the jsrecord has a reference to the original edited records.

Why has this a reference to the original? How can I copy the edited records and unrelate them from the original records?

this is logical, the records you hold on to are exactly the same record that gets reverted (if you do record.value = x you want that it really will change the actual value of the ‘real’ record)
If you really want to keep the data you have to loop over the records
and copy the record.getChangedData() into an array instead of the record itself.

Easy way to duplicate a record:

// get foundset of source record
var serverName = srcRecord.foundset.getServerName()
var tableName = srcRecord.foundset.getTableName()
var fsThis = databaseManager.getFoundSet(serverName,tableName)

// create duplicate record and copy data
var destRecord = fsThis.getRecord(fsThis.newRecord(false,true))
databaseManager.copyMatchingFields(srcRecord,destRecord,overwriteOK[0] || false)

Use a different destination foundset (with identical fields) to archive records.

http://community.data-sutra.com/project … s.js#L4279 for a utility function that copies a record and all related records (Servoy 3 to 5 era code but it still works).

jcompagner:
this is logical, the records you hold on to are exactly the same record that gets reverted (if you do record.value = x you want that it really will change the actual value of the ‘real’ record)

Why is there no ‘virtual’ record, that has no binding to the database / memory or to the record stored in the database / memory. I think it is really useful, if this would be possible and the possibility to override the record in the database with the ‘virtual’ record (only for values that can not cause data inconsistencies).

jcompagner:
If you really want to keep the data you have to loop over the records
and copy the record.getChangedData() into an array instead of the record itself.

I found this solution, but it would be great if Servoy has a built in function for this.

/**
 * Backup record changes for later reusing if they needed.
 * 
 * @param {String} formName , the name of the form to get the foundset for backup the record changes.
 * @param {String} foundSet , the foundset or relation name to backup its changes.
 * @param {String} uid , a column name as unique record identifier in the context of the record in the foundset.
 * 
 * @return {Array<Array<Array<Object>>>} the array with the changed values for the records and "null" if there are no changed record values.
 *
 * @public
 * @since 02.10.2013
 * @version 04.10.2013 14:11:36
 *
 * @author deezzub
 */
function backupRecordChanges( formName, foundSet, uid ) {
	var changedData,
		changedRow,
		editedRec,
		editedRecs,
		/** @type {JSFoundSet} */
		fs = forms[ formName ][ foundSet ],
		recBackup,
		recsBackup = [ ],
		recUid;

	if ( databaseManager.hasRecordChanges( fs ) ) {

		editedRecs = databaseManager.getEditedRecords( fs );

		for ( var recIndex = 0; recIndex < editedRecs.length; recIndex++ ) {
			/** @type {JSRecord} */
			editedRec = editedRecs [ recIndex ],
			changedData = editedRec.getChangedData( ),
			recBackup = [ ],
			recUid = editedRecs [ recIndex ][ uid ];

			for ( var rowIndex = 1; rowIndex <= changedData.getMaxRowIndex( ); rowIndex++ ) {
				changedRow = [ ];
                                for ( var columnIndex = 1; columnIndex <= 3; columnIndex++ ) {

					changedRow[ columnIndex - 1 ] = changedData.getValue( rowIndex, columnIndex );
				}
				recBackup[ 0 ] = recUid;
				recBackup[ rowIndex ] = changedRow
			}
			recsBackup[ recIndex ] = recBackup;
		}
	} else {
		recsBackup = null;
	}
	return recsBackup;
}

david:
Easy way to duplicate a record:

// get foundset of source record

var serverName = srcRecord.foundset.getServerName()
var tableName = srcRecord.foundset.getTableName()
var fsThis = databaseManager.getFoundSet(serverName,tableName)

// create duplicate record and copy data
var destRecord = fsThis.getRecord(fsThis.newRecord(false,true))
databaseManager.copyMatchingFields(srcRecord,destRecord,overwriteOK[0] || false)




Use a different destination foundset (with identical fields) to archive records.

<a class="postlink" href="http://community.data-sutra.com/projects/datasutra/repository/entry/trunk/_ds_CODE_resources/globals.js#L4279">http://community.data-sutra.com/project ... s.js#L4279</a> for a utility function that copies a record and all related records (Servoy 3 to 5 era code but it still works).

Can I use the following to get a foundset, that has the edited records, but it’s not changed if I changed the source foundset?

var fsCopy = foundset[ relation ].duplicateFoundSet();
fsCopy.unrelate();

deezzub:
Can I use the following to get a foundset, that has the edited records, but it’s not changed if I changed the source foundset?

var fsCopy = foundset[ relation ].duplicateFoundSet();

fsCopy.unrelate();

I think you are getting confused with what “duplicate” at the foundset level means. Foundsets are their own scriptable objects that just so happen to have records in them. So foundset.duplicateFoundSet() and foundset.unrelate() do not do anything to the actual records in the foundset record collection – they just give you a “new” foundset object with potentially different record collection characteristics (ie. total number) and selected index.

The most common usage for duplicateFoundset() is to duplicate a foundset just prior to doing a search on a foundset. If the search returns no records, you can restore the visible foundset (that now contains zero records because of the search operation) with the previously duplicated foundset (which has the original record set). (https://wiki.servoy.com/display/DOCS/JS … teFoundSet.)

If you want to duplicated the records in a foundset, you have to iterate over those records and copy/duplicate individually. All of this follows javascript object duplication rules so it’s standard stuff.

I have a related question. Let’s say I have a related foundset of unpaid invoices that looks like this:

customerRecord.customers_to_unpaid_invoices

And now I want to do a 2-phase process on those invoice records.

Phase 1: mark the invoices as ‘paid’
Phase 2: print the invoice numbers in a log file.

If I work directly that foundset, I won’t be able to do phase 2 because the records will fall out of the foundset as I mark them ‘paid’.

So I want to create an unrelated foundset that contains the same records, and work with that foundset.

I have tried

var newFoundset = customerRecord.customers_to_unpaid_invoices.duplicateFoundset()
newFoundset.unrelate()

but newFoundset still loses records as I mark invoices ‘paid’. I am wondering if unrelate() only works on form foundsets. and not on foundset objects held in javascript vars.

So I ended up doing this:

	var ds =  databaseManager.convertToDataSet(customerRecord.customers_to_unpaid_invoices,['invoice_id'])
	var newFoundset = databaseManager.getFoundSet('myServer','invoices')
	newFoundset.loadRecords(ds)

which works fine. Was there a way of doing this using duplication and/or unrelate that I just haven’t figured out?

try this:

var newFoundset = customerRecord.customers_to_unpaid_invoices.unrelate();

Thanks Johan that worked.

In the Wiki, the sample code shown for how to use unrelate() is this:

forms.customer.foundset.unrelate()

In the Serclipse IDE the sample code is:

foundset.unrelate()

These examples make it seem like unrelate() ACTS ON the foundset, converting it to an unrelated foundset. It would be a bit clearer if the examples were more like this:

var newFoundset = forms.customer.foundset.unrelate();

I’ve added this suggestion in the support system.

Talking to Johan Compagner at ServoyCamp last month I learned a bit more about the .unrelate() method that I thought I’d share what I learned.

when you do this:

var newFoundset = relatedFoundset.unrelate();

your newFoundset will stop behaving like a related foundset, and will start behaving like a foundset that was created using find/search. What does this mean?

Related foundsets are of course based on relations. Servoy ensures that a related foundset always contains EXACTLY the records that match the relation. After you’ve created a related foundset, Servoy monitors the db and if it sees new records that meet the relation’s criteria, it will automatically add them to the foundset. Similarly, records that started out in the related foundset will drop out of it automatically if they are modified in such a way that they no longer meet the criteria set out in the relation.

But for UNrelated foundsets, Servoy does not do that management. If you modify a record in an UNrelated foundset such that it no longer matches the find/search criteria, it won’t automatically drop out of the foundset. If after creating an UNrelated foundset you create new records that match the find/search criteria, they will not be added to the UNrelated foundset automatically. If you modify existing records such that they now match the find/search criteria where they didn’t before, they will NOT be automatically added to the foundset. To refresh your UNrelated foundset to take all such changes into account, you would need to do a loadRecords(). Servoy remembers the query that it used to build the foundset in the first place, so it just re-runs that query.

You can see a foundset’s query anytime by doing databaseManager.getSQL(foundset)

Finally, on an UNrelated foundset, loadAllRecords() will load ALL records in the source table, whereas on a related foundset, loadAllRecords() loads all the related records as defined in the relation. This is useful if you’ve reduced your related foundset by performing a find/search on it, and now want to get back all your related records.

I hope some people find this helpful. And if you see any errors in what I’ve said please let me know!

Totally correct! :-)