Exemplo n.º 1
0
def _upload_one_all_columns(
    cursor,
    table_name,
    table_id,
    columns,
    input_dict,
    overwrite,
    print_string,
    verbose,
    **kwargs,
):
    """Insert or overwrite a list of things in a table."""
    to_insert = [table_id] + columns

    if overwrite:
        sql_com = build_update(
            table=table_name, to_set=columns, where=[table_id]
        )
    else:
        sql_com = build_insert(table=table_name, to_insert=to_insert)

    # Upload or modify data
    insert_dict = {key: input_dict.get(key) for key in to_insert}
    try:
        cursor.execute(sql_com, insert_dict)
    except sqlite3.Error as e:
        raise type(e)(
            f"Error inserting dict {insert_dict}. Original error:\n {e}"
        )

    if verbose:
        # Print success
        logger.info(f"{print_string} uploaded {insert_dict.get(table_id)}")
Exemplo n.º 2
0
def isotherm_to_db(
    isotherm,
    db_path=None,
    autoinsert_material=True,
    autoinsert_adsorbate=True,
    verbose=True,
    **kwargs
):
    """
    Uploads isotherm to the database.

    If overwrite is set to true, the isotherm is overwritten.
    Overwrite is done based on isotherm.iso_id

    Parameters
    ----------
    isotherm : Isotherm
        Isotherm, PointIsotherm or ModelIsotherm to upload to the database.
    db_path : str, None
        Path to the database. If none is specified, internal database is used.
    autoinsert_material: bool, True
        Whether to automatically insert an isotherm material if it is not found
        in the database.
    autoinsert_adsorbate: bool, True
        Whether to automatically insert an isotherm adsorbate if it is not found
        in the database.
    verbose : bool, True
        Extra information printed to console.
    """

    cursor = kwargs['cursor']
    # Checks
    if autoinsert_material:
        if isotherm.material not in MATERIAL_LIST:
            material_to_db(
                isotherm.material if isinstance(isotherm.material, Material)
                else Material(isotherm.material),
                db_path=db_path,
                cursor=cursor
            )
    if autoinsert_adsorbate:
        if isotherm.adsorbate not in ADSORBATE_LIST:
            adsorbate_to_db(
                isotherm.adsorbate
                if isinstance(isotherm.adsorbate, Adsorbate) else
                Adsorbate(isotherm.adsorbate),
                db_path=db_path,
                cursor=cursor
            )

    # The isotherm is going to be inserted into the database
    # Build upload dict
    iso_id = isotherm.iso_id
    upload_dict = {'id': iso_id}

    if isinstance(isotherm, PointIsotherm):
        upload_dict['iso_type'] = 'pointisotherm'
    elif isinstance(isotherm, ModelIsotherm):
        upload_dict['iso_type'] = 'modelisotherm'
    elif isinstance(isotherm, BaseIsotherm):
        upload_dict['iso_type'] = 'isotherm'
    else:
        raise ParsingError("Unknown isotherm type.")

    iso_dict = isotherm.to_dict()

    # attributes which are kept in the database
    upload_dict.update({
        param: iso_dict.pop(param, None)
        for param in BaseIsotherm._required_params
    })

    # Upload isotherm info to database
    db_columns = ["id", "iso_type"] + BaseIsotherm._required_params
    try:
        cursor.execute(
            build_insert(table='isotherms', to_insert=db_columns), upload_dict
        )
    except sqlite3.Error as e:
        raise type(e)(
            f"""Error inserting isotherm "{upload_dict["id"]}" base properties. """
            f"""Ensure material "{upload_dict["material"]}", and adsorbate "{upload_dict["adsorbate"]}" """
            f"""exist in the database already. Original error:\n {e}"""
        ) from None

    # TODO insert multiple
    # Upload the other isotherm parameters
    for key in iso_dict:
        if key not in isotherm._unit_params:
            # Deal with bools
            val = iso_dict[key]
            if isinstance(val, bool):
                val = 'TRUE' if val else 'FALSE'
            cursor.execute(
                build_insert(
                    table='isotherm_properties',
                    to_insert=['iso_id', 'type', 'value']
                ), {
                    'iso_id': iso_id,
                    'type': key,
                    'value': val
                }
            )

    # Then, the isotherm data/model will be uploaded into the data table

    # Build sql request
    sql_insert = build_insert(
        table='isotherm_data', to_insert=['iso_id', 'type', 'data']
    )

    if isinstance(isotherm, PointIsotherm):
        # Insert standard data fields:
        cursor.execute(
            sql_insert, {
                'iso_id': iso_id,
                'type': 'pressure',
                'data': isotherm.pressure().tobytes()
            }
        )
        cursor.execute(
            sql_insert, {
                'iso_id': iso_id,
                'type': 'loading',
                'data': isotherm.loading().tobytes()
            }
        )
        # Update or insert other fields:
        for key in isotherm.other_keys:
            cursor.execute(
                sql_insert, {
                    'iso_id': iso_id,
                    'type': key,
                    'data': isotherm.other_data(key).tobytes()
                }
            )
    elif isinstance(isotherm, ModelIsotherm):
        # Insert model parameters
        cursor.execute(
            sql_insert, {
                'iso_id': iso_id,
                'type': 'model',
                'data': json.dumps(isotherm.model.to_dict())
            }
        )

    if verbose:
        # Print success
        logger.info(f"Isotherm uploaded: '{isotherm.iso_id}'")
