chainalysis.data_solutions_table package

Submodules

chainalysis.data_solutions_table.analytical_table module

class chainalysis.data_solutions_table.analytical_table.AnalyticalTable(api_key: str, chain_table_name: str)[source]

Bases: Select

The AnalyticalTable class implements the Select base class for querying a chain-specific table within the Data Solutions system.

It provides the structure for constructing and executing SQL queries using Common Table Expressions.

execute(polling_interval_sec: int = 5, autopaginate: bool = True) Analytical[source]

Execute the query and return an Analytical object.

Parameters:
  • polling_interval_sec (int, optional) – The interval in seconds between status checks. The minimum value is 5 seconds.

  • autopaginate (bool, optional) – Whether to automatically retrieve full results instead of individual pages.

Returns:

Analytical object.

Return type:

Analytical

get_table(chain, table) Table[source]

Return a SQLAlchemy Table object for the given chain and table name.

Parameters:
  • chain (str) – The chain name.

  • table (str) – The table name.

Returns:

A SQLAlchemy Table object.

Return type:

Table

Raises:

ValueException – If the chain or table does not exist in the database.

chainalysis.data_solutions_table.data_solutions_table module

class chainalysis.data_solutions_table.data_solutions_table.Select(api_key: str, chain_table_name: str)[source]

Bases: Select, ABC

Select is an abstract base class that represents an interface for querying a chain-specific table within the Data Solutions system.

It provides the structure for constructing and executing SQL queries using Common Table Expressions. Child classes must implement methods to retrieve tables and execute queries, which will return the appropriate result type.

__init__(api_key: str, chain_table_name: str)[source]

Initialize the Select object.

Parameters:
  • api_key (str) – The API key for the Data Solutions API.

  • chain_table_name (str) – The chain and table name formatted as ‘chain.table’.

Raises:

ValueException – If the table name is not formatted correctly.

property c: ColumnCollection

Return the columns of the table.

Returns:

A collection of column objects associated with the table.

Return type:

ColumnCollection

abstract execute() Transactional | Analytical[source]

Execute the query and return a Transactional or Analytical object.

Returns:

Transactional or Analytical object.

Return type:

Union[Transactional, Analytical]

abstract get_table(chain, table: str) Table[source]

Return a SQLAlchemy Table object for the given chain and table name.

Parameters:
  • chain – The chain name.

  • table – The table name.

Returns:

A SQLAlchemy Table object.

Return type:

Table

Raises:

ValueException – If the chain or table does not exist in the database.

select(*columns) Select[source]

Select specific columns from the table for querying.

Parameters:

columns (Column) – The columns to be selected.

Returns:

The Select instance with the selected columns.

Return type:

Select

sql() str[source]

Compile the query into a raw SQL string.

Returns:

The compiled SQL query as a string.

Return type:

str

chainalysis.data_solutions_table.data_solutions_table.and_(*clauses)[source]

Produce a conjunction of expressions joined by AND.

E.g.:

from sqlalchemy import and_

stmt = select(users_table).where(
                and_(
                    users_table.c.name == 'wendy',
                    users_table.c.enrolled == True
                )
            )

The and_() conjunction is also available using the Python & operator (though note that compound expressions need to be parenthesized in order to function with Python operator precedence behavior):

stmt = select(users_table).where(
                (users_table.c.name == 'wendy') &
                (users_table.c.enrolled == True)
            )

The and_() operation is also implicit in some cases; the _expression.Select.where() method for example can be invoked multiple times against a statement, which will have the effect of each clause being combined using and_():

stmt = select(users_table).\
        where(users_table.c.name == 'wendy').\
        where(users_table.c.enrolled == True)

The and_() construct must be given at least one positional argument in order to be valid; a and_() construct with no arguments is ambiguous. To produce an “empty” or dynamically generated and_() expression, from a given list of expressions, a “default” element of _sql.true() (or just True) should be specified:

from sqlalchemy import true
criteria = and_(true(), *expressions)

