def person_already_exists(transaction_executor, gov_id):
    """
    Verify whether a driver already exists in the database.

    :type transaction_executor: :py:class:`pyqldb.execution.executor.Executor`
    :param transaction_executor: An Executor object allowing for execution of statements within a transaction.

    :type gov_id: str
    :param gov_id: The government ID to search `Person` table against.

    :rtype: bool
    :return: If the Person has been registered.
    """
    query = 'SELECT * FROM Person AS p WHERE p.GovId = ?'
    cursor = transaction_executor.execute_statement(
        query, convert_object_to_ion(gov_id))
    try:
        next(cursor)
        return True
    except StopIteration:
        return False
def register_new_drivers_license(driver, person, new_license):
    """
    Register a new person and a new driver's license.

    :type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver`
    :param driver: An instance of the QldbDriver class.

    :type person: dict
    :param person: The person to register.

    :type new_license: dict
    :param new_license: The driver's license to register.
    """
    person_id = register_new_person(driver, person)
    if driver.execute_lambda(
            lambda executor: person_has_drivers_license(executor, person_id)):
        gov_id = person['GovId']
        logger.info(
            "Person with government ID '{}' already has a license! No new license added."
            .format(gov_id))
    else:
        logger.info("Registering new driver's license...")
        # Update the new license with new driver's unique PersonId.
        new_license.update({'PersonId': str(person_id)})
        statement = 'INSERT INTO DriversLicense ?'
        driver.execute_lambda(lambda executor: executor.execute_statement(
            statement, convert_object_to_ion(new_license)))

        cursor = driver.execute_lambda(
            lambda executor: lookup_drivers_license_for_person(
                executor, person_id))
        try:
            next(cursor)
            logger.info('Successfully registered new driver.')
            return
        except StopIteration:
            logger.info(
                'Problem occurred while inserting new license, please review the results.'
            )
            return
def insert_documents(transaction_executor, table_name, documents):
    """
    Insert the given list of documents into a table in a single transaction.

    :type transaction_executor: :py:class:`pyqldb.session.executor.Executor`
    :param transaction_executor: An Executor object allowing for execution of statements within a transaction.

    :type table_name: str
    :param table_name: Name of the table to insert documents into.

    :type documents: list
    :param documents: List of documents to insert.

    :rtype: list
    :return: List of documents IDs for the newly inserted documents.
    """
    logger.info('Inserting some documents in the {} table...'.format(table_name))
    statement = 'INSERT INTO {} ?'.format(table_name)
    cursor = transaction_executor.execute_statement(statement, [convert_object_to_ion(documents)])
    list_of_document_ids = get_document_ids_from_dml_results(cursor)

    return list_of_document_ids
예제 #4
0
def register_new_drivers_license(transaction_executor, driver, new_license):
    """
    Register a new driver and a new driver's license in a single transaction.

    :type transaction_executor: :py:class:`pyqldb.session.executor.Executor`
    :param transaction_executor: An Executor object allowing for execution of statements within a transaction.

    :type driver: dict
    :param driver: The driver's license to register.

    :type new_license: dict
    :param new_license: The driver's license to register.
    """
    person_id = register_new_driver(transaction_executor, driver)
    if person_has_drivers_license(transaction_executor, person_id):
        gov_id = driver['GovId']
        logger.info(
            "Person with government ID '{}' already has a license! No new license added."
            .format(gov_id))
    else:
        logger.info("Registering new driver's license...")
        # Update the new license with new driver's unique PersonId.
        new_license.update({'PersonId': str(person_id)})
        statement = 'INSERT INTO DriversLicense ?'
        transaction_executor.execute_statement(
            statement, [convert_object_to_ion(new_license)])

        cursor = lookup_drivers_license_for_person(transaction_executor,
                                                   person_id)
        try:
            next(cursor)
            logger.info('Successfully registered new driver.')
            return
        except StopIteration:
            logger.info(
                'Problem occurred while inserting new license, please review the results.'
            )
            return
