function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Steve ChadbournSteve Chadbourn 

SOQL for cloning an object

I'm passed an object id and want to clone it. I'm guessing I need to write a soql query to get an instance of the object then clone it but I don't want to hard code all the field names as they may change. Is there a way to do a select * or a way of getting the object that doesn't involve hard coding?
micwamicwa
You can't do that in SOQL but in Apex:

Function: clone(Boolean opt_preserve_id, Boolean opt_IsDeepClone)

ex.
Code:
Account a = [select... from Account where Id = :AccountId]
Account clonedAccount = a.clone(false, true);

 


Steve ChadbournSteve Chadbourn

Thanks. That's exactly what I want to do.

The problem is that where you typed select... I have to type the name of all the fields I want to clone.There could be a lot in Account. And If I add new ones in the future I will have to update the select statement.

I'm hoping there is a way to do select * or write some DML that can generate a select for me that includes all the fields.

Any ideas anyone?

cheminchemin
Hi Steve,

I'm facing the same situation. Did you find a solution for this?
gregsgregs
here is the code to do what you want.  basically you use the describe metadata api to build a list of fieldnames for the object at runtime.  this will work regardless of what the object type is... the implementation below is in apex, but you can do the same thing in an scontrol or vfpage controller (apex) as well... the example below is for an Account object, but you can change the object type to match the name of your object.
 
Code:
 
    //get object and field describe info
    Schema.DescribeSObjectResult dsoResult = Account.sObjectType.getDescribe();
    Schema.SObjectType. fieldMap = Schema.SObjectType.Account.fields.getMap());
    //build a list of all fieldnames for the object
    List<String> fieldList = getFieldList(fieldMap,false);
    String fieldNames = getFieldNamesFromList(fieldList);
    String q = 'select '+fieldNames+' from Account where Id=\''+acctId+'\'';
                                    
    //guery using dynamic query
    Account acctObj = Database.query(q);
 
    //now sObj above will contain all fields you want and you can get them by
    //referencing them directly, such as String acctName = acctObj.Name;
    ...
 
    public static List<String> getFieldList(
        Map<String,Schema.SObjectField> fieldMap, Boolean selectAllFields)
    {
        List<String> fieldList = new List<String>();
       
        //build dynamic list of fieldnames
        for (String fieldKey : fieldMap.keySet()) {
            Schema.SObjectField fsObj = fieldMap.get(fieldKey);
            Schema.DescribeFieldResult f = fsObj.getDescribe();
            String fieldName = f.getName();
           
            if (selectAllFields) {
                fieldList.add(fieldName);
            } else {
                if (f.getName()=='Id' || f.isNameField() || f.isCustom()) {
                    fieldList.add(fieldName);
                }
            }
        }
       
        return fieldList;
    }
    public static String getFieldNamesFromList(List<String> fieldList) {
        String fieldNames = '';
        for (String field : fieldList) {
            if (fieldNames.length()>0) {
                fieldNames += ',';
            }
            fieldNames += field;
        }
       
        if (fieldNames.length()>10000) {
            throw new ApprovalException('Fieldnames length > 10000 characters');
        }
       
        return fieldNames;
    }
 

 


Message Edited by gregs on 10-02-2008 07:19 AM

Message Edited by gregs on 10-02-2008 07:21 AM

Message Edited by gregs on 10-02-2008 07:22 AM

Message Edited by gregs on 10-02-2008 07:24 AM

Message Edited by gregs on 10-02-2008 07:24 AM
cheminchemin
Thanks for your reply gregs. I tried implementing this code and after some corrections I ended up with a "Dynamic SOQL is not allowed for this org" error (I'm using a developer account).

I figured out a different way to clone and object without going through all the fields: Using the ajax toolkit and a custom button, I force an update on a hidden control field on the record to clone. A trigger attached to it fires, and sends the full record object to an appex class where I just use the clone method. This method makes makes a full copy of the object without iterating through its fields. The new challenge here is to let the user/browser know the id of the new record and automatically navigate to it, so I'm working on it now.
Raghu_devRaghu_dev
Hi, did you find the way to send the response back to user ? I am working something similar to what was on this thread. Any help is appreciated.

Thanks
Raghu

Message Edited by Raghu_dev on 12-03-2008 02:15 PM
cheminchemin
I placed the Id of the new (child) record on a hidden field of the father record. Then used a visual force page to navigate to the new record