# SM019: Column name is a SQL reserved keyword

**Severity:** INFO
**Database:** All (PostgreSQL, MySQL, SQLite)
**Category:** naming, informational

## Description

Using SQL reserved keywords as column names can cause issues with raw SQL queries, database tools, and third-party libraries that don't properly quote identifiers.

While Django's ORM automatically quotes identifiers, this rule warns about potential problems when working outside the ORM.

## Examples

### ❌ Problematic Names

```python
migrations.AddField(
    model_name='article',
    name='order',  # Reserved keyword
    field=models.IntegerField(),
)

migrations.AddField(
    model_name='profile',
    name='user',  # Reserved in PostgreSQL
    field=models.ForeignKey('auth.User', on_delete=models.CASCADE),
)

migrations.CreateModel(
    name='Item',
    fields=[
        ('id', models.AutoField(primary_key=True)),
        ('type', models.CharField(max_length=50)),  # Reserved
        ('status', models.CharField(max_length=20)),  # Reserved
    ],
)
```

### ✅ Recommended Names

```python
migrations.AddField(
    model_name='article',
    name='sort_order',  # More descriptive
    field=models.IntegerField(),
)

migrations.AddField(
    model_name='profile',
    name='owner',  # Avoids reserved word
    field=models.ForeignKey('auth.User', on_delete=models.CASCADE),
)

migrations.CreateModel(
    name='Item',
    fields=[
        ('id', models.AutoField(primary_key=True)),
        ('item_type', models.CharField(max_length=50)),
        ('current_status', models.CharField(max_length=20)),
    ],
)
```

## Common Reserved Keywords

The following are commonly problematic column names:

| Keyword  | Better Alternatives                        |
| -------- | ------------------------------------------ |
| `user`   | `owner`, `created_by`, `author`, `user_id` |
| `order`  | `sort_order`, `sequence`, `display_order`  |
| `group`  | `group_name`, `category`, `team`           |
| `type`   | `item_type`, `category`, `kind`            |
| `status` | `current_status`, `order_status`, `state`  |
| `name`   | `title`, `label`, `display_name`           |
| `key`    | `lookup_key`, `api_key`, `identifier`      |
| `value`  | `amount`, `content`, `data`                |
| `date`   | `created_date`, `event_date`, `due_date`   |
| `time`   | `start_time`, `duration`, `timestamp`      |

## Why This Matters

1. **Raw SQL queries fail** — Unquoted identifiers cause syntax errors:

   ```sql
   -- Fails!
   SELECT user, order FROM profile;

   -- Works but cumbersome
   SELECT "user", "order" FROM profile;
   ```

2. **Database tools have issues** — GUI tools, export utilities, and reporting tools may not handle reserved words correctly

3. **Third-party libraries** — ORMs, query builders, and analytics tools may not quote identifiers properly

4. **Debugging is harder** — Stack traces and error messages become confusing

## How to Fix

### Option 1: Use a more descriptive name (Recommended)

```python
# Instead of 'order'
name='sort_order'
name='display_order'
name='sequence_number'
```

### Option 2: Use `db_column` to keep model clean

If you want a clean model field name but a different database column:

```python
class Article(models.Model):
    order_number = models.IntegerField(db_column='article_order')
```

### Option 3: Accept and document

If you must use a reserved word, Django will quote it correctly in ORM queries. Just be careful with:

- Raw SQL queries
- Database migrations and dumps
- Third-party integrations

## Detected Keywords

This rule checks for SQL reserved keywords from:

- SQL standard (SELECT, INSERT, UPDATE, DELETE, etc.)
- PostgreSQL specific (ANALYSE, FREEZE, VERBOSE, etc.)
- MySQL specific (DATABASE, SCHEMA, etc.)
- Common problematic names (user, order, group, type, etc.)

## Related Rules

- [SM006](SM006.md) — Column rename detection

## References

- [PostgreSQL Reserved Keywords](https://www.postgresql.org/docs/current/sql-keywords-appendix.html)
- [MySQL Reserved Keywords](https://dev.mysql.com/doc/refman/8.0/en/keywords.html)
- [SQLite Keywords](https://www.sqlite.org/lang_keywords.html)
