Skip to content

sqlite: column "id" does not exist for left-joined query #2271

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
diamondburned opened this issue May 7, 2023 · 3 comments · Fixed by #2465
Closed

sqlite: column "id" does not exist for left-joined query #2271

diamondburned opened this issue May 7, 2023 · 3 comments · Fixed by #2465

Comments

@diamondburned
Copy link

diamondburned commented May 7, 2023

Version

1.17.2 (also happens with 1.18.0)

What happened?

With the query posted below, sqlc will return the following error:

sqlite/queries.sql:3:2: column "id" does not exist

Relevant log output

No response

Database schema

CREATE TABLE IF NOT EXISTS users (
	id TEXT PRIMARY KEY, -- github user ID
	username TEXT NOT NULL, -- login
	email TEXT NOT NULL,
	real_name TEXT NOT NULL,
	pronouns TEXT NOT NULL,
	avatar_url TEXT NOT NULL,
	joined_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
	is_owner BOOLEAN NOT NULL DEFAULT FALSE,
	preferences BLOB NOT NULL DEFAULT '{}'
);

CREATE TABLE IF NOT EXISTS tiers (
	id TEXT PRIMARY KEY, -- github tier ID
	name TEXT NOT NULL,
	price INTEGER NOT NULL, -- cents
	description TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS user_tiers (
	user_id TEXT UNIQUE NOT NULL REFERENCES users(id) ON DELETE CASCADE,
	tier_id TEXT REFERENCES tiers(id) ON DELETE SET NULL,
	price INTEGER NOT NULL, -- cents
	is_one_time BOOLEAN NOT NULL DEFAULT FALSE,
	is_custom_amount BOOLEAN NOT NULL DEFAULT FALSE,
	started_at TIMESTAMP NOT NULL,
	renewed_at TIMESTAMP NOT NULL
);

SQL queries

-- name: User :one
SELECT
	users.id, users.username, users.email, users.real_name, users.pronouns, users.avatar_url, users.joined_at,
	user_tiers.started_at AS tier_started_at,
	user_tiers.renewed_at AS tier_renewed_at,
	tiers.id AS tier_id,
	tiers.name AS tier_name,
	tiers.price AS tier_price,
	tiers.description AS tier_description
FROM users
LEFT JOIN user_tiers ON users.id = user_tiers.user_id
LEFT JOIN tiers ON user_tiers.tier_id = tiers.id
WHERE users.id = ?;

Configuration

{
  "version": 2,
  "sql": [
    {
      "engine": "sqlite",
      "schema": "sqlite/schema.sql",
      "queries": "sqlite/queries.sql",
      "gen": {
        "go": {
          "package": "sqlite",
          "out": "sqlite",
          "output_files_suffix": ".gen",
          "output_db_file_name": "db.gen.go",
          "output_models_file_name": "models.gen.go"
        }
      }
    }
  ]
}

Playground URL

https://play.sqlc.dev/p/96a33a86cc6f0f8bf7ba2260d9341aa8ea88d6ad36747d5da92ea56e411d6efe

What operating system are you using?

Linux

What database engines are you using?

SQLite

What type of code are you generating?

Go

@diamondburned diamondburned added bug Something isn't working triage New issues that hasn't been reviewed labels May 7, 2023
@diamondburned
Copy link
Author

diamondburned commented May 7, 2023

If I alias the users table, then everything seems to work:

-- name: User :one
SELECT
	u.id, u.username, u.email, u.real_name, u.pronouns, u.avatar_url, u.joined_at,
	user_tiers.started_at AS tier_started_at,
	user_tiers.renewed_at AS tier_renewed_at,
	tiers.id AS tier_id,
	tiers.name AS tier_name,
	tiers.price AS tier_price,
	tiers.description AS tier_description
FROM users AS u
LEFT JOIN user_tiers ON users.id = user_tiers.user_id
LEFT JOIN tiers ON user_tiers.tier_id = tiers.id
WHERE users.id = ?;

Doing FROM users users also works with the original query.

@skurhse
Copy link

skurhse commented May 7, 2023

here's a distilled example:

-- name: User :one
SELECT users.id
FROM users
LEFT JOIN tiers ON tiers.id == users.id
WHERE users.id = ?;

It appears that the join statement causes the column search to fail in resolveCatalogRefs. I suspect the join statement causes the sqlite parser to appends a near-duplicate to the tables list, overwriting the correct typeMap entry.

@orisano
Copy link
Contributor

orisano commented Jul 11, 2023

This is a bug in SQLiteParser.g4

tree

The cause of this issue is that LEFT in LEFT JOIN is consumed as table_alias.

@diamondburned diamondburned changed the title sqlite: column "id" does not exist for inner-joined query sqlite: column "id" does not exist for left-joined query Jul 11, 2023
orisano added a commit to orisano/sqlc that referenced this issue Jul 15, 2023
changed rules to conform to fallback directive behavior

fix sqlc-dev#2271
orisano added a commit to orisano/sqlc that referenced this issue Jul 15, 2023
changed rules to conform to fallback directive behavior

fix sqlc-dev#2271
kyleconroy added a commit to orisano/sqlc that referenced this issue Jul 24, 2023
kyleconroy added a commit that referenced this issue Jul 24, 2023
* fix(engine/sqlite): fix table_alias rules

changed rules to conform to fallback directive behavior

fix #2271

* test: update endtoend

* Update parser code

---------

Co-authored-by: Kyle Conroy <kyle@sqlc.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants