.. -*- coding: utf-8 -*-
.. :Project:   metapensiero.sqlalchemy.dbloady -- YAML based data loader
.. :Created:   ven  1 gen 2016, 16.19.54, CET
.. :Author:    Lele Gaifax <lele@metapensiero.it>
.. :License:   GNU General Public License version 3 or later
.. :Copyright: Copyright (C) 2016 Lele Gaifax
..

=================================
 metapensiero.sqlalchemy.dbloady
=================================

YAML based data loader
======================

 :author: Lele Gaifax
 :contact: lele@metapensiero.it
 :license: GNU General Public License version 3 or later

Load new instances in the database, or update/delete existing ones, given a data structure
represented by a YAML stream, as the following::

    - entity: gam.model.Fascicolo
      key: descrizione
      # no data, just "declare" the entity

    - entity: gam.model.TipologiaFornitore
      key: tipologiafornitore
      data:
        - &tf_onesto
          tipologiafornitore: Test fornitori onesti

    - entity: gam.model.ClienteFornitore
      key: descrizione
      data:
        - descrizione: Test altro fornitore onesto
          tipologiafornitore: *tf_onesto
          partitaiva: 01234567890
        - &cf_lele
          codicefiscale: GFSMNL68C18H612V
          descrizione: Dipendente A

    - entity: gam.model.Dipendente
      key: codicefiscale
      data:
        - &lele
          codicefiscale: GFSMNL68C18H612V
          nome: Emanuele
          cognome: Gaifas
          clientefornitore: *cf_lele
          foto: !File {path: ../img/lele.jpg}

    - entity: gam.model.Attrezzature
      key: descrizione
      data:
        - &macchina
          descrizione: Fiat 500

    - entity: gam.model.Prestiti
      key:
        - dipendente
        - attrezzatura
      data:
        - dipendente: *lele
        - attrezzatura: *macchina

The ``key`` entry may be either a single attribute name or a list of them, not necessarily
corresponding to the primary key of the entity.  To handle the simplest case of structured
values (for example, when a field is backed by a PostgreSQL HSTORE), the key attribute name may
be in the form ``name->slot``::

    - entity: model.Product
      key: description->en
      data:
        - &cage
          description:
            en: "Roadrunner cage"
            it: "Gabbia per struzzi"

When all (or most of) the instances share the same fields, a more compact representation may be
used::

    - entity: model.Values
      key:
        - product
        - attribute
      fields: [ product, attribute, value ]
      data:
        - [ *cage, *size, 110cm x 110cm x 120cm ]
        - [ *cage, *weight, 230kg ]

where ``fields`` contains a list of field names and ``data`` is a sequence of lists, each
containing the values of a single instance.  The two sintaxes may be mixed though, so you can
say::

    - entity: model.Person
      key: [ lastname, firstname ]
      fields: [ lastname, firstname, password ]
      data:
        - [ gaifax, lele, "123456" ]
        - [ foobar, john, "abcdef" ]
        - lastname: rossi
          firstname: paolo
          birthdate: 1950-02-03

With the option ``--save-new-instances`` newly created instances will be written (actually
added) to the given file in YAML format, so that at some point they can be deleted using the
option ``--delete`` on that file.  Ideally

::

  dbloady -u postgresql://localhost/test -s new.yaml fixture.yaml
  dbloady -u postgresql://localhost/test -D new.yaml

should remove fixture's traces from the database, if it contains only new data.
