sqlglot icon indicating copy to clipboard operation
sqlglot copied to clipboard

[draft] - Noklam/fix alter table alter column drop not null

Open noklam opened this issue 1 year ago • 0 comments

fix: #3534 Context:

class AlterColumn(Expression):
    arg_types = {
        "this": True,
        "dtype": False,
        "collate": False,
        "using": False,
        "default": False,
        "drop": False,
        "comment": False,

    }

The existing AlterColumn expression seems to assume only SET DEFAULT and NOT DEFAULT is possible. Therefore is drop is True is sufficient to represent DROP DEFAULT and when default is not null it means set default. This seems to be insufficient to handle statement like DROP NOT NULL and SET NOT NULL

Few questions:

  • there are many _match_xxx functions, is _match_text_seq the most suitable one?
  • I don't know if I should use things like _parse_not_constraints here.
  • I figured I should edit the AlterColumn expression, but I am not sure how to add a new type for SET NOT NULL and DROP NOT NULL. I found there are NotNullColumnConstrains. I take a look at other expression and I thought adding a new optional arg_type expression seems to best fit.

Test

Reuse the original issue example.

from sqlglot import parse_one

query = """
    ALTER TABLE DB_NAME.SCHMA_NAME.TBL_NAME
    ALTER COLUMN MY_COLUMN DROP NOT NULL ;
"""

parsed = parse_one(query, read='snowflake')

This gives me:

AlterTable(
  this=Table(
    this=Identifier(this=TBL_NAME, quoted=False),
    db=Identifier(this=SCHMA_NAME, quoted=False),
    catalog=Identifier(this=DB_NAME, quoted=False)),
  actions=[
    AlterColumn(
      this=Identifier(this=MY_COLUMN, quoted=False),
      drop=True,
      expression=<class 'sqlglot.expressions.NotNullColumnConstraint'>)])

But on the transpile step I get error that I cannot understand and would appreciate some help:

a =parsed.sql(dialect="duckdb")
Details
Traceback (most recent call last):
  File "/Users/Nok_Lam_Chan/Documents/GitHub/sqlglot/nok.py", line 26, in <module>
    a =parsed.sql(dialect="duckdb")
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/Nok_Lam_Chan/Documents/GitHub/sqlglot/sqlglot/expressions.py", line 597, in sql
    return Dialect.get_or_raise(dialect).generate(self, **opts)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/Nok_Lam_Chan/Documents/GitHub/sqlglot/sqlglot/dialects/dialect.py", line 520, in generate
    return self.generator(**opts).generate(expression, copy=copy)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/Nok_Lam_Chan/Documents/GitHub/sqlglot/sqlglot/generator.py", line 615, in generate
    expression = expression.copy()
                 ^^^^^^^^^^^^^^^^^
  File "/Users/Nok_Lam_Chan/Documents/GitHub/sqlglot/sqlglot/expressions.py", line 302, in copy
    return deepcopy(self)
           ^^^^^^^^^^^^^^
  File "/Users/Nok_Lam_Chan/miniconda3/lib/python3.11/copy.py", line 153, in deepcopy
    y = copier(memo)
        ^^^^^^^^^^^^
  File "/Users/Nok_Lam_Chan/Documents/GitHub/sqlglot/sqlglot/expressions.py", line 282, in __deepcopy__
    stack.append((vs, vs.__class__()))
                      ^^^^^^^^^^^^^^
TypeError: _Expression.__new__() missing 3 required positional arguments: 'clsname', 'bases', and 'attrs'

noklam avatar May 25 '24 23:05 noklam