CRM-20237 Event pricesets copied with long suffix cause DB error

    Details

    • Type: Bug
    • Status: Done/Fixed
    • Priority: Critical
    • Resolution: Fixed/Completed
    • Affects Version/s: 4.7.15
    • Fix Version/s: 4.7.25
    • Component/s: None
    • Labels:
      None
    • Versioning Impact:
      Patch (backwards-compatible bug fixes)
    • Documentation Required?:
      None
    • Funding Source:
      Contributed Code
    • Verified?:
      No

      Description

      Hi all,

      A client with a lot of events just ran into this Civi error while adding her latest event:
      "DB Error: already exists."

      When I looked at the error log I found this:
      {{Mar 08 16:33:29 [info] $Fatal Error Details = Array
      (
      [callback] => Array
      (
      [0] => CRM_Core_Error
      [1] => handle
      )

      [code] => -5
      [message] => DB Error: already exists
      [mode] => 16
      [debug_info] => INSERT INTO civicrm_price_set (name , title , is_active , extends , financial_type_id , is_quick_config , is_reserved , min_amount ) VALUES ('cle_event_template_Copy_id_73_Copy_id_82_Copy_id_85_Copy_id_99_Copy_id_106_Copy_id_107_Copy_id_111_Copy_id_112_Copy_id_113_Copy_id_125_Copy_id_126_Copy_id_130_Copy_id_131_Copy_id_136_Copy_id_137_Copy_id_138_Copy_id_139_Copy_id_141' , 'CLE Event Template [Copy id 73] [Copy id 82] [Copy id 85] [Copy id 99] [Copy id 106] [Copy id 107] [Copy id 111] [Copy id 112] [Copy id 113] [Copy id 125] [Copy id 126] [Copy id 130] [Copy id 131] [Copy id 136] [Copy id 137] [Copy id 138] [Copy id 139] [Copy id 141]' , 1 , '1' , 4 , 1 , 0 , 0 ) [nativecode=1062 ** Duplicate entry 'cle_event_template__Copy_id_73___Copy_id_82___Copy_id_85___Copy_' for key 'UI_name']
      [type] => DB_Error
      [user_info] => INSERT INTO civicrm_price_set (name , title , is_active , extends , financial_type_id , is_quick_config , is_reserved , min_amount ) VALUES ('cle_event_template_Copy_id_73_Copy_id_82_Copy_id_85_Copy_id_99_Copy_id_106_Copy_id_107_Copy_id_111_Copy_id_112_Copy_id_113_Copy_id_125_Copy_id_126_Copy_id_130_Copy_id_131_Copy_id_136_Copy_id_137_Copy_id_138_Copy_id_139_Copy_id_141' , 'CLE Event Template [Copy id 73] [Copy id 82] [Copy id 85] [Copy id 99] [Copy id 106] [Copy id 107] [Copy id 111] [Copy id 112] [Copy id 113] [Copy id 125] [Copy id 126] [Copy id 130] [Copy id 131] [Copy id 136] [Copy id 137] [Copy id 138] [Copy id 139] [Copy id 141]' , 1 , '1' , 4 , 1 , 0 , 0 ) [nativecode=1062 ** Duplicate entry 'cle_event_template__Copy_id_73___Copy_id_82___Copy_id_85___Copy_' for key 'UI_name']
      [to_string] => [db_error: message="DB Error: already exists" code=-5 mode=callback callback=CRM_Core_Error::handle prefix="" info="INSERT INTO civicrm_price_set (name , title , is_active , extends , financial_type_id , is_quick_config , is_reserved , min_amount ) VALUES ('cle_event_template_Copy_id_73_Copy_id_82_Copy_id_85_Copy_id_99_Copy_id_106_Copy_id_107_Copy_id_111_Copy_id_112_Copy_id_113_Copy_id_125_Copy_id_126_Copy_id_130_Copy_id_131_Copy_id_136_Copy_id_137_Copy_id_138_Copy_id_139_Copy_id_141' , 'CLE Event Template [Copy id 73] [Copy id 82] [Copy id 85] [Copy id 99] [Copy id 106] [Copy id 107] [Copy id 111] [Copy id 112] [Copy id 113] [Copy id 125] [Copy id 126] [Copy id 130] [Copy id 131] [Copy id 136] [Copy id 137] [Copy id 138] [Copy id 139] [Copy id 141]' , 1 , '1' , 4 , 1 , 0 , 0 ) [nativecode=1062 ** Duplicate entry 'cle_event_template__Copy_id_73___Copy_id_82___Copy_id_85___Copy_' for key 'UI_name']"]
      )}}

      It looks like every time a priceset is copied from an event, the word "Copy_id" is getting added to the name and title fields of the civicrm_price_set table. However, the `title` field is only 255 characters long and must be unique. So at a certain point when the string of copy_id_##copy_id## gets too long and becomes truncated, the values are no-longer identical.

      I found that I could do a preg_replace() and delete the old "Copy" text before Civi tries to add on a new suffix.

      Here is my fix below, but maybe someone with more Civi knowledge than me can check if it is indeed the best solution or if there should be something else.

      civicrm/CRM/Core/DAO.php @ Line 1507

              if (isset($fieldsToSuffix[$dbName])) {
                /* preg_replace to remove old copy suffix first */
                $pattern = '/__Copy_id_\d+_$/';
                $newObject->$dbName = preg_replace($pattern, "", $newObject->$dbName);
      
                $pattern = '/\[Copy id \d+\]$/';
                $newObject->$dbName = preg_replace($pattern, "", $newObject->$dbName);
                /* end preg_replace to remove old copy suffix first */
      
                $newObject->$dbName .= $fieldsToSuffix[$dbName];
              }
      
      

        Attachments

          Activity

          [CRM-20237] Event pricesets copied with long suffix cause DB error
          John Kirk added a comment -

          Joel Stevens in my mind the whole concept of "copy_id" is wrong. If we need to maintain where the event was copied from then this should be in a separate field - copy_id.

          To keep the names unique is simple, this is done elsewhere by adding _integer, e.g., _1, _2, _3 etc.

          Eileen McNaughton added a comment -

          John Kirk should you have time & enthusiasm it would be great if you could tackle this

           

          It is a rare error but having a fatal error is bad

          Joel Stevens added a comment -

          I agree, removing this suffix feature and adding a copy_id field if you really need to keep track of what was copied from what is a good idea. Does it really need the copy_id though? Once a priceset is copied over to a new event, it just becomes associated with the new event. Perhaps it's simpler to drop it altogether? It can be made unique by adding the event ID number or something.

           

          A lot of this client's events have identical pricing (sometimes it changes), but don't need the complexity of a pricesets. And they love copying older events to make new ones.

          Seamus Lee added a comment -

          Ok so having thinking about this, i know that for example if i make a clone of a contribution page for example having it have Copy Of helps me then find the new Contribution page it has just created. In regards to Price sets, i could see worth in the label etc but not really with the ID, i'll try and come up with something today on it. 

          Seamus Lee added a comment -

          I have put in a PR here that should resolve the issues hopefully https://github.com/civicrm/civicrm-core/pull/10929

            People

            • Assignee:
              Jitendra Purohit
              Reporter:
              Joel Stevens

              Dates

              • Created:
                Updated:
                Resolved: