Skip to content

[BUG] multiple errors in ClickHouse dialect #480

@Slach

Description

@Slach

Bug Description

table could be field name, lot of queries can't be parsed properly

Code Example

package expert

import (
	"testing"

	"github.com/ajitpratap0/GoSQLX/pkg/gosqlx"
	"github.com/ajitpratap0/GoSQLX/pkg/sql/keywords"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestGoSQLXParsesClickHouseQueries(t *testing.T) {
	queries := map[string]string{
		"replicas_with_table_column": `SELECT
    database,
    table,
    is_leader,
    is_readonly,
    is_session_expired,
    parts_to_check,
    queue_size,
    inserts_in_queue,
    merges_in_queue,
    absolute_delay,
    last_queue_update,
    zookeeper_path
FROM system.replicas
ORDER BY absolute_delay DESC`,

		"tables_with_bytes_on_disk": `SELECT
    database,
    table,
    engine,
    formatReadableSize(bytes_on_disk) AS size,
    parts,
    active_parts
FROM system.tables
WHERE engine LIKE '%MergeTree%'
  AND is_temporary = 0
ORDER BY bytes_on_disk DESC
LIMIT 10`,

		"tables_with_total_bytes": `SELECT
    database,
    table,
    engine,
    formatReadableSize(total_bytes) AS size,
    parts,
    active_parts
FROM system.tables
WHERE engine LIKE '%MergeTree%'
  AND is_temporary = 0
ORDER BY total_bytes DESC
LIMIT 10`,

		"parts_with_concat_table": `SELECT
    concat(database, '.' ,table) AS table_name,
    count() AS part_count,
    max(partition) AS latest_partition,
    formatReadableSize(sum(bytes_on_disk)) AS total_size
FROM system.parts
WHERE active = 1
  AND database NOT IN ('system')
GROUP BY database, table
ORDER BY part_count DESC
LIMIT 10`,

		"parts_having_count": `SELECT
    database,
    table,
    count() AS parts,
    formatReadableSize(sum(bytes_on_disk)) AS size
FROM system.parts
WHERE active = 1
  AND database NOT IN ('system')
GROUP BY database, table
HAVING parts > 300
ORDER BY parts DESC`,
	}

	for name, query := range queries {
		t.Run(name, func(t *testing.T) {
			parsed, err := gosqlx.ParseWithDialect(query, keywords.DialectClickHouse)
			require.NoError(t, err, "gosqlx.ParseWithDialect should parse ClickHouse query without error")
			assert.NotNil(t, parsed, "parsed AST should not be nil")
		})
	}
}

Expected Behavior

All queries parsed

Actual Behavior

2026-04-03 10:12:54.619 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 3, column 5: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    database, \n    table, \n    is_leader, \n    is_readonly, \n    is_session_expired, \n    parts_to_check, \n    queue_size, \n    inserts_in_queue, \n    merges_in_queue,\n    absolute_delay,\n    last_queue_update,\n    zookeeper_path\nFROM system.replicas \nORDER BY absolute_delay DESC" version=dev
2026-04-03 10:12:54.623 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 3, column 5: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    database, \n    table, \n    engine, \n    formatReadableSize(bytes_on_disk) AS size, \n    parts, \n    active_parts\nFROM system.tables \nWHERE engine LIKE '%MergeTree%' \n  AND is_temporary = 0 \nORDER BY bytes_on_disk DESC \nLIMIT 10" version=dev
2026-04-03 10:12:54.624 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 3, column 5: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    database, \n    table, \n    engine, \n    formatReadableSize(total_bytes) AS size, \n    parts, \n    active_parts\nFROM system.tables \nWHERE engine LIKE '%MergeTree%' \n  AND is_temporary = 0 \nORDER BY total_bytes DESC \nLIMIT 10" version=dev
2026-04-03 10:12:54.626 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 2, column 27: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    concat(database, '.' ,table) AS table_name,\n    count() AS part_count,\n    max(partition) AS latest_partition,\n    formatReadableSize(sum(bytes_on_disk)) AS total_size\nFROM system.parts \nWHERE active = 1 \n  AND database NOT IN ('system')\nGROUP BY database, table\nORDER BY part_count DESC\nLIMIT 10" version=dev
2026-04-03 10:12:54.627 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 3, column 5: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    database,\n    table,\n    count() AS parts,\n    formatReadableSize(sum(bytes_on_disk)) AS size\nFROM system.parts \nWHERE active = 1\n  AND database NOT IN ('system')\nGROUP BY database, table\nHAVING parts > 300\nORDER BY parts DESC" version=dev
2026-04-03 10:14:29.395 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 3, column 5: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    database, \n    table, \n    is_leader, \n    is_readonly, \n    is_session_expired, \n    parts_to_check, \n    queue_size, \n    inserts_in_queue, \n    merges_in_queue,\n    absolute_delay,\n    last_queue_update,\n    zookeeper_path\nFROM system.replicas \nORDER BY absolute_delay DESC" version=dev
2026-04-03 10:14:29.399 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 3, column 5: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    database, \n    table, \n    engine, \n    formatReadableSize(bytes_on_disk) AS size, \n    parts, \n    active_parts\nFROM system.tables \nWHERE engine LIKE '%MergeTree%' \n  AND is_temporary = 0 \nORDER BY bytes_on_disk DESC \nLIMIT 10" version=dev
2026-04-03 10:14:29.400 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 3, column 5: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    database, \n    table, \n    engine, \n    formatReadableSize(total_bytes) AS size, \n    parts, \n    active_parts\nFROM system.tables \nWHERE engine LIKE '%MergeTree%' \n  AND is_temporary = 0 \nORDER BY total_bytes DESC \nLIMIT 10" version=dev
2026-04-03 10:14:29.402 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 2, column 27: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    concat(database, '.' ,table) AS table_name,\n    count() AS part_count,\n    max(partition) AS latest_partition,\n    formatReadableSize(sum(bytes_on_disk)) AS total_size\nFROM system.parts \nWHERE active = 1 \n  AND database NOT IN ('system')\nGROUP BY database, table\nORDER BY part_count DESC\nLIMIT 10" version=dev
2026-04-03 10:14:29.403 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 3, column 5: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    database,\n    table,\n    count() AS parts,\n    formatReadableSize(sum(bytes_on_disk)) AS size\nFROM system.parts \nWHERE active = 1\n  AND database NOT IN ('system')\nGROUP BY database, table\nHAVING parts > 300\nORDER BY parts DESC" version=dev
2026-04-03 10:14:36.923 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 3, column 5: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    database, \n    table, \n    is_leader, \n    is_readonly, \n    is_session_expired, \n    parts_to_check, \n    queue_size, \n    inserts_in_queue, \n    merges_in_queue,\n    absolute_delay,\n    last_queue_update,\n    zookeeper_path\nFROM system.replicas \nORDER BY absolute_delay DESC" version=dev
2026-04-03 10:14:36.927 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 3, column 5: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    database, \n    table, \n    engine, \n    formatReadableSize(bytes_on_disk) AS size, \n    parts, \n    active_parts\nFROM system.tables \nWHERE engine LIKE '%MergeTree%' \n  AND is_temporary = 0 \nORDER BY bytes_on_disk DESC \nLIMIT 10" version=dev
2026-04-03 10:14:36.928 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 3, column 5: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    database, \n    table, \n    engine, \n    formatReadableSize(total_bytes) AS size, \n    parts, \n    active_parts\nFROM system.tables \nWHERE engine LIKE '%MergeTree%' \n  AND is_temporary = 0 \nORDER BY total_bytes DESC \nLIMIT 10" version=dev
2026-04-03 10:14:36.931 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 2, column 27: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    concat(database, '.' ,table) AS table_name,\n    count() AS part_count,\n    max(partition) AS latest_partition,\n    formatReadableSize(sum(bytes_on_disk)) AS total_size\nFROM system.parts \nWHERE active = 1 \n  AND database NOT IN ('system')\nGROUP BY database, table\nORDER BY part_count DESC\nLIMIT 10" version=dev
2026-04-03 10:14:36.932 DBG pkg/sqlfmt/format.go:20 > gosqlx.ParseWithDialect failed, falling back to regexp formatter error="Error E2001 at line 3, column 5: unexpected token: TABLE ('table')\n\n\nHint: Check the SQL syntax at this position\nHelp: https://github.com/ajitpratap0/GoSQLX/blob/main/docs/ERROR_CODES.md#E2001" original_query="SELECT \n    database,\n    table,\n    count() AS parts,\n    formatReadableSize(sum(bytes_on_disk)) AS size\nFROM system.parts \nWHERE active = 1\n  AND database NOT IN ('system')\nGROUP BY database, table\nHAVING parts > 300\nORDER BY parts DESC" version=dev

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions