def insert(object_: Dict[str, Any], session: scoped_session, id_: Optional[int] = None) -> int: """Insert an object to database [POST] and returns the inserted object.""" rdf_class = None instance = None # Check for class in the begging try: rdf_class = session.query(RDFClass).filter( RDFClass.name == object_["@type"]).one() except NoResultFound: raise ClassNotFound(type_=object_["@type"]) if id_ is not None: if session.query(exists().where(Instance.id == id_)).scalar(): raise InstanceExists(type_=rdf_class.name, id_=id_) else: instance = Instance(id=id_, type_=rdf_class.id) else: instance = Instance(type_=rdf_class.id) session.add(instance) session.flush() for prop_name in object_: if prop_name not in ["@type", "@context"]: try: property_ = session.query(properties).filter( properties.name == prop_name).one() except NoResultFound: # Adds new Property session.close() raise PropertyNotFound(type_=prop_name) # For insertion in III if type(object_[prop_name]) == dict: instance_id = insert(object_[prop_name], session=session) instance_object = session.query(Instance).filter( Instance.id == instance_id).one() if property_.type_ == "PROPERTY" or property_.type_ == "INSTANCE": property_.type_ = "INSTANCE" session.add(property_) triple = GraphIII(subject=instance.id, predicate=property_.id, object_=instance_object.id) session.add(triple) else: session.close() raise NotInstanceProperty(type_=prop_name) # For insertion in IAC elif session.query(exists().where( RDFClass.name == str(object_[prop_name]))).scalar(): if property_.type_ == "PROPERTY" or property_.type_ == "ABSTRACT": property_.type_ = "ABSTRACT" session.add(property_) class_ = session.query(RDFClass).filter( RDFClass.name == object_[prop_name]).one() triple = GraphIAC(subject=instance.id, predicate=property_.id, object_=class_.id) session.add(triple) else: session.close() raise NotAbstractProperty(type_=prop_name) # For insertion in IIT else: terminal = Terminal(value=object_[prop_name]) session.add(terminal) session.flush() # Assigns ID without committing if property_.type_ == "PROPERTY" or property_.type_ == "INSTANCE": property_.type_ = "INSTANCE" session.add(property_) triple = GraphIIT(subject=instance.id, predicate=property_.id, object_=terminal.id) # Add things directly to session, if anything fails whole transaction is aborted session.add(triple) else: session.close() raise NotInstanceProperty(type_=prop_name) session.commit() return instance.id
def insert_object(object_: Dict[str, Any], session: scoped_session, collection: bool = False) -> str: """ Insert the object in the database :param object_: Dict containing object properties :param session: sqlalchemy session :return: The ID of the inserted object """ type_ = get_type(object_) database_class = get_database_class(type_) id_ = object_.get("id", None) if collection: # if type_ is of a collection class members = object_['members'] collection_id = id_ if id_ else str(uuid.uuid4()) for member in members: # add all the members of that collection inserted_object = database_class( members=member['id_'], collection_id=collection_id, member_type=member['@type'], ) try: session.add(inserted_object) session.commit() except InvalidRequestError: session.rollback() return collection_id else: # when type_ is of a non-collection class if (id_ is not None and session.query( exists().where(database_class.id == id_)).scalar()): raise InstanceExists(type_, id_) foreign_keys = database_class.__table__.foreign_keys for fk in foreign_keys: # the name of the column through which this foreign key relationship # is being established fk_column = fk.info["column_name"] try: fk_object = object_[fk_column] except KeyError as e: wrong_property = e.args[0] raise PropertyNotGiven(type_=wrong_property) # insert the foreign key object fk_object_id = insert_object(fk_object, session) # put the id of the foreign instance in this table's column object_[fk_column] = fk_object_id try: # remove the @type from object before using the object to make a # instance of it using sqlalchemy class object_.pop("@type") inserted_object = database_class(**object_) except TypeError as e: # extract the wrong property name from TypeError object wrong_property = e.args[0].split("'")[1] raise PropertyNotFound(type_=wrong_property) try: session.add(inserted_object) session.commit() except InvalidRequestError: session.rollback() return inserted_object.id
def insert_multiple(objects_: List[Dict[str, Any]], session: scoped_session, id_: Optional[str] = "") -> List[int]: """ Adds a list of object with given ids to the database :param objects_: List of dict's to be added to the database :param session: scoped session from getSession in utils :param id_: optional parameter containing the ids of objects that have to be inserted :return: Ids that have been inserted """ # instance list to store instances instance_list = list() triples_list = list() properties_list = list() instances = list() id_list = id_.split(',') instance_id_list = list() # the number of objects would be the same as number of instances for index in range(len(objects_)): try: rdf_class = session.query(RDFClass).filter( RDFClass.name == objects_[index]["@type"]).one() except NoResultFound: raise ClassNotFound(type_=objects_[index]["@type"]) if index in range(len(id_list)) and id_list[index] != "": if session.query( exists().where( Instance.id == id_list[index])).scalar(): print(session.query( exists().where( Instance.id == id_list[index]))) # TODO handle where intance already exists , if instance is # fetched later anyways remove this raise InstanceExists(type_=rdf_class.name, id_=id_list[index]) else: instance = Instance(id=id_list[index], type_=rdf_class.id) instances.append(instance) else: instance = Instance(type_=rdf_class.id) instances.append(instance) session.add_all(instances) session.flush() for i in range(len(instances)): instance_id_list.append(instances[i].id) for index in range(len(objects_)): for prop_name in objects_[index]: if prop_name not in ["@type", "@context"]: try: property_ = session.query(properties).filter( properties.name == prop_name).one() except NoResultFound: # Adds new Property session.close() raise PropertyNotFound(type_=prop_name) # For insertion in III if isinstance(objects_[index][prop_name], dict): instance_id = insert( objects_[index][prop_name], session=session) instance_object = session.query(Instance).filter( Instance.id == instance_id).one() if property_.type_ == "PROPERTY" or property_.type_ == "INSTANCE": property_.type_ = "INSTANCE" properties_list.append(property_) triple = GraphIII( subject=instances[index].id, predicate=property_.id, object_=instance_object.id) triples_list.append(triple) else: session.close() raise NotInstanceProperty(type_=prop_name) # For insertion in IAC elif session.query( exists().where(RDFClass.name == str(objects_[index][prop_name]))).scalar(): if property_.type_ == "PROPERTY" or property_.type_ == "ABSTRACT": property_.type_ = "ABSTRACT" properties_list.append(property_) class_ = session.query(RDFClass).filter( RDFClass.name == objects_[index][prop_name]).one() triple = GraphIAC( subject=instances[index].id, predicate=property_.id, object_=class_.id) triples_list.append(triple) else: session.close() raise NotAbstractProperty(type_=prop_name) # For insertion in IIT else: terminal = Terminal(value=objects_[index][prop_name]) session.add(terminal) session.flush() # Assigns ID without committing if property_.type_ == "PROPERTY" or property_.type_ == "INSTANCE": property_.type_ = "INSTANCE" properties_list.append(property_) triple = GraphIIT( subject=instances[index].id, predicate=property_.id, object_=terminal.id) # Add things directly to session, if anything fails # whole transaction is aborted triples_list.append(triple) else: session.close() raise NotInstanceProperty(type_=prop_name) session.bulk_save_objects(properties_list) session.bulk_save_objects(triples_list) session.commit() return instance_id_list
def insert(object_: Dict[str, Any], session: scoped_session, id_: Optional[str] = None) -> str: """Insert an object to database [POST] and returns the inserted object. :param object_: object to be inserted :param session: sqlalchemy scoped session :param id_: id of the object to be inserted (optional param) :return: ID of object inserted Raises: ClassNotFound: If `object_["@type"] is not a valid/defined RDFClass. InstanceExists: If an Instance `id_` already exists. PropertyNotFound: If any property name of `object_` other than `@type` or `@context` is not a valid/defined property. NotInstanceProperty: If any property of `object_` is a dictionary but not an Instance property NotAbstractProperty: If any property of `object_` is a valid/defined RDFClass but is not a dictionary neither an Abstract Property """ rdf_class = None instance = None # Check for class in the begging try: rdf_class = session.query(RDFClass).filter( RDFClass.name == object_["@type"]).one() except NoResultFound: raise ClassNotFound(type_=object_["@type"]) if id_ is not None and session.query(exists().where(Instance.id == id_)).scalar(): raise InstanceExists(type_=rdf_class.name, id_=id_) elif id_ is not None: instance = Instance(id=id_, type_=rdf_class.id) else: instance = Instance(type_=rdf_class.id) session.add(instance) session.flush() for prop_name in object_: if prop_name not in ["@type", "@context"]: try: property_ = session.query(properties).filter( properties.name == prop_name).one() except NoResultFound: # Adds new Property session.close() raise PropertyNotFound(type_=prop_name) # For insertion in III if isinstance(object_[prop_name], dict): instance_id = insert(object_[prop_name], session=session) instance_object = session.query(Instance).filter( Instance.id == instance_id).one() if property_.type_ == "PROPERTY" or property_.type_ == "INSTANCE": property_.type_ = "INSTANCE" session.add(property_) triple = GraphIII( subject=instance.id, predicate=property_.id, object_=instance_object.id) session.add(triple) else: session.close() raise NotInstanceProperty(type_=prop_name) # For insertion in IAC elif session.query(exists().where(RDFClass.name == str(object_[prop_name]))).scalar() \ and property_.type_ == "PROPERTY" or property_.type_ == "ABSTRACT": property_.type_ = "ABSTRACT" session.add(property_) class_ = session.query(RDFClass).filter( RDFClass.name == object_[prop_name]).one() triple = GraphIAC( subject=instance.id, predicate=property_.id, object_=class_.id) session.add(triple) elif session.query(exists().where(RDFClass.name == str(object_[prop_name]))).scalar(): session.close() raise NotAbstractProperty(type_=prop_name) # For insertion in IIT else: terminal = Terminal(value=object_[prop_name]) session.add(terminal) session.flush() # Assigns ID without committing if property_.type_ == "PROPERTY" or property_.type_ == "INSTANCE": property_.type_ = "INSTANCE" session.add(property_) triple = GraphIIT( subject=instance.id, predicate=property_.id, object_=terminal.id) # Add things directly to session, if anything fails whole # transaction is aborted session.add(triple) else: session.close() raise NotInstanceProperty(type_=prop_name) session.commit() return instance.id