The above expression will compile to SQL as the expression true or 1 = 1, depending on backend, if no other expressions are present. If expressions are present, then the _sql.true() value is ignored as it does not affect the outcome of an AND expression that has other elements.

Deprecated since version 1.4: The and_() element now requires that at least one argument is passed; creating the and_() construct with no arguments is deprecated, and will emit a deprecation warning while continuing to produce a blank SQL string.

See also

or_()

chainalysis.data_solutions_table.data_solutions_table.between(expr: _ColumnExpressionOrLiteralArgument[_T], lower_bound: Any, upper_bound: Any, symmetric: bool = False) BinaryExpression[bool][source]

Produce a BETWEEN predicate clause.

E.g.:

from sqlalchemy import between
stmt = select(users_table).where(between(users_table.c.id, 5, 7))

Would produce SQL resembling:

SELECT id, name FROM user WHERE id BETWEEN :id_1 AND :id_2

The between() function is a standalone version of the _expression.ColumnElement.between() method available on all SQL expressions, as in:

stmt = select(users_table).where(users_table.c.id.between(5, 7))

All arguments passed to between(), including the left side column expression, are coerced from Python scalar values if a the value is not a _expression.ColumnElement subclass. For example, three fixed values can be compared as in:

print(between(5, 3, 7))

Which would produce:

:param_1 BETWEEN :param_2 AND :param_3
Parameters:
  • expr – a column expression, typically a _expression.ColumnElement instance or alternatively a Python scalar expression to be coerced into a column expression, serving as the left side of the BETWEEN expression.

  • lower_bound – a column or Python scalar expression serving as the lower bound of the right side of the BETWEEN expression.

  • upper_bound – a column or Python scalar expression serving as the upper bound of the right side of the BETWEEN expression.

  • symmetric – if True, will render “ BETWEEN SYMMETRIC “. Note that not all databases support this syntax.

See also

_expression.ColumnElement.between()

chainalysis.data_solutions_table.data_solutions_table.case(*whens: typing_Tuple[_ColumnExpressionArgument[bool], Any] | Mapping[Any, Any], value: Any | None = None, else_: Any | None = None) Case[Any][source]

Produce a CASE expression.

The CASE construct in SQL is a conditional object that acts somewhat analogously to an “if/then” construct in other languages. It returns an instance of Case.

case() in its usual form is passed a series of “when” constructs, that is, a list of conditions and results as tuples:

from sqlalchemy import case

stmt = select(users_table).\
            where(
                case(
                    (users_table.c.name == 'wendy', 'W'),
                    (users_table.c.name == 'jack', 'J'),
                    else_='E'
                )
            )

The above statement will produce SQL resembling:

SELECT id, name FROM user
WHERE CASE
    WHEN (name = :name_1) THEN :param_1
    WHEN (name = :name_2) THEN :param_2
    ELSE :param_3
END

When simple equality expressions of several values against a single parent column are needed, case() also has a “shorthand” format used via the :paramref:`.case.value` parameter, which is passed a column expression to be compared. In this form, the :paramref:`.case.whens` parameter is passed as a dictionary containing expressions to be compared against keyed to result expressions. The statement below is equivalent to the preceding statement:

stmt = select(users_table).\
            where(
                case(
                    {"wendy": "W", "jack": "J"},
                    value=users_table.c.name,
                    else_='E'
                )
            )

The values which are accepted as result values in :paramref:`.case.whens` as well as with :paramref:`.case.else_` are coerced from Python literals into bindparam() constructs. SQL expressions, e.g. _expression.ColumnElement constructs, are accepted as well. To coerce a literal string expression into a constant expression rendered inline, use the _expression.literal_column() construct, as in:

from sqlalchemy import case, literal_column

case(
    (
        orderline.c.qty > 100,
        literal_column("'greaterthan100'")
    ),
    (
        orderline.c.qty > 10,
        literal_column("'greaterthan10'")
    ),
    else_=literal_column("'lessthan10'")
)

