[CDO] CDO version/history/revision functionality [message #1002602] |
Fri, 18 January 2013 23:15 |
Andrew Whelan Messages: 71 Registered: October 2012 Location: Syracuse NY |
Member |
|
|
Hello,
I have some questions about the versioning/history functionality that comes with CDO. I am using a DBStore store with a MySQL database. What we are looking for is being able to recover a history of a certain object (CDOObject). We'll use a Company object for the sake of demonstration (the code below is for demonstration, it's not something that I'm running so if you see something that looks a little off....).
CDOTransaction transaction = cdoSession.openTransaction();
CDOResource resource = transaction
.getOrCreateResource("/repo1");
Company company = CompanyFactory.eINSTANCE.createCompany();
Company.setName("Andrew's 1st company");
Company.setCity("Paris");
resource.getContents().add(company);
transaction.commit();
....the below code in some other function retrieves it and updates....
CDOTransaction transaction = cdoSession.openTransaction();
CDOResource resource = transaction.getOrCreateResource("/repo1");
EList<EObject> list = resource.getContents();
for(EObject e : list)
{
CompanyImpl company = (CompanyImpl)e;
If(company.getName().equals("Andrew's 1st company"))
{
company.setCity("Berlin");
}
}
transaction.commit();
So now we should have 2 versions of this Company object in the database.
Say we make a couple of more updates to this Company record's city (2 more would make 4 versions). The CDOID will be the same and uniquely identifiers it (please let me know if this is not the case. I'm fairly certain I read that a CDOID is unique for a repository ("/repo1" in this case)).
At some time in the future when I am working with the latest version of the Company object (named in our example above "Andrew's 1st company"), I would like to get a list of the Company objects so I can display the historical information for each version in a separate screen. I looked through the CDORevision and CDOView documentation as well as the test code and am having a difficult time determining how to do this.
One of the things I did try was using the CDOQuery functionality:
CDOID cdoID = company.cdoID();
id = CDOIDUtil.getLong(cdoID);
//NOTE: I was able to retrieve a list of cdo_version values that were associated with
//cdo_id = id. Looping through the cdo_version values, storing them in an int version
//variable, we have the following code snippet
CDOQuery query =
transaction.createQuery("sql",
"select cdo_id from <repository name>.company_model_company where cdo_version=:version and cdo_id=:id");
query.setParameter("version", version);
query.setParameter("id",id);
List<Company> companies = query.getResult(Company.class);
Doing this I do get a company/CDOObject object back but it is always the latest version. The cdo_version value in the above query seems to have no effect. I think part of the problem would be that the past versions are not available through a read/write object view?
So the question I need answered is, how do I do what I am trying to do with CDO in the dialog above?
Thanks
-Andrew
PS: The correct way to go from a CDOObject to the deltas of the revisions would be good to know also. Again I saw that there was delta functionality but am not sure how to get there from a CDOObject that I have obtained from the database.
|
|
|
Re: [CDO] CDO version/history/revision functionality [message #1002699 is a reply to message #1002602] |
Sat, 19 January 2013 06:24 |
|
Am 19.01.2013 00:15, schrieb Andrew Whelan:
> Hello,
>
> I have some questions about the versioning/history functionality that comes with CDO. I am using a DBStore store with
> a MySQL database. What we are looking for is being able to recover a history of a certain object (CDOObject).
If by "recover" you mean "revert a certain object to a certain historical state" that can be problematic because
referential integrity is not easy to ensure. A former committer has left this controversial enhancement request:
260036: Provide "revert to the history revision" operation
https://bugs.eclipse.org/bugs/show_bug.cgi?id=260036
> We'll use a Company object for the sake of demonstration (the code below is for demonstration, it's not something that
> I'm running so if you see something that looks a little off....).
>
>
> CDOTransaction transaction = cdoSession.openTransaction();
> CDOResource resource = transaction
> .getOrCreateResource("/repo1"); Company company = CompanyFactory.eINSTANCE.createCompany();
> Company.setName("Andrew's 1st company");
> Company.setCity("Paris");
> resource.getContents().add(company);
> transaction.commit();
>
>
>
> ...the below code in some other function retrieves it and updates....
>
> CDOTransaction transaction = cdoSession.openTransaction();
> CDOResource resource = transaction.getOrCreateResource("/repo1");
> EList<EObject> list = resource.getContents();
>
> for(EObject e : list)
> {
> CompanyImpl company = (CompanyImpl)e;
> If(company.getName().equals("Andrew's 1st company"))
> {
> company.setCity("Berlin");
> }
> }
> transaction.commit();
>
>
> So now we should have 2 versions of this Company object in the database.
> Say we make a couple of more updates to this Company record's city (2 more would make 4 versions). The CDOID will be
> the same and uniquely identifiers it (please let me know if this is not the case. I'm fairly certain I read that a
> CDOID is unique for a repository ("/repo1" in this case)).
Totally correct. The CDOID is unique for a CDOObject in an IRepository. All CDORevisions (in both time and branch
dimensions) of this CDOObject share the same CDOID.
> At some time in the future when I am working with the latest version of the Company object (named in our example above
> "Andrew's 1st company"), I would like to get a list of the Company objects so I can display the historical information
> for each version in a separate screen.
That's possible but let's see if that (historical *CDOObjects* ) is really what you want...
> I looked through the CDORevision and CDOView documentation as well as the test code and am having a difficult time
> determining how to do this. One of the things I did try was using the CDOQuery functionality:
>
>
> CDOID cdoID = company.cdoID();
> id = CDOIDUtil.getLong(cdoID);
Note that this last statement makes your code kind of depend on the DBStore. The same is true for your SQL query below.
> //NOTE: I was able to retrieve a list of cdo_version values that were associated with //cdo_id = id. Looping through
> the cdo_version values, storing them in an int version
> //variable, we have the following code snippet
>
> CDOQuery query = transaction.createQuery("sql", "select cdo_id from <repository
> name>.company_model_company where cdo_version=:version and cdo_id=:id");
That looks like a NOOP: "select id where id=123"
> query.setParameter("version", version);
> query.setParameter("id",id);
>
> List<Company> companies = query.getResult(Company.class);
This query is bound to your transaction that you opened the query upon. It can only return CDOObjects that are valid in
this transaction (i.e. the latest state of the transaction's branch).
> Doing this I do get a company/CDOObject object back but it is always the latest version. The cdo_version value in the
> above query seems to have no effect.
Of course not, as we've seen above.
> I think part of the problem would be that the past versions are not available through a read/write object view?
Yes, that's part of the problem. A CDOTransaction (and all CDOQueries from this transaction) always return CDOObjects
that are "wired" with the latest CDORevisions from the transaction's branch.
> So the question I need answered is, how do I do what I am trying to do with CDO in the dialog above?
What dialog?
Let's clarify a few core concepts:
A CDOView or CDOTransaction provides *consistent* access to the CDOObject *graph* at a certain point in time in a
certain branch (e.g. the MAIN branch). You can navigate this graph through EMF API and will never leave this
time/branch. A CDOTransaction always "looks" at the latest time in its branch, while a pure CDOView can "wind back
time". Views and transactions are *revision selectors* , where a revision is the state of a *single* object for a
certain period of time in a certain branch.
With a transaction you can modify the object graph atomically. The transitions between two consecutive commits are
described by CDOCommitInfos. They're returned from transaction.commit() and can later be recreated, e.g., through
session.getCommitInfoManager() methods. It's often more convenient to use the newer CDOCommitHistory or CDOObjectHistory
APIs as returned by implementations of CDOCommitHistory.Provider. A commit history is an ordered collection of
CDOCommitInfos (also used by our CDOHistoryPage contribution to the Eclipse "History" view part). The availablity of
historical commit infos and the cost to recreate them may depend on the used IStore.
CDOCommitInfos contain/provide the *deltas* between two consecutive sets of CDORevisions (the *states* of relevant
objects before and after a commit). They know nothing about CDOViews, CDOTransactions or CDOObjects (other than their
CDOIDs). But you can always turn a CDOID into a CDOObject (and the associated object graph) by opening a CDOView at the
time and branch that's associated with the CDOCommitInfo (and all its deltas and resulting revisions). That's what we do
in our EMF Compare integration as you can see by double clicking a commit info in the CDOHistoryPage.
Sounds complex? Maybe others can put it simpler ;-)
>
> Thanks
> -Andrew
>
> PS: The correct way to go from a CDOObject to the deltas of the revisions would be good to know also.
In CDO 4.2:
CDOObjectHistory history = cdoObject.cdoHistory();
Note that a history is an IContainer<CDOCommitInfo>.
> Again I saw that there was delta functionality but am not sure how to get there from a CDOObject that I have obtained
> from the database.
See above. No need to depend on the/a database.
Cheers
/Eike
----
http://www.esc-net.de
http://thegordian.blogspot.com
http://twitter.com/eikestepper
Cheers
/Eike
----
http://www.esc-net.de
http://thegordian.blogspot.com
http://twitter.com/eikestepper
|
|
|
|
|
|
Re: [CDO] CDO version/history/revision functionality [message #1005356 is a reply to message #1005342] |
Fri, 25 January 2013 04:35 |
|
Am 25.01.2013 00:01, schrieb Andrew Whelan:
> Please see the following code. Reference extends CDOObject. We have an Ecore model. We generate our code from the
> ecore model.
> We use the CDO reflective migration to insert the CDO layer (CDOObject) between Reference and EObject.
Ok. In case you don't generate your models for CDO you can get the CDOObject for a "legacy" EObject with
CDOUtil.getCDOObject(eObject).
>
> The "id" parameter in the getReference method below is obtained in a call like the following:
>
>
> long id = CDOIDUtil.getLong(reference.cdoID());
I already told you that something in your implementation is likely "not so good" if you feel the need to convert a CDOID
to a long integer value. You lose (storage) portability by doing so. All client-side (and the generic server-side) APIs
take/use CDOIDs directly. Only store implementations and their tests make assumptions about the internal CDOID format.
> where reference is an instance of a Reference object. Now I need to figure out how to get the correct timestamp value
> for original and subsequent records in the database so I can look at historical versions.
>
> So lets say we use a CDOTransaction to commit a certain Reference object to the database. For a new object, what is
> the best way to obtain the correct timestamp to reflect when the object is created in the database.
Directly after committing:
transaction.commit().getTimeStamp();
or at any time later:
object.cdoRevision().getTimeStamp();
The latter call gives you the time of the revision that's currently valid/visible in the view was created/committed.
> Would it be using cdo_created from the database?
Accessing the database directly should be the last resort only.
> Or reference.cdoRevision().getTimeStamp()? Which value is this last one returning? reference.cdo_created or
> reference.cdo_revised?
cdo_created.
> How do I get the correct timestamp value to, in the future, return the correct Reference (CDOObject) from the
> following method for the originally created record?
I don't seem to understand this question. For a given *CDOObject* (and with auduting enabled in the server) you can
access any *revision* with these methods:
CDOUtil.getRevisionByVersion(CDOObject, int)
CDOUtil.getRevisionByVersion(CDOObject, CDOBranch, int)
If you need the "CDOObjects" for these *revisions* you must open audit views for the time stamps of these revisions:
int version = 1;
CDOView audit = object.cdoView().getSession.openView(CDOUtil.getRevision(object, version).getTimeStamp());
CDOObject oldObject = audit.getObject(object);
> How do I get the correct value for a subsequent version that may not be the current version.
int version = 1 + i;
...
> We do need a CDOObject even if we shouldn't be editing it. We just won't edit it. We need a CDOObject because
> Reference extends CDOObject.
>
>
>
> public Reference getReference(long id, long timestamp)
> {
> Reference ret = null;
> try
> {
> CDOView audit = session.openView(timestamp);
> CDOResource auditResource = audit.getResource("/repo1");
> if((auditResource!=null) && (auditResource.getContents()!=null))
> { for(EObject e : auditResource.getContents())
No, that's bad.
> {
> Reference o = (Reference)e; if(id == CDOIDUtil.getLong(o.cdoID())){
That's worse ;-)
Cheers
/Eike
----
http://www.esc-net.de
http://thegordian.blogspot.com
http://twitter.com/eikestepper
> ret = o;
> break;
> }
> }
> }
> }
> catch(Exception e)
> {
> e.printStackTrace();
> }
> return ret;
> }
>
> Thanks! Sorry for being such a newbie.
Cheers
/Eike
----
http://www.esc-net.de
http://thegordian.blogspot.com
http://twitter.com/eikestepper
|
|
|
|
Re: [CDO] CDO version/history/revision functionality [message #1007421 is a reply to message #1007368] |
Tue, 05 February 2013 19:17 |
|
Am 05.02.2013 17:14, schrieb Andrew Whelan:
> What is the best way to deterime how many revisions there are for a particular CDOID?
>
> The following is not portable, as Eike has stated. Is there a portable way to do what I am trying to do here?
> long id = CDOIDUtil.getLong(referenceObject.cdoID());
> CDOQuery query = transaction.createQuery("sql",
> "select count(*) from project_schema.reference_reference where cdo_id=:id");
> query.setParameter("id", id);
> query.setParameter("cdoObjectQuery", false);
> List<Long> count = query.getResult(Long.class);
You can ask for the version of the latest revision of an object by
a) If you have a view/transaction open: view.getObject(id).cdoRevision().getVersion() or
b) by using the revision manager: session.getRevisionManager().getRevision(id, mainBranch.getHead(), ...).getVersion()
If you only use one branch (the main branch) that version is equal to the number of revisions of that object.
Cheers
/Eike
----
http://www.esc-net.de
http://thegordian.blogspot.com
http://twitter.com/eikestepper
Cheers
/Eike
----
http://www.esc-net.de
http://thegordian.blogspot.com
http://twitter.com/eikestepper
|
|
|
Powered by
FUDForum. Page generated in 0.03810 seconds