def find_primary_owner_for_vehicle(transaction_executor, vin):
    """
    Find the primary owner of a vehicle given its VIN.

    :type transaction_executor: :py:class:`pyqldb.execution.executor.Executor`
    :param transaction_executor: An Executor object allowing for execution of statements within a transaction.

    :type vin: str
    :param vin: The VIN to find primary owner for.

    :rtype: :py:class:`amazon.ion.simple_types.IonPyDict`
    :return: The resulting document from the query.
    """
    logger.info('Finding primary owner for vehicle with VIN: {}.'.format(vin))
    query = "SELECT Owners.PrimaryOwner.PersonId FROM VehicleRegistration AS v WHERE v.VIN = ?"
    cursor = transaction_executor.execute_statement(query,
                                                    convert_object_to_ion(vin))
    try:
        return find_person_from_document_id(transaction_executor,
                                            next(cursor).get('PersonId'))
    except StopIteration:
        logger.error('No primary owner registered for this vehicle.')
        return None
def insert_documents(driver, table_name, documents):
    """
    Insert the given list of documents into a table in a single transaction.

    :type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver`
    :param driver: An instance of the QldbDriver class.

    :type table_name: str
    :param table_name: Name of the table to insert documents into.

    :type documents: list
    :param documents: List of documents to insert.

    :rtype: list
    :return: List of documents IDs for the newly inserted documents.
    """
    logger.info(
        'Inserting some documents in the {} table...'.format(table_name))
    statement = 'INSERT INTO {} ?'.format(table_name)
    cursor = driver.execute_lambda(lambda executor: executor.execute_statement(
        statement, convert_object_to_ion(documents)))
    list_of_document_ids = get_document_ids_from_dml_results(cursor)

    return list_of_document_ids
def update_vehicle_registration(driver, vin, document_id):
    """
    Update the primary owner for a vehicle using the given VIN.

    :type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver`
    :param driver: An instance of the QldbDriver class.

    :type vin: str
    :param vin: The VIN for the vehicle to operate on.

    :type document_id: :py:class:`amazon.ion.simple_types.IonPyText`
    :param document_id: New PersonId for the primary owner.

    :raises RuntimeError: If no vehicle registration was found using the given document ID and VIN.
    """
    logger.info('Updating the primary owner for vehicle with Vin: {}...'.format(vin))
    statement = "UPDATE VehicleRegistration AS r SET r.Owners.PrimaryOwner.PersonId = ? WHERE r.VIN = ?"
    cursor = driver.execute_lambda(lambda executor: executor.execute_statement(statement, document_id,
                                                                               convert_object_to_ion(vin)))
    try:
        print_result(cursor)
        logger.info('Successfully transferred vehicle with VIN: {} to new owner.'.format(vin))
    except StopIteration:
        raise RuntimeError('Unable to transfer vehicle, could not find registration.')
