Skip to content

Commit 62e87f0

Browse files
authored
Add AI Agent Guidelines for msphpsql (#1585)
1 parent 6b2c33e commit 62e87f0

1 file changed

Lines changed: 315 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
# AI Agent Guidelines for Microsoft Drivers for PHP for SQL Server
2+
3+
This document provides guidance for AI coding agents working with the msphpsql GitHub repository — the open-source home of the **sqlsrv** and **pdo_sqlsrv** PHP extensions for Microsoft SQL Server.
4+
5+
## Quick Start
6+
7+
### Essential Context Files
8+
9+
| File | Purpose |
10+
|------|---------|
11+
| [README.md](README.md) | Project overview, prerequisites, build basics |
12+
| [CHANGELOG.md](CHANGELOG.md) | Full release history; current version at top |
13+
| [Linux-mac-install.md](Linux-mac-install.md) | Step-by-step install guide for every supported Unix platform |
14+
| [buildscripts/README.md](buildscripts/README.md) | Detailed Windows build instructions (manual & scripted) |
15+
| [source/shared/version.h](source/shared/version.h) | Single source of truth for version numbers and preview state |
16+
17+
### Repository at a Glance
18+
19+
| Area | Path | Description |
20+
|------|------|-------------|
21+
| Shared core | `source/shared/` | C++ code shared by both extensions |
22+
| SQLSRV extension | `source/sqlsrv/` | Procedural PHP API extension |
23+
| PDO_SQLSRV extension | `source/pdo_sqlsrv/` | PDO interface extension |
24+
| Packaging script | `source/packagize.sh` | Copies `shared/` into each extension dir for PECL packaging |
25+
| Functional tests | `test/functional/` | `.phpt` test suites for both extensions |
26+
| Extended tests | `test/extended/` | Always Encrypted v2 special tests |
27+
| BVT tests | `test/bvt/` | Basic verification tests |
28+
| Performance tests | `test/Performance/` | Benchmark suite (phpbench) |
29+
| Windows build scripts | `buildscripts/` | `builddrivers.py`, `buildtools.py` |
30+
| Samples | `sample/` | `sqlsrv_sample.php`, `pdo_sqlsrv_sample.php` |
31+
| CI (Linux/Mac) | [azure-pipelines.yml](azure-pipelines.yml) | Azure Pipelines — builds PHP from source, runs tests |
32+
| CI (Windows) | [appveyor.yml](appveyor.yml) | AppVeyor — PHP SDK build matrix |
33+
| Docker | [Dockerfile-msphpsql](Dockerfile-msphpsql) | Ubuntu 24.04 dev environment image |
34+
35+
## Architecture
36+
37+
### Two Extensions, One Shared Core
38+
39+
The drivers ship as two separate PHP extensions that share a common C++ core layer:
40+
41+
```
42+
source/
43+
├── shared/ # Core logic (ODBC, connection, statement, stream, error handling)
44+
│ ├── core_conn.cpp # Connection management
45+
│ ├── core_init.cpp # Driver initialization
46+
│ ├── core_results.cpp # Result set processing
47+
│ ├── core_stmt.cpp # Statement execution
48+
│ ├── core_stream.cpp # Stream handling
49+
│ ├── core_util.cpp # Utility functions
50+
│ ├── core_sqlsrv.h # Main shared header (includes Zend API, ODBC, platform abstractions)
51+
│ ├── version.h # Version constants
52+
│ ├── FormattedPrint.cpp/h # Cross-platform printf implementation
53+
│ ├── StringFunctions.cpp/h # Cross-platform string operations
54+
│ ├── localizationimpl.cpp # Localization/encoding support
55+
│ ├── msodbcsql.h # ODBC driver header
56+
│ └── xplat_*.h, typedefs_for_linux.h, interlockedatomic*.h # Platform abstractions
57+
58+
├── sqlsrv/ # Procedural API extension
59+
│ ├── conn.cpp # sqlsrv_connect(), sqlsrv_close(), etc.
60+
│ ├── init.cpp # Extension module init/shutdown
61+
│ ├── stmt.cpp # sqlsrv_query(), sqlsrv_fetch(), etc.
62+
│ ├── util.cpp # Error handling, logging
63+
│ ├── config.m4 # Linux/Mac autoconf build
64+
│ └── config.w32 # Windows JScript build
65+
66+
├── pdo_sqlsrv/ # PDO extension
67+
│ ├── pdo_dbh.cpp # PDO database handle (new PDO(...))
68+
│ ├── pdo_init.cpp # Extension module init/shutdown
69+
│ ├── pdo_parser.cpp # SQL parser for named params
70+
│ ├── pdo_stmt.cpp # PDOStatement operations
71+
│ ├── pdo_util.cpp # Error handling
72+
│ ├── config.m4 # Linux/Mac autoconf build
73+
│ └── config.w32 # Windows JScript build
74+
75+
└── packagize.sh # Copies shared/ into sqlsrv/ and pdo_sqlsrv/ for PECL
76+
```
77+
78+
### Key Design Patterns
79+
80+
- **Zend API integration**: All C++ code uses the PHP Zend Engine API. The shared header `core_sqlsrv.h` includes `<php.h>` and `<zend.h>` with MSVC warning suppression for known benign warnings (4100, 4127, 4146, 4244, 4267, 4456, 4457, 4706).
81+
- **Platform abstraction**: Unix builds use `typedefs_for_linux.h`, `xplat_*.h`, and `interlockedatomic*.h` to map Win32 types/functions to POSIX equivalents (e.g., `stricmp``strcasecmp`, `GetLastError``errno`).
82+
- **ODBC layer**: All SQL Server communication goes through the Microsoft ODBC Driver for SQL Server (version 17 or 18). The code never talks to TDS directly.
83+
- **MARS**: Multiple Active Result Sets enabled by default via `MARS_Connection={Yes}`.
84+
85+
## Build System
86+
87+
### Linux / macOS (autoconf)
88+
89+
Each extension has a `config.m4` that registers the extension with PHP's build system:
90+
91+
```bash
92+
# Build from PHP source tree (extensions in ext/ directory)
93+
phpize
94+
./configure --with-sqlsrv # or --with-pdo_sqlsrv
95+
make
96+
make install
97+
```
98+
99+
The `config.m4` includes logic to avoid double-compiling shared sources when both extensions are built as static (non-shared) in the same PHP build.
100+
101+
### Windows (PHP SDK + JScript)
102+
103+
Each extension has a `config.w32` (JScript) for the PHP Windows SDK build:
104+
105+
- **Visual Studio**: VS2019 for PHP 8.3, VS2022 for PHP 8.4+
106+
- **Security flags**: `/NXCOMPAT`, `/DYNAMICBASE`, `/guard:cf`, `/ZH:SHA_256`, `/W4`, `/WX`, `/CETCOMPAT`, `/Qspectre` (for VCVERS >= 1913)
107+
- **Scripted builds**: `buildscripts/builddrivers.py` automates downloading PHP SDK, source, and building both extensions
108+
109+
### PECL Packaging
110+
111+
`source/packagize.sh` copies `shared/` files into both `sqlsrv/` and `pdo_sqlsrv/` directories, making each extension self-contained for PECL distribution. **Note**: PECL version strings must not contain hyphens (e.g., `5.13.0beta1` not `5.13.0-beta1`).
112+
113+
### Docker
114+
115+
The `Dockerfile-msphpsql` provides a complete Ubuntu 24.04 development environment with PHP, ODBC 18, and all build dependencies pre-installed.
116+
117+
## Version Management
118+
119+
All version information lives in `source/shared/version.h`:
120+
121+
| Constant | Purpose | Current |
122+
|----------|---------|---------|
123+
| `SQLVERSION_MAJOR` | Incompatible API changes | 5 |
124+
| `SQLVERSION_MINOR` | Backward-compatible features | 13 |
125+
| `SQLVERSION_PATCH` | Backward-compatible bug fixes | 0 |
126+
| `SQLVERSION_BUILD` | Build metadata (appended as `+N`) | 0 |
127+
| `PREVIEW` | Set to 1+ for beta releases, 0 for stable | 0 |
128+
| `PHP_SQLSRV_VERSION` | PECL version string for sqlsrv | "5.13.0" |
129+
| `PHP_PDO_SQLSRV_VERSION` | PECL version string for pdo_sqlsrv | "5.13.0" |
130+
131+
**Versioning rules**:
132+
- Follows [semantic versioning](https://semver.org/)
133+
- When `PREVIEW > 0`, the version string becomes `MAJOR.MINOR.PATCH-betaN` (e.g., `5.13.0-beta1`)
134+
- PECL versions use `MAJOR.MINOR.PATCHbetaN` (no hyphen)
135+
- The `PHP_SQLSRV_VERSION` and `PHP_PDO_SQLSRV_VERSION` constants must be updated manually (cannot use preprocessor macros due to PECL/Pickle constraints)
136+
137+
## Testing
138+
139+
### Test Format
140+
141+
Tests use PHP's standard `.phpt` format:
142+
143+
```
144+
--TEST--
145+
Description of the test
146+
--SKIPIF--
147+
<?php require('skipif_*.inc'); ?>
148+
--FILE--
149+
<?php
150+
// Test code here
151+
?>
152+
--EXPECT--
153+
Expected output
154+
```
155+
156+
### Test Organization
157+
158+
| Directory | Contents | Count |
159+
|-----------|----------|-------|
160+
| `test/functional/sqlsrv/` | SQLSRV extension tests | ~260+ tests |
161+
| `test/functional/pdo_sqlsrv/` | PDO_SQLSRV extension tests | ~280+ tests |
162+
| `test/functional/setup/` | SQL scripts, BCP data files, Python setup scripts |
163+
| `test/functional/inc/` | Shared binary data (GIF files), TVP test data |
164+
| `test/extended/` | Always Encrypted v2 tests | ~12 tests |
165+
| `test/bvt/` | Basic verification tests |
166+
| `test/Performance/` | phpbench-based benchmarks |
167+
168+
### Test Configuration
169+
170+
Tests read connection info from `MsSetup.inc` (present in each test directory). Connection settings can be overridden via environment variables:
171+
172+
| Variable | Purpose | Default |
173+
|----------|---------|---------|
174+
| `MSSQL_SERVER` | SQL Server hostname | `TARGET_SERVER` placeholder |
175+
| `MSSQL_DATABASE_NAME` | Database name | `TARGET_DATABASE` placeholder |
176+
| `MSSQL_UID` | SQL login username | `TARGET_USERNAME` placeholder |
177+
| `MSSQL_PWD` | SQL login password | `TARGET_PASSWORD` placeholder |
178+
| `MSSQL_DRIVER` | ODBC driver version string | `ODBC Driver 18 for SQL Server` |
179+
180+
### Running Tests
181+
182+
```bash
183+
# Run all sqlsrv tests
184+
php run-tests.php test/functional/sqlsrv/
185+
186+
# Run all pdo_sqlsrv tests
187+
php run-tests.php test/functional/pdo_sqlsrv/
188+
189+
# Run a single test
190+
php run-tests.php test/functional/sqlsrv/sqlsrv_connect.phpt
191+
```
192+
193+
### Test Helper Includes
194+
195+
| File | Purpose |
196+
|------|---------|
197+
| `MsSetup.inc` | Connection configuration (server, database, credentials, ODBC driver) |
198+
| `MsCommon.inc` | ~600 lines of shared helpers: `connect()`, `isWindows()`, `testMode()`, `traceMode()`, table creation, data generators |
199+
| `MsHelper.inc` | Additional helper functions |
200+
| `MsData.inc` | Test data constants |
201+
| `skipif*.inc` | Skip conditions (OS, extensions, features, server version) |
202+
| `tools.inc` | Diagnostic and utility functions |
203+
204+
### Test Categories
205+
206+
Tests cover a wide range of features:
207+
- **Connectivity**: Connect, close, connection options, connection resiliency, connection pooling
208+
- **Data types**: All SQL Server types, Unicode, large objects, date/time, decimal precision
209+
- **Fetch modes**: Forward-only, scrollable, buffered queries, client-side cursors
210+
- **Transactions**: Commit, rollback, savepoints
211+
- **Stored procedures**: Input/output params, return values, result sets
212+
- **Always Encrypted**: Column encryption, key vault, enclave operations
213+
- **Azure AD / Entra**: Authentication modes (`ActiveDirectoryPassword`, `ActiveDirectoryMSI`, etc.)
214+
- **Table-Valued Parameters (TVP)**: Sending structured data
215+
- **Bulk Copy (BCP)**: `test/functional/setup/*.dat` and `*.fmt` files
216+
217+
## Core Principles
218+
219+
1. **Shared Core, Separate Extensions**: Common logic goes in `source/shared/`. Extension-specific API binding goes in `source/sqlsrv/` or `source/pdo_sqlsrv/`. Never duplicate logic between extensions.
220+
2. **ODBC Abstraction**: All database communication uses ODBC. Never implement protocol-level (TDS) communication.
221+
3. **Cross-Platform**: Code must compile and run on Windows, Linux, and macOS. Use the platform abstraction headers (`xplat_*.h`, `typedefs_for_linux.h`) for OS-specific functionality.
222+
4. **PHP Zend Compatibility**: Follow Zend Engine API conventions. Use `zend_*` functions for memory management. Be aware of thread-safety requirements (ZTS vs NTS builds).
223+
5. **Security by Default**: Windows builds enforce `/NXCOMPAT`, `/DYNAMICBASE`, `/guard:cf`, `/Qspectre`, `/CETCOMPAT`. Never log credentials or connection strings in error output.
224+
6. **Backward Compatibility**: Avoid breaking existing PHP userland code. New connection options should default to preserving existing behavior.
225+
7. **Test Coverage**: All changes must include `.phpt` tests. Both `sqlsrv` and `pdo_sqlsrv` should be tested when shared code changes. Tests have standard dependencies connectivity to a server and database. If a test includes dependencies beyond the standard that aren't present, they should include relevant skip logic.
226+
227+
## Common Tasks
228+
229+
### Bug Fix Workflow
230+
231+
1. Reproduce the issue — write or identify a `.phpt` test that demonstrates the bug
232+
2. Determine if the fix belongs in `source/shared/` (affects both extensions) or in an extension-specific file
233+
3. Implement the fix
234+
4. Add or update `.phpt` tests in both `test/functional/sqlsrv/` and `test/functional/pdo_sqlsrv/` if shared code changed
235+
5. Update `CHANGELOG.md` with a description under the appropriate version heading
236+
237+
### Adding a New Connection Option
238+
239+
1. Add the ODBC keyword mapping in `source/shared/core_sqlsrv.h` (connection option definitions)
240+
2. Register the option in `source/shared/core_conn.cpp` connection option arrays
241+
3. Expose in `source/sqlsrv/conn.cpp` and/or `source/pdo_sqlsrv/pdo_dbh.cpp`
242+
4. Default to backward-compatible value
243+
5. Add tests for the new option in both test suites
244+
6. Document in `CHANGELOG.md`
245+
246+
### Version Bump
247+
248+
1. Edit `source/shared/version.h`:
249+
- Update `SQLVERSION_MAJOR`, `SQLVERSION_MINOR`, and/or `SQLVERSION_PATCH`
250+
- Update `PHP_SQLSRV_VERSION` and `PHP_PDO_SQLSRV_VERSION` string literals
251+
- Set `PREVIEW` to 0 for stable, or 1+ for beta releases
252+
2. Update `CHANGELOG.md` with new version heading and release notes
253+
3. The file header comment `Microsoft Drivers X.YY for PHP for SQL Server` in source files may need updating for major/minor bumps
254+
255+
### Adding a New Test
256+
257+
1. Create a `.phpt` file in the appropriate `test/functional/` subdirectory
258+
2. Include standard skip logic: `--SKIPIF--` with `<?php require('skipif_*.inc'); ?>`
259+
3. Use `MsCommon.inc` helpers for connection setup and data generation
260+
4. Ensure the test is deterministic and cleans up after itself (drop temp tables, close connections)
261+
5. Provide explicit `--EXPECT--` or `--EXPECTF--` output
262+
263+
### Preparing a PECL Release
264+
265+
1. Set version in `source/shared/version.h` (ensure `PREVIEW` is set correctly)
266+
2. Run `source/packagize.sh` to copy `shared/` into both extension directories
267+
3. Verify `PHP_SQLSRV_VERSION` / `PHP_PDO_SQLSRV_VERSION` strings have no hyphens
268+
4. Each extension directory becomes a self-contained PECL package
269+
270+
## CI / CD
271+
272+
### GitHub CI
273+
274+
| Pipeline | Platform | Trigger |
275+
|----------|----------|---------|
276+
| Azure Pipelines (`azure-pipelines.yml`) | Linux, macOS | Push to `dev`, `fix/*`; PRs to `dev` |
277+
| AppVeyor (`appveyor.yml`) | Windows | Push (except legacy branches) |
278+
| Codecov (`codecov.yml`) | Windows | Coverage reporting |
279+
280+
The Azure Pipelines job builds PHP from source on each target platform, compiles both extensions, then runs the full `.phpt` test suite against a SQL Server (Docker container on Linux, local instance on Windows/macOS).
281+
282+
### Internal CI/CD (msphpsql in ADO)
283+
284+
The internal Azure DevOps repo (`msphpsql`) contains the production CI/CD pipelines for official builds, matrix testing, signing, packaging, and release. See that repo's `AGENTS.md` for pipeline architecture details.
285+
286+
## Branching and Contributions
287+
288+
- **`dev`** — active development branch; all PRs should target `dev`
289+
- **`main`** (or `master`) — stable release branch
290+
- **`fix/*`** — bug fix branches (trigger CI)
291+
- Pull requests require CI to pass before merge
292+
293+
## External Resources
294+
295+
| Resource | Link |
296+
|----------|------|
297+
| Microsoft Docs (PHP Drivers) | https://learn.microsoft.com/sql/connect/php/microsoft-php-driver-for-sql-server |
298+
| ODBC Driver Docs | https://learn.microsoft.com/sql/connect/odbc/microsoft-odbc-driver-for-sql-server |
299+
| PHP Internals (Building) | https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2 |
300+
| PECL sqlsrv | https://pecl.php.net/package/sqlsrv |
301+
| PECL pdo_sqlsrv | https://pecl.php.net/package/pdo_sqlsrv |
302+
| GitHub Issues | https://github.com/microsoft/msphpsql/issues |
303+
| GitHub Releases | https://github.com/microsoft/msphpsql/releases |
304+
305+
## Getting Help
306+
307+
- Check `test/functional/` for usage patterns and expected behavior
308+
- Read `MsCommon.inc` for available test helper functions
309+
- Consult `core_sqlsrv.h` for internal data structures and ODBC wrappers
310+
- For ODBC behavior, reference the Microsoft ODBC Driver documentation
311+
- For PHP extension API, reference the [PHP Internals Book](https://www.phpinternalsbook.com/)
312+
313+
---
314+
315+
*This document is automatically loaded as context for AI agents working in this repository.*

0 commit comments

Comments
 (0)