def get_connection(self, cluster_user: str, cluster_address: str,
                       cluster_port: int, database: str, pwd: str, ssl: bool):
        self._logger.debug("Creating new Database Connection")
        self._logger.debug(locals())

        if self._dialect == DIALECT_PG:
            # connect to the database
            conn = pg8000.connect(user=cluster_user,
                                  host=cluster_address,
                                  port=int(cluster_port),
                                  database=database,
                                  password=pwd,
                                  ssl_context=ssl.create_default_context()
                                  if ssl is True else None,
                                  timeout=None,
                                  tcp_keepalive=True,
                                  application_name=params.AWS_DATA_API_NAME)

            # Enable keepalives manually until pg8000 supports it
            # For future reference: https://github.com/mfenniak/pg8000/issues/149
            # TCP keepalives still need to be configured appropriately on OS level as well
            conn._usock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
            conn.autocommit = True

            return conn
        else:
            raise exceptions.UnimplementedFeatureException()
示例#2
0
def json_to_pg(p_name: str, p_spec: dict, p_required: dict,
               pk_name: str) -> str:
    '''Convert a JSON type to a Postgres type with nullability spec
    '''
    base = None
    if p_spec is not None:
        p_type = p_spec.get("type")

        if p_type.lower() == 'string':
            base = 'varchar'
        elif p_type.lower() == 'number':
            base = 'double precision'
        elif p_type.lower() == 'integer':
            base = 'integer'
        elif p_type.lower() == 'boolean':
            base = 'char(1) DEFAULT 0'
            return base
        else:
            raise exceptions.UnimplementedFeatureException(
                f"Type {p_type} not translatable to RDBMS types")

        # process null/not null
        if p_name.lower() == pk_name:
            base += ' NOT NULL PRIMARY KEY'
        elif p_name in p_required:
            base += ' NOT NULL'
        else:
            base += ' NULL'

        return base
    else:
        raise exceptions.DetailedException("Unable to render None Type Spec")
 def who_column_insert(self, caller_identity: str):
     if self._dialect == DIALECT_PG:
         return [
             f"0", f"'{params.ACTION_CREATE}'", f"CURRENT_TIMESTAMP",
             f"'{caller_identity}'"
         ]
     else:
         raise exceptions.UnimplementedFeatureException()
 def verify_table(self, conn, table_ref: str, table_schema: dict,
                  pk_name: str) -> None:
     if self._dialect == DIALECT_PG:
         try:
             cursor = conn.cursor()
             query = f'select count(9) from "{table_ref}"'
             self._logger.debug(query)
             cursor.execute(query)
             res = cursor.fetchone()
             self._logger.info(f"Bound to existing table {table_ref}")
         except ProgrammingError as pe:
             if "not exist" in str(pe):
                 # table doesn't exist so create it based on the current schema
                 self.create_table_from_schema(conn, table_ref,
                                               table_schema, pk_name)
             else:
                 self._logger.error(pe)
                 raise exceptions.DetailedException(pe)
     else:
         raise exceptions.UnimplementedFeatureException()
 def get_streams(self):
     raise exceptions.UnimplementedFeatureException()
    def delete(self, id: str, caller_identity: str, **kwargs):
        response = {}

        if params.METADATA in kwargs:
            if len(kwargs.get(params.METADATA)) == 0:
                # hard delete the metadata record - there is no soft delete
                response[params.METADATA] = {
                    params.DATA_MODIFIED: self._delete_metadata(id)
                }
            else:
                # just delete the specified attributes
                response[params.METADATA] = {
                    params.DATA_MODIFIED:
                    self.remove_metadata_attributes(
                        id=id,
                        metadata_attributes=kwargs.get(params.METADATA),
                        caller_identity=caller_identity)
                }

        if kwargs is None or kwargs == {} or params.RESOURCE in kwargs:
            if params.RESOURCE not in kwargs or len(kwargs.get(
                    params.RESOURCE)) == 0:
                if self._delete_mode == params.DELETE_MODE_SOFT:
                    # perform a soft delete and reflect that only the resource will have been deleted in the response§
                    update = self._create_update_statement(
                        table_ref=self._resource_table_name,
                        pk_name=self._pk_name,
                        input={
                            self._engine_type.get_who(params.DELETED): True
                        },
                        item_id=id,
                        caller_identity=caller_identity)
                    counts, records = self._engine_type.run_commands(
                        self._db_conn, [update])

                    if counts is not None and counts[0] > 0:
                        response[params.RESOURCE] = {
                            params.DATA_MODIFIED: True
                        }
                    else:
                        response[params.RESOURCE] = {
                            params.DATA_MODIFIED: False
                        }
                elif self._delete_mode == params.DELETE_MODE_HARD:
                    # remove the metadata
                    response[params.METADATA] = {
                        params.DATA_MODIFIED: self._delete_metadata(id)
                    }

                    # delete the database record
                    response[params.RESOURCE] = {
                        params.DATA_MODIFIED:
                        self._delete_record(
                            table_name=self._resource_table_name, item_id=id)
                    }
                else:
                    # tombstone deletions not supported in rdbms due to nullability constraints
                    raise exceptions.UnimplementedFeatureException(
                        "Cannot Tombstone Delete in RDBMS")
            else:
                # remove resource attributes only
                response[params.RESOURCE] = {
                    params.DATA_MODIFIED:
                    self.remove_resource_attributes(
                        id=id,
                        resource_attributes=kwargs.get(params.RESOURCE),
                        caller_identity=caller_identity)
                }

        return response