예제 #8
0
def insert_and_verify_ion_types(driver):
    """
    Insert all the supported Ion types and Python values that are convertible to Ion into a ledger and verify that they
    are stored and can be retrieved properly, retaining their original properties.

    :type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver`
    :param driver: A QLDB Driver object.
    """
    python_bytes = str.encode('hello')
    python_bool = True
    python_float = float('0.2')
    python_decimal = Decimal('0.1')
    python_string = "string"
    python_int = 1
    python_null = None
    python_datetime = datetime(2016, 12, 20, 5, 23, 43)
    python_list = [1, 2]
    python_dict = {"brand": "Ford"}

    ion_clob = convert_object_to_ion(loads('{{"This is a CLOB of text."}}'))
    ion_blob = convert_object_to_ion(python_bytes)
    ion_bool = convert_object_to_ion(python_bool)
    ion_decimal = convert_object_to_ion(python_decimal)
    ion_float = convert_object_to_ion(python_float)
    ion_int = convert_object_to_ion(python_int)
    ion_list = convert_object_to_ion(python_list)
    ion_null = convert_object_to_ion(python_null)
    ion_sexp = convert_object_to_ion(loads('(cons 1 2)'))
    ion_string = convert_object_to_ion(python_string)
    ion_struct = convert_object_to_ion(python_dict)
    ion_symbol = convert_object_to_ion(SymbolToken(text='abc', sid=123))
    ion_timestamp = convert_object_to_ion(python_datetime)

    ion_null_clob = convert_object_to_ion(loads('null.clob'))
    ion_null_blob = convert_object_to_ion(loads('null.blob'))
    ion_null_bool = convert_object_to_ion(loads('null.bool'))
    ion_null_decimal = convert_object_to_ion(loads('null.decimal'))
    ion_null_float = convert_object_to_ion(loads('null.float'))
    ion_null_int = convert_object_to_ion(loads('null.int'))
    ion_null_list = convert_object_to_ion(loads('null.list'))
    ion_null_sexp = convert_object_to_ion(loads('null.sexp'))
    ion_null_string = convert_object_to_ion(loads('null.string'))
    ion_null_struct = convert_object_to_ion(loads('null.struct'))
    ion_null_symbol = convert_object_to_ion(loads('null.symbol'))
    ion_null_timestamp = convert_object_to_ion(loads('null.timestamp'))

    create_table(driver, TABLE_NAME)
    insert_documents(driver, TABLE_NAME, [{'Name': 'val'}])
    update_record_and_verify_type(driver, python_bytes, IonPyBytes, IonType.BLOB)
    update_record_and_verify_type(driver, python_bool, IonPyBool, IonType.BOOL)
    update_record_and_verify_type(driver, python_float, IonPyFloat, IonType.FLOAT)
    update_record_and_verify_type(driver, python_decimal, IonPyDecimal, IonType.DECIMAL)
    update_record_and_verify_type(driver, python_string, IonPyText, IonType.STRING)
    update_record_and_verify_type(driver, python_int, IonPyInt, IonType.INT)
    update_record_and_verify_type(driver, python_null, IonPyNull, IonType.NULL)
    update_record_and_verify_type(driver, python_datetime, IonPyTimestamp, IonType.TIMESTAMP)
    update_record_and_verify_type(driver, python_list, IonPyList, IonType.LIST)
    update_record_and_verify_type(driver, python_dict, IonPyDict, IonType.STRUCT)
    update_record_and_verify_type(driver, ion_clob, IonPyBytes, IonType.CLOB)
    update_record_and_verify_type(driver, ion_blob, IonPyBytes, IonType.BLOB)
    update_record_and_verify_type(driver, ion_bool, IonPyBool, IonType.BOOL)
    update_record_and_verify_type(driver, ion_decimal, IonPyDecimal, IonType.DECIMAL)
    update_record_and_verify_type(driver, ion_float, IonPyFloat, IonType.FLOAT)
    update_record_and_verify_type(driver, ion_int, IonPyInt, IonType.INT)
    update_record_and_verify_type(driver, ion_list, IonPyList, IonType.LIST)
    update_record_and_verify_type(driver, ion_null, IonPyNull, IonType.NULL)
    update_record_and_verify_type(driver, ion_sexp, IonPyList, IonType.SEXP)
    update_record_and_verify_type(driver, ion_string, IonPyText, IonType.STRING)
    update_record_and_verify_type(driver, ion_struct, IonPyDict, IonType.STRUCT)
    update_record_and_verify_type(driver, ion_symbol, IonPySymbol, IonType.SYMBOL)
    update_record_and_verify_type(driver, ion_timestamp, IonPyTimestamp, IonType.TIMESTAMP)
    update_record_and_verify_type(driver, ion_null_clob, IonPyNull, IonType.CLOB)
    update_record_and_verify_type(driver, ion_null_blob, IonPyNull, IonType.BLOB)
    update_record_and_verify_type(driver, ion_null_bool, IonPyNull, IonType.BOOL)
    update_record_and_verify_type(driver, ion_null_decimal, IonPyNull, IonType.DECIMAL)
    update_record_and_verify_type(driver, ion_null_float, IonPyNull, IonType.FLOAT)
    update_record_and_verify_type(driver, ion_null_int, IonPyNull, IonType.INT)
    update_record_and_verify_type(driver, ion_null_list, IonPyNull, IonType.LIST)
    update_record_and_verify_type(driver, ion_null_sexp, IonPyNull, IonType.SEXP)
    update_record_and_verify_type(driver, ion_null_string, IonPyNull, IonType.STRING)
    update_record_and_verify_type(driver, ion_null_struct, IonPyNull, IonType.STRUCT)
    update_record_and_verify_type(driver, ion_null_symbol, IonPyNull, IonType.SYMBOL)
    update_record_and_verify_type(driver, ion_null_timestamp, IonPyNull, IonType.TIMESTAMP)
    delete_table(driver, TABLE_NAME)