Exemplo n.º 3
0
def material_to_db(
    material,
    db_path=None,
    overwrite=False,
    verbose=True,
    **kwargs,
):
    """
    Upload a material to the database.

    If overwrite is set to true, the material is overwritten.
    Overwrite is done based on material.name

    Parameters
    ----------
    material : Material
        Material class to upload to the database.
    db_path : str, None
        Path to the database. If none is specified, internal database is used.
    overwrite : bool
        Whether to upload the material or overwrite it.
        WARNING: Overwrite is done on ALL fields.
    verbose : bool
        Extra information printed to console.

    """

    cursor = kwargs['cursor']

    # If we need to overwrite, we find the id of existing adsorbate.
    if overwrite:
        ids = cursor.execute(
            build_select(table='materials', to_select=['id'], where=['name']),
            {
                'name': material.name
            }
        ).fetchone()
        if ids is None:
            raise sqlite3.IntegrityError(
                f"Material to overwrite ({material.name}) does not exist in database."
            )
        mat_id = ids[0]
    # If overwrite is not specified, we upload it to the adsorbates table
    else:
        cursor.execute(
            build_insert(table="materials", to_insert=['name']),
            {'name': material.name}
        )
        mat_id = cursor.lastrowid

    # Upload or modify data in material_properties table
    properties = material.to_dict()
    del properties['name']  # no need for this

    if properties:
        if overwrite:
            # Delete existing properties
            _delete_by_id(
                cursor,
                'material_properties',
                'mat_id',
                mat_id,
                'material properties',
                verbose,
            )

        for prop, val in properties.items():

            sql_insert = build_insert(
                table='material_properties',
                to_insert=['mat_id', 'type', 'value'],
            )

            if not isinstance(val, (list, set, tuple)):
                val = [val]

            for vl in val:
                try:
                    cursor.execute(
                        sql_insert, {
                            'mat_id': mat_id,
                            'type': prop,
                            'value': vl
                        }
                    )
                except sqlite3.InterfaceError as e:
                    raise type(e)(
                        f"Cannot process property {prop}: {vl}"
                        f"Original error:\n{e}"
                    ) from None

    # Add to existing list
    if overwrite:
        if material in MATERIAL_LIST:
            MATERIAL_LIST.remove(material.name)

    MATERIAL_LIST.append(material)

    if verbose:
        # Print success
        logger.info(f"Material uploaded: '{material.name}'")
Exemplo n.º 4
0
def test_insert():
    insert = r'INSERT INTO "table" (a, b) VALUES (:a, :b)'
    assert insert == squ.build_insert(tb, s1)