1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Proc macros operate on named structs where field.ident is always Some
//! # mssql-derive
//!
//! Procedural macros for SQL Server row mapping and parameter handling.
//!
//! This crate provides derive macros for automatically implementing
//! row-to-struct mapping and struct-to-parameter conversion.
//!
//! ## Available Macros
//!
//! - `#[derive(FromRow)]` - Convert database rows to structs
//! - `#[derive(ToParams)]` - Convert structs to query parameters
//! - `#[derive(Tvp)]` - Table-valued parameter support
//!
//! ## Example
//!
//! ```rust,ignore
//! use mssql_derive::{FromRow, ToParams};
//!
//! // Automatic row mapping
//! #[derive(FromRow)]
//! struct User {
//! id: i32,
//! #[mssql(rename = "user_name")]
//! name: String,
//! email: Option<String>,
//! }
//!
//! // Automatic parameter conversion
//! #[derive(ToParams)]
//! struct NewUser {
//! name: String,
//! email: String,
//! }
//! ```
use TokenStream;
use parse_macro_input;
/// Derive macro for implementing `FromRow` trait.
///
/// This macro generates code to convert a database row into a struct.
///
/// ## Attributes
///
/// ### Field Attributes
///
/// - `#[mssql(rename = "column_name")]` - Map field to a different column name
/// - `#[mssql(skip)]` - Skip this field (must have a Default implementation)
/// - `#[mssql(default)]` - Use Default if column is NULL or missing
/// - `#[mssql(flatten)]` - Flatten a nested struct implementing FromRow
///
/// ### Struct Attributes
///
/// - `#[mssql(rename_all = "snake_case")]` - Apply naming convention to all fields
///
/// ## Example
///
/// ```rust,ignore
/// #[derive(FromRow)]
/// #[mssql(rename_all = "PascalCase")]
/// struct User {
/// id: i32,
/// #[mssql(rename = "UserName")]
/// name: String,
/// #[mssql(default)]
/// email: Option<String>,
/// #[mssql(skip)]
/// computed: String,
/// }
/// ```
/// Derive macro for implementing `ToParams` trait.
///
/// This macro generates code to convert a struct into query parameters.
///
/// ## Attributes
///
/// - `#[mssql(rename = "param_name")]` - Use a different parameter name
/// - `#[mssql(skip)]` - Don't include this field as a parameter
///
/// ## Example
///
/// ```rust,ignore
/// #[derive(ToParams)]
/// struct NewUser {
/// name: String,
/// #[mssql(rename = "email_address")]
/// email: String,
/// #[mssql(skip)]
/// internal_id: u64,
/// }
///
/// let user = NewUser {
/// name: "Alice".into(),
/// email: "alice@example.com".into(),
/// internal_id: 0,
/// };
///
/// client.execute(
/// "INSERT INTO users (name, email_address) VALUES (@name, @email_address)",
/// &user.to_params()?,
/// ).await?;
/// ```
/// Derive macro for implementing `Tvp` trait (Table-Valued Parameters).
///
/// This macro generates code to use a struct as a table-valued parameter row.
///
/// ## Attributes
///
/// ### Struct Attributes (Required)
///
/// - `#[mssql(type_name = "schema.TypeName")]` - SQL Server TVP type name
///
/// ### Field Attributes
///
/// - `#[mssql(rename = "column_name")]` - Map field to a different column name
/// - `#[mssql(skip)]` - Don't include this field in the TVP
///
/// ## Example
///
/// First, create the table type in SQL Server:
///
/// ```sql
/// CREATE TYPE dbo.UserIdList AS TABLE (
/// UserId INT NOT NULL
/// );
/// ```
///
/// Then derive the trait:
///
/// ```rust,ignore
/// #[derive(Tvp)]
/// #[mssql(type_name = "dbo.UserIdList")]
/// struct UserId {
/// #[mssql(rename = "UserId")]
/// user_id: i32,
/// }
///
/// let ids = vec![UserId { user_id: 1 }, UserId { user_id: 2 }];
/// let tvp = TvpValue::new(&ids)?;
/// ```