def find_primary_owner_for_vehicle(driver, vin):
    """
    Find the primary owner of a vehicle given its VIN.

    :type driver: :py:class:`pyqldb.driver.qldb_driver.QldbDriver`
    :param driver: An instance of the QldbDriver class.

    :type vin: str
    :param vin: The VIN to find primary owner for.

    :rtype: :py:class:`amazon.ion.simple_types.IonPyDict`
    :return: The resulting document from the query.
    """
    logger.info('Finding primary owner for vehicle with VIN: {}.'.format(vin))
    query = "SELECT Owners.PrimaryOwner.PersonId FROM VehicleRegistration AS v WHERE v.VIN = ?"
    cursor = driver.execute_lambda(lambda executor: executor.execute_statement(query, convert_object_to_ion(vin)))
    try:
        return driver.execute_lambda(lambda executor: find_person_from_document_id(executor,
                                                                                   next(cursor).get('PersonId')))
    except StopIteration:
        logger.error('No primary owner registered for this vehicle.')
        return None
    cursor = transaction_executor.execute_statement(
        'DROP TABLE {}'.format(table_name))
    logger.info("'{}' table successfully deleted.".format(table_name))
    return len(list(cursor))


TABLE_NAME = 'IonTypes'

if __name__ == '__main__':
    """
    Insert all the supported Ion types into a ledger and verify that they are stored and can be retrieved properly, 
    retaining their original properties.
    """
    try:
        with create_qldb_session() as session:
            ion_clob = convert_object_to_ion(
                loads('{{"This is a CLOB of text."}}'))
            ion_blob = convert_object_to_ion(str.encode('hello'))
            ion_bool = convert_object_to_ion(True)
            ion_decimal = convert_object_to_ion(Decimal('0.1'))
            ion_float = convert_object_to_ion(float('0.2'))
            ion_int = convert_object_to_ion(1)
            ion_list = convert_object_to_ion([1, 2])
            ion_null = convert_object_to_ion(None)
            ion_sexp = convert_object_to_ion(loads('(cons 1 2)'))
            ion_string = convert_object_to_ion("string")
            ion_struct = convert_object_to_ion({"brand": "Ford"})
            ion_symbol = convert_object_to_ion(SymbolToken(text='abc',
                                                           sid=123))
            ion_timestamp = convert_object_to_ion(
                datetime(2016, 12, 20, 5, 23, 43))
            break
        except ClientError as ce:
            if is_occ_conflict_exception(ce):
                logger.error('Commit failed due to an OCC conflict. Restart transaction.')
                transaction = qldb_session.start_transaction()
                execute_transaction(qldb_session, transaction, statement, parameters)


if __name__ == '__main__':
    """
    Demonstrates how to handle OCC conflicts, where two users try to execute and commit changes to the same document.
    When OCC conflict occurs on execute or commit, implicitly handled by restarting the transaction.
    In this example, two sessions on the same ledger try to access the registration city for the same Vehicle Id.
    """
    vehicle_vin = SampleData.VEHICLE_REGISTRATION[0]['VIN']
    parameters = [convert_object_to_ion(vehicle_vin)]
    query1 = "UPDATE VehicleRegistration AS v SET v.City = 'Tukwila' WHERE v.VIN = ?"
    query2 = 'SELECT City FROM VehicleRegistration AS v WHERE v.VIN = ?'

    with create_qldb_session() as session1, create_qldb_session() as session2:
        logger.info('Updating the VehicleRegistration city in transaction 1...')
        transaction1 = session1.start_transaction()
        logger.info('Selecting the VehicleRegistration city in transaction 2...')
        transaction2 = session2.start_transaction()

        logger.info('Executing transaction 1')
        execute_transaction(session1, transaction1, query1, parameters)
        logger.info('Executing transaction 2')
        execute_transaction(session2, transaction2, query2, parameters)

        logger.info('Committing transaction 1...')