@@ -342,19 +342,66 @@ func (c *ClickHouseConnector) GetTransactions(qf QueryFilter) (QueryResult[commo
342342 return executeQuery [common.Transaction ](c , "transactions" , columns , qf , scanTransaction )
343343}
344344
345- func (c * ClickHouseConnector ) GetLogs (qf QueryFilter ) (QueryResult [map [string ]interface {}], error ) {
346- var columns string
345+ func (c * ClickHouseConnector ) GetLogs (qf QueryFilter ) (QueryResult [common.Log ], error ) {
346+ columns := "chain_id, block_number, block_hash, block_timestamp, transaction_hash, transaction_index, log_index, address, data, topic_0, topic_1, topic_2, topic_3"
347+ return executeQuery [common.Log ](c , "logs" , columns , qf , scanLog )
348+ }
349+
350+ func (c * ClickHouseConnector ) GetAggregations (table string , qf QueryFilter ) (QueryResult [interface {}], error ) {
351+ // Build the SELECT clause with aggregates
352+ columns := strings .Join (append (qf .GroupBy , qf .Aggregates ... ), ", " )
353+ query := fmt .Sprintf ("SELECT %s FROM %s.%s WHERE is_deleted = 0" , columns , c .cfg .Database , table )
354+
355+ // Apply filters
356+ if qf .ChainId != nil && qf .ChainId .Sign () > 0 {
357+ query = addFilterParams ("chain_id" , qf .ChainId .String (), query )
358+ }
359+ query = addContractAddress (table , query , qf .ContractAddress )
360+
361+ if qf .Signature != "" {
362+ query += fmt .Sprintf (" AND topic_0 = '%s'" , qf .Signature )
363+ }
347364
348- if len (qf .GroupBy ) > 0 || len (qf .Aggregates ) > 0 {
349- // Build columns for SELECT when grouping or aggregating
350- selectColumns := append (qf .GroupBy , qf .Aggregates ... )
351- columns = strings .Join (selectColumns , ", " )
352- } else {
353- // Default columns when not grouping
354- columns = "chain_id, block_number, block_hash, block_timestamp, transaction_hash, transaction_index, log_index, address, data, topic_0, topic_1, topic_2, topic_3"
365+ for key , value := range qf .FilterParams {
366+ query = addFilterParams (key , strings .ToLower (value ), query )
355367 }
356368
357- return executeQuery [map [string ]interface {}](c , "logs" , columns , qf , scanRowToMap )
369+ // Add GROUP BY clause if specified
370+ if len (qf .GroupBy ) > 0 {
371+ groupByColumns := strings .Join (qf .GroupBy , ", " )
372+ query += fmt .Sprintf (" GROUP BY %s" , groupByColumns )
373+ }
374+
375+ // Execute the query
376+ rows , err := c .conn .Query (context .Background (), query )
377+ if err != nil {
378+ return QueryResult [interface {}]{}, err
379+ }
380+ defer rows .Close ()
381+
382+ // Collect results
383+ var aggregates []map [string ]interface {}
384+ for rows .Next () {
385+ columns := rows .Columns ()
386+ values := make ([]interface {}, len (columns ))
387+ valuePtrs := make ([]interface {}, len (columns ))
388+ for i := range columns {
389+ valuePtrs [i ] = & values [i ]
390+ }
391+
392+ if err := rows .Scan (valuePtrs ... ); err != nil {
393+ return QueryResult [interface {}]{}, err
394+ }
395+
396+ result := make (map [string ]interface {})
397+ for i , col := range columns {
398+ result [col ] = values [i ]
399+ }
400+
401+ aggregates = append (aggregates , result )
402+ }
403+
404+ return QueryResult [interface {}]{Data : nil , Aggregates : aggregates }, nil
358405}
359406
360407func executeQuery [T any ](c * ClickHouseConnector , table , columns string , qf QueryFilter , scanFunc func (driver.Rows ) (T , error )) (QueryResult [T ], error ) {
@@ -367,8 +414,7 @@ func executeQuery[T any](c *ClickHouseConnector, table, columns string, qf Query
367414 defer rows .Close ()
368415
369416 queryResult := QueryResult [T ]{
370- Data : []T {},
371- Aggregates : map [string ]string {},
417+ Data : []T {},
372418 }
373419
374420 for rows .Next () {
@@ -379,21 +425,13 @@ func executeQuery[T any](c *ClickHouseConnector, table, columns string, qf Query
379425 queryResult .Data = append (queryResult .Data , item )
380426 }
381427
382- if len (qf .Aggregates ) > 0 {
383- aggregates , err := c .executeAggregateQuery (table , qf )
384- if err != nil {
385- return queryResult , err
386- }
387- queryResult .Aggregates = aggregates
388- }
389-
390428 return queryResult , nil
391429}
392430
393431func (c * ClickHouseConnector ) buildQuery (table , columns string , qf QueryFilter ) string {
394432 query := fmt .Sprintf ("SELECT %s FROM %s.%s WHERE is_deleted = 0" , columns , c .cfg .Database , table )
395433
396- if qf .ChainId .Sign () > 0 {
434+ if qf .ChainId != nil && qf . ChainId .Sign () > 0 {
397435 query = addFilterParams ("chain_id" , qf .ChainId .String (), query )
398436 }
399437 query = addContractAddress (table , query , qf .ContractAddress )
@@ -407,12 +445,6 @@ func (c *ClickHouseConnector) buildQuery(table, columns string, qf QueryFilter)
407445 query = addFilterParams (key , strings .ToLower (value ), query )
408446 }
409447
410- // Add GROUP BY clause if specified
411- if len (qf .GroupBy ) > 0 {
412- groupByColumns := strings .Join (qf .GroupBy , ", " )
413- query += fmt .Sprintf (" GROUP BY %s" , groupByColumns )
414- }
415-
416448 // Add ORDER BY clause
417449 if qf .SortBy != "" {
418450 query += fmt .Sprintf (" ORDER BY %s %s" , qf .SortBy , qf .SortOrder )
@@ -422,9 +454,8 @@ func (c *ClickHouseConnector) buildQuery(table, columns string, qf QueryFilter)
422454 if qf .Page > 0 && qf .Limit > 0 {
423455 offset := (qf .Page - 1 ) * qf .Limit
424456 query += fmt .Sprintf (" LIMIT %d OFFSET %d" , qf .Limit , offset )
425- } else {
426- // Add limit clause
427- query += getLimitClause (int (qf .Limit ))
457+ } else if qf .Limit > 0 {
458+ query += fmt .Sprintf (" LIMIT %d" , qf .Limit )
428459 }
429460
430461 return query
@@ -484,35 +515,6 @@ func getTopicValueFormat(topic string) string {
484515 return result
485516}
486517
487- func (c * ClickHouseConnector ) executeAggregateQuery (table string , qf QueryFilter ) (map [string ]string , error ) {
488- aggregateQuery := "SELECT " + strings .Join (qf .Aggregates , ", " ) +
489- fmt .Sprintf (" FROM %s.%s WHERE is_deleted = 0" , c .cfg .Database , table )
490-
491- if qf .ContractAddress != "" {
492- aggregateQuery += fmt .Sprintf (" AND address = '%s'" , qf .ContractAddress )
493- }
494- if qf .Signature != "" {
495- aggregateQuery += fmt .Sprintf (" AND topic_0 = '%s'" , qf .Signature )
496- }
497- for key , value := range qf .FilterParams {
498- aggregateQuery += fmt .Sprintf (" AND %s = '%s'" , key , value )
499- }
500-
501- row := c .conn .QueryRow (context .Background (), aggregateQuery )
502- aggregateResultsJSON , err := json .Marshal (row )
503- if err != nil {
504- return nil , fmt .Errorf ("error marshaling aggregate results to JSON: %w" , err )
505- }
506-
507- var aggregateResultsMap map [string ]string
508- err = json .Unmarshal (aggregateResultsJSON , & aggregateResultsMap )
509- if err != nil {
510- return nil , fmt .Errorf ("error unmarshaling aggregate results JSON to map: %w" , err )
511- }
512-
513- return aggregateResultsMap , nil
514- }
515-
516518func scanTransaction (rows driver.Rows ) (common.Transaction , error ) {
517519 var tx common.Transaction
518520 err := rows .Scan (
@@ -572,27 +574,6 @@ func scanLog(rows driver.Rows) (common.Log, error) {
572574 return log , nil
573575}
574576
575- func scanRowToMap (rows driver.Rows ) (map [string ]interface {}, error ) {
576- columns := rows .Columns ()
577- values := make ([]interface {}, len (columns ))
578- valuePtrs := make ([]interface {}, len (columns ))
579-
580- for i := range columns {
581- valuePtrs [i ] = & values [i ]
582- }
583-
584- if err := rows .Scan (valuePtrs ... ); err != nil {
585- return nil , err
586- }
587-
588- result := make (map [string ]interface {})
589- for i , col := range columns {
590- result [col ] = values [i ]
591- }
592-
593- return result , nil
594- }
595-
596577func (c * ClickHouseConnector ) GetMaxBlockNumber (chainId * big.Int ) (maxBlockNumber * big.Int , err error ) {
597578 query := fmt .Sprintf ("SELECT number FROM %s.blocks WHERE is_deleted = 0" , c .cfg .Database )
598579 if chainId .Sign () > 0 {
0 commit comments