The above will render the given constants without using bound parameters for the result values (but still for the comparison values), as in:

CASE
    WHEN (orderline.qty > :qty_1) THEN 'greaterthan100'
    WHEN (orderline.qty > :qty_2) THEN 'greaterthan10'
    ELSE 'lessthan10'
END
Parameters:
  • *whens

    The criteria to be compared against, :paramref:`.case.whens` accepts two different forms, based on whether or not :paramref:`.case.value` is used.

    Changed in version 1.4: the _sql.case() function now accepts the series of WHEN conditions positionally

    In the first form, it accepts multiple 2-tuples passed as positional arguments; each 2-tuple consists of (<sql expression>, <value>), where the SQL expression is a boolean expression and “value” is a resulting value, e.g.:

    case(
        (users_table.c.name == 'wendy', 'W'),
        (users_table.c.name == 'jack', 'J')
    )
    

    In the second form, it accepts a Python dictionary of comparison values mapped to a resulting value; this form requires :paramref:`.case.value` to be present, and values will be compared using the == operator, e.g.:

    case(
        {"wendy": "W", "jack": "J"},
        value=users_table.c.name
    )
    

  • value – An optional SQL expression which will be used as a fixed “comparison point” for candidate values within a dictionary passed to :paramref:`.case.whens`.

  • else_ – An optional SQL expression which will be the evaluated result of the CASE construct if all expressions within :paramref:`.case.whens` evaluate to false. When omitted, most databases will produce a result of NULL if none of the “when” expressions evaluate to true.

chainalysis.data_solutions_table.data_solutions_table.distinct(expr: _ColumnExpressionArgument[_T]) UnaryExpression[_T][source]

Produce an column-expression-level unary DISTINCT clause.

This applies the DISTINCT keyword to an individual column expression (e.g. not the whole statement), and renders specifically in that column position; this is used for containment within an aggregate function, as in:

from sqlalchemy import distinct, func
stmt = select(users_table.c.id, func.count(distinct(users_table.c.name)))

The above would produce an statement resembling:

SELECT user.id, count(DISTINCT user.name) FROM user

Tip

The _sql.distinct() function does not apply DISTINCT to the full SELECT statement, instead applying a DISTINCT modifier to individual column expressions. For general SELECT DISTINCT support, use the _sql.Select.distinct() method on _sql.Select.

The distinct() function is also available as a column-level method, e.g. _expression.ColumnElement.distinct(), as in:

stmt = select(func.count(users_table.c.name.distinct()))

The distinct() operator is different from the _expression.Select.distinct() method of _expression.Select, which produces a SELECT statement with DISTINCT applied to the result set as a whole, e.g. a SELECT DISTINCT expression. See that method for further information.

See also

_expression.ColumnElement.distinct()

_expression.Select.distinct()

func

chainalysis.data_solutions_table.data_solutions_table.except_(*selects: _SelectStatementForCompoundArgument) CompoundSelect[source]

Return an EXCEPT of multiple selectables.

The returned object is an instance of _expression.CompoundSelect.

Parameters:

*selects – a list of _expression.Select instances.

chainalysis.data_solutions_table.data_solutions_table.except_all(*selects: _SelectStatementForCompoundArgument) CompoundSelect[source]

Return an EXCEPT ALL of multiple selectables.

The returned object is an instance of _expression.CompoundSelect.

Parameters:

*selects – a list of _expression.Select instances.

chainalysis.data_solutions_table.data_solutions_table.exists(__argument: _ColumnsClauseArgument[Any] | SelectBase | ScalarSelect[Any] | None = None) Exists[source]

Construct a new _expression.Exists construct.

The _sql.exists() can be invoked by itself to produce an _sql.Exists construct, which will accept simple WHERE criteria:

exists_criteria = exists().where(table1.c.col1 == table2.c.col2)

However, for greater flexibility in constructing the SELECT, an existing _sql.Select construct may be converted to an _sql.Exists, most conveniently by making use of the _sql.SelectBase.exists() method:

exists_criteria = (
    select(table2.c.col2).
    where(table1.c.col1 == table2.c.col2).
    exists()
)

The EXISTS criteria is then used inside of an enclosing SELECT:

stmt = select(table1.c.col1).where(exists_criteria)

The above statement will then be of the form:

SELECT col1 FROM table1 WHERE EXISTS
(SELECT table2.col2 FROM table2 WHERE table2.col2 = table1.col1)

See also

tutorial_exists - in the 2.0 style tutorial.

_sql.SelectBase.exists() - method to transform a SELECT to an EXISTS clause.

chainalysis.data_solutions_table.data_solutions_table.intersect(*selects: _SelectStatementForCompoundArgument) CompoundSelect[source]

Return an INTERSECT of multiple selectables.

The returned object is an instance of _expression.CompoundSelect.

Parameters:

*selects – a list of _expression.Select instances.

chainalysis.data_solutions_table.data_solutions_table.intersect_all(*selects: _SelectStatementForCompoundArgument) CompoundSelect[source]

Return an INTERSECT ALL of multiple selectables.

The returned object is an instance of _expression.CompoundSelect.

Parameters:

*selects – a list of _expression.Select instances.

chainalysis.data_solutions_table.data_solutions_table.join(left: _FromClauseArgument, right: _FromClauseArgument, onclause: _OnClauseArgument | None = None, isouter: bool = False, full: bool = False) Join[source]

Produce a _expression.Join object, given two _expression.FromClause expressions.

E.g.:

j = join(user_table, address_table,
         user_table.c.id == address_table.c.user_id)
stmt = select(user_table).select_from(j)

would emit SQL along the lines of:

SELECT user.id, user.name FROM user
JOIN address ON user.id = address.user_id

Similar functionality is available given any _expression.FromClause object (e.g. such as a _schema.Table) using the _expression.FromClause.join() method.

Parameters:
  • left – The left side of the join.

  • right – the right side of the join; this is any _expression.FromClause object such as a _schema.Table object, and may also be a selectable-compatible object such as an ORM-mapped class.

  • onclause – a SQL expression representing the ON clause of the join. If left at None, _expression.FromClause.join() will attempt to join the two tables based on a foreign key relationship.

  • isouter – if True, render a LEFT OUTER JOIN, instead of JOIN.

  • full – if True, render a FULL OUTER JOIN, instead of JOIN.

See also

_expression.FromClause.join() - method form, based on a given left side.

_expression.Join - the type of object produced.

chainalysis.data_solutions_table.data_solutions_table.lateral(selectable: SelectBase | _FromClauseArgument, name: str | None = None) LateralFromClause[source]

Return a _expression.Lateral object.

_expression.Lateral is an _expression.Alias subclass that represents a subquery with the LATERAL keyword applied to it.

The special behavior of a LATERAL subquery is that it appears in the FROM clause of an enclosing SELECT, but may correlate to other FROM clauses of that SELECT. It is a special case of subquery only supported by a small number of backends, currently more recent PostgreSQL versions.

See also

tutorial_lateral_correlation - overview of usage.

chainalysis.data_solutions_table.data_solutions_table.literal(value: Any, type_: _TypeEngineArgument[Any] | None = None, literal_execute: bool = False) BindParameter[Any][source]

Return a literal clause, bound to a bind parameter.

Literal clauses are created automatically when non- _expression.ClauseElement objects (such as strings, ints, dates, etc.) are used in a comparison operation with a _expression.ColumnElement subclass, such as a Column object. Use this function to force the generation of a literal clause, which will be created as a BindParameter with a bound value.

Parameters:
  • value – the value to be bound. Can be any Python object supported by the underlying DB-API, or is translatable via the given type argument.

  • type_ – an optional TypeEngine which will provide bind-parameter translation for this literal.

  • literal_execute

    optional bool, when True, the SQL engine will attempt to render the bound value directly in the SQL statement at execution time rather than providing as a parameter value.

    Added in version 2.0.

chainalysis.data_solutions_table.data_solutions_table.not_(clause: _ColumnExpressionArgument[_T]) ColumnElement[_T][source]

Return a negation of the given clause, i.e. NOT(clause).

The ~ operator is also overloaded on all _expression.ColumnElement subclasses to produce the same result.

chainalysis.data_solutions_table.data_solutions_table.or_(*clauses)[source]

Produce a conjunction of expressions joined by OR.

E.g.:

from sqlalchemy import or_

stmt = select(users_table).where(
                or_(
                    users_table.c.name == 'wendy',
                    users_table.c.name == 'jack'
                )
            )

The or_() conjunction is also available using the Python | operator (though note that compound expressions need to be parenthesized in order to function with Python operator precedence behavior):

stmt = select(users_table).where(
                (users_table.c.name == 'wendy') |
                (users_table.c.name == 'jack')
            )

The or_() construct must be given at least one positional argument in order to be valid; a or_() construct with no arguments is ambiguous. To produce an “empty” or dynamically generated or_() expression, from a given list of expressions, a “default” element of _sql.false() (or just False) should be specified:

from sqlalchemy import false
or_criteria = or_(false(), *expressions)

The above expression will compile to SQL as the expression false or 0 = 1, depending on backend, if no other expressions are present. If expressions are present, then the _sql.false() value is ignored as it does not affect the outcome of an OR expression which has other elements.

Deprecated since version 1.4: The or_() element now requires that at least one argument is passed; creating the or_() construct with no arguments is deprecated, and will emit a deprecation warning while continuing to produce a blank SQL string.

See also

and_()

chainalysis.data_solutions_table.data_solutions_table.outerjoin(left: _FromClauseArgument, right: _FromClauseArgument, onclause: _OnClauseArgument | None = None, full: bool = False) Join[source]

Return an OUTER JOIN clause element.

The returned object is an instance of _expression.Join.

Similar functionality is also available via the _expression.FromClause.outerjoin() method on any _expression.FromClause.

Parameters:
  • left – The left side of the join.

  • right – The right side of the join.

  • onclause – Optional criterion for the ON clause, is derived from foreign key relationships established between left and right otherwise.

To chain joins together, use the _expression.FromClause.join() or _expression.FromClause.outerjoin() methods on the resulting _expression.Join object.

chainalysis.data_solutions_table.data_solutions_table.union(*selects: _SelectStatementForCompoundArgument) CompoundSelect[source]

Return a UNION of multiple selectables.

The returned object is an instance of _expression.CompoundSelect.

A similar union() method is available on all _expression.FromClause subclasses.

Parameters:
  • *selects – a list of _expression.Select instances.

  • **kwargs – available keyword arguments are the same as those of with_columns().

chainalysis.data_solutions_table.data_solutions_table.union_all(*selects: _SelectStatementForCompoundArgument) CompoundSelect[source]

Return a UNION ALL of multiple selectables.

The returned object is an instance of _expression.CompoundSelect.

A similar union_all() method is available on all _expression.FromClause subclasses.

Parameters:

*selects – a list of _expression.Select instances.

chainalysis.data_solutions_table.transactional_table module

class chainalysis.data_solutions_table.transactional_table.TransactionalTable(api_key: str, chain_table_name: str)[source]

Bases: Select

The TransactionalTable class implements the Select base class for querying a chain-specific table within the Data Solutions system.

It provides the structure for constructing and executing SQL queries using Common Table Expressions.

execute(options: dict = {}) Transactional[source]

Execute the query and return a Transactional object.

Parameters:

options (dict) – The options for the query.

Returns:

Transactional object.

Return type:

Transactional

get_table(chain, table) None[source]

Return a SQLAlchemy Table object for the given chain and table name.

Parameters:
  • chain (str) – The chain name.

  • table (str) – The table name.

Returns:

A SQLAlchemy Table object.

Return type:

Table

Raises:

ValueException – If the chain or table does not exist in the database.

Module contents