Skip to content

updateOrCreate($model->toArray()); with double primary key returns SQLSTATE[23502]: Not null violation #31105

@Jeroenvanderholst

Description

@Jeroenvanderholst
  • Laravel Version: 6.9.0
  • PHP Version: 7.3.9
  • Database Driver & Version: PostgreSQL 12

Description:

I am fleshing out a multi level XML part that I am loading into a new model instance. This model consists of a double primary key: id and language.
The ->save() method works fine, but I need to update the data table which means that I could use the ->updateOrCreate() method, but I need to transform the object to an array first, as this is what the updateOrCreate() method eats. It does not take any model objects. I find that to be somewhat inconsistent.

When I reload the exact same data using this approach, it all works fine.

However, when I test my code by throwing away the first few records, the SQL server blows up, It gives a SQLSTATE[23502]: Not null violation error. The first record is not found, and it tries to create it, but for some vague reason the first primary key is returning "NULL"

Steps To Reproduce:

Here's my store method:

public function store(Request $request, EtimUpdate $etim_update, EtimUnit $etim_unit)
{
    // DB::table('etim_units')->delete();
    $units =$etim_update->harvest("Units");

    // ddd($unit->Translations->Translation[0]->attributes()["language"]->__toString());
    foreach($units->children() as $unit) {
        foreach ($unit->Translations->children() as $translation) {

           $etim_unit = new EtimUnit;
            $etim_unit->id = $unit->Code->__toString();
            $etim_unit->language = $translation->attributes()["language"];
            $etim_unit->description = $translation->Description->__toString();
            $etim_unit->abbreviation = $translation->Abbreviation->__toString();

            $etim_unit->updateOrCreate($etim_unit->toArray());
            // $etim_unit->save();
        }
    }
}

And the harvest() metthod asused above is coming from an inherited base class EtimUpdate.php, see code below:

public function harvest($element)
{
    $reader = new XMLReader();

   $reader->open($this->path . $this->filename) ;
   $result = [];

      while ($reader->read()) {

        if ($reader->name == $element && $reader->nodeType == XMLReader::ELEMENT) {
            // $result = new SimpleXMLElement($reader->readOuterXml());
            $result = simplexml_load_string($reader->readOuterXml());
            
            
         return $result;   
         
        }
    }
    $reader->close();
}

And here's a sample of a unit element which is loaded from a very large XML:

  <Units>
    <Unit>
      <Code>EU000002</Code>
      <Translations>
        <Translation language="de-DE">
          <Description>Hekto-Pascal</Description>
          <Abbreviation>hPa</Abbreviation>
        </Translation>
        <Translation language="EN">
          <Description>Hecto Pascal</Description>
          <Abbreviation>hPa</Abbreviation>
        </Translation>
        <Translation language="fi-FI">
          <Description>hehtopascal</Description>
          <Abbreviation>hPa</Abbreviation>
        </Translation>
        <Translation language="fr-BE">
          <Description>hectopascal</Description>
          <Abbreviation>hPa</Abbreviation>
        </Translation>
        <Translation language="it-IT">
          <Description>hPa</Description>
          <Abbreviation>hPa</Abbreviation>
        </Translation>
        <Translation language="nb-NO">
          <Description>Hekto-Pascal</Description>
          <Abbreviation>hPa</Abbreviation>
        </Translation>
        <Translation language="nl-BE">
          <Description>Hecto Pascal</Description>
          <Abbreviation>hPa</Abbreviation>
        </Translation>
        <Translation language="nl-NL">
          <Description>Hectopascal</Description>
          <Abbreviation>hPa</Abbreviation>
        </Translation>
      </Translations>
    </Unit>
  </Units>

The temporary workaround is to empty the data table and reload everything, but that is not the truly right way to maintain this data table. I need the updateOrCreate() method to work with a bunch of other tables that need to keep historic data too.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions