async-pybatis-orm LLM Quick Guide
=================================

1) Project Purpose
------------------
- Python async ORM for MySQL.
- API style is designed to be close to Java MyBatis-Plus:
  - CRUD model methods
  - Query/Update wrapper style condition building
  - Pagination support
- Best fit: async web apps (FastAPI etc.) with simple, explicit SQL generation.


2) Core Concepts
----------------
- Base model classes:
  - CommonModel: recommended in app runtime; uses DatabaseManager adapter.
  - CRUDModel: full CRUD capability via mixins.
- Field declaration:
  - PrimaryKey(...)
  - Field(...)
- Condition wrappers:
  - QueryWrapper for select/delete conditions
  - UpdateWrapper for update set + where conditions
- Pagination:
  - Page(current, size)
  - PageResult(records, total, current, size)


3) Minimal Runtime Flow
-----------------------
Step A: initialize DB connection once at app startup.

Example:
from async_pybatis_orm.base.connection import DatabaseManager
await DatabaseManager.initialize(
    database_url="mysql+aiomysql://user:pass@127.0.0.1:3306/dbname"
)

Step B: define model classes inheriting CommonModel (or CRUDModel).

Example:
from typing import Optional
from datetime import datetime
from async_pybatis_orm.base.common_model import CommonModel
from async_pybatis_orm.fields import Field, PrimaryKey

class User(CommonModel):
    __table_meta__ = {"table_name": "user", "primary_key": "id"}
    id: Optional[int] = PrimaryKey(column_name="id", auto_increment=True)
    username: str = Field(column_name="username", nullable=False, max_length=64)
    updated_at: datetime = Field(default_factory=datetime.now, auto_update=True)

Step C: use class methods for CRUD.

Example:
u = User(username="alice")
ok = await User.save(u)
u2 = await User.select_by_id(u.id)

Step D: close DB connection on app shutdown.

Example:
await DatabaseManager.close()


4) Frequently Used APIs
-----------------------
Select:
- select_by_id(id) / get_by_id(id)
- select_one(wrapper)
- select_list(wrapper) / list_by_condition(wrapper)
- select_count(wrapper) / count_by_condition(wrapper)
- select_page(page, wrapper) / page_query(page, wrapper)

Insert:
- save(entity)
- insert(entity)
- insert_returning_id(entity)
- insert_batch(entities)
- batch_save(entities)

Update:
- update_by_id(entity)
- update_by_wrapper(update_wrapper)

Delete:
- remove_by_id(id)
- remove_by_ids(ids)
- remove_by_wrapper(wrapper)
- truncate()
- remove_all()


5) Wrapper Usage
----------------
Field style supports BOTH:
- string field names: "username"
- model field objects: User.username

Common methods:
- eq / ne / gt / ge / lt / le
- like / not_like / like_left / like_right
- in_list / not_in / between / not_between
- is_null / is_not_null
- order_by / group_by / select / last

Notes:
- group_by is chainable.
- remove_by_wrapper requires non-empty effective conditions; empty wrapper raises error.


6) Defaults and auto_update
---------------------------
- Prefer dynamic defaults with default_factory:
  - Field(default_factory=datetime.now)
- If default is callable, framework now evaluates it.
- auto_update=True tries default_factory first, then callable default.
- Avoid relying on static mutable defaults.


7) Model Code Generator (New)
-----------------------------
SDK exports:
- DBConfig
- GenerateOptions
- GenerateResult
- generate_models(...)
- generate_models_async(...)

Typical SDK usage:
from async_pybatis_orm import DBConfig, GenerateOptions, generate_models

db = DBConfig(
    host="127.0.0.1",
    port=3306,
    user="root",
    password="123456",
    database="sakila",
)
opts = GenerateOptions(
    output_dir="generated_models",
    tables=["actor", "film"],
    overwrite=False,
    file_layout="per_table",   # or "single_file"
    base_class="CommonModel",  # or "CRUDModel"
)
result = generate_models(db, opts)

CLI:
python scripts/generate_models.py \
  --host 127.0.0.1 \
  --port 3306 \
  --user root \
  --password 123456 \
  --database sakila \
  --output-dir generated_models \
  --tables actor,film

Generator capabilities:
- table filtering: tables/include_tables/exclude_tables
- overwrite control
- per-table or single-file layout
- naming strategy + custom naming callbacks
- optional __init__.py export generation


8) Important Constraints / Caveats
----------------------------------
- MySQL-focused (metadata introspection uses information_schema).
- Requires async runtime for ORM operations.
- SQL snippets via wrapper.last(...) are raw SQL; caller must ensure safety.
- delete/update wrappers intentionally reject unsafe empty conditions in key paths.


9) Recommended Prompting for Other LLMs
---------------------------------------
When asking another model to modify this project, include:
- target file paths
- expected API behavior (sync/async, return type)
- whether compatibility with current public exports is required
- concrete example model/wrapper usage
- migration expectation (breaking vs non-breaking)

This reduces ambiguous refactors and keeps generated code aligned with this project.

