Selcan Yukcu commited on
Commit ·
b112622
1
Parent(s): e27d11b
fix: memory store issue again, update prompts
Browse files- conversation_memory.py +7 -4
- postgre_mcp_client.py +2 -1
- postgre_mcp_server.py +184 -77
conversation_memory.py
CHANGED
|
@@ -13,11 +13,14 @@ class ConversationMemory:
|
|
| 13 |
for step in parsed_steps:
|
| 14 |
if step['type'] == 'ai_function_call':
|
| 15 |
tools.append(step['tool'])
|
| 16 |
-
if 'query' in step:
|
| 17 |
-
|
|
|
|
|
|
|
| 18 |
elif step['type'] == 'ai_final_answer':
|
| 19 |
-
if
|
| 20 |
-
|
|
|
|
| 21 |
elif step['type'] == 'tool_response':
|
| 22 |
if step['tool'] == 'execute_query':
|
| 23 |
self.query_results.append(step['response'])
|
|
|
|
| 13 |
for step in parsed_steps:
|
| 14 |
if step['type'] == 'ai_function_call':
|
| 15 |
tools.append(step['tool'])
|
| 16 |
+
if 'query' in step['args']:
|
| 17 |
+
args_dict = json.loads(step['args'])
|
| 18 |
+
query = args_dict['query']
|
| 19 |
+
self.all_queries.append(query)
|
| 20 |
elif step['type'] == 'ai_final_answer':
|
| 21 |
+
if step['ai_said']:
|
| 22 |
+
if 'query' in step['ai_said'][0]:
|
| 23 |
+
self.all_queries.append(step['ai_said'][1])
|
| 24 |
elif step['type'] == 'tool_response':
|
| 25 |
if step['tool'] == 'execute_query':
|
| 26 |
self.query_results.append(step['response'])
|
postgre_mcp_client.py
CHANGED
|
@@ -24,7 +24,8 @@ The users table stores information about the individuals who use the application
|
|
| 24 |
The posts table represents content created by users, such as blog posts or messages. Like the users table, each entry has a unique, auto-incrementing id as the primary key. The user_id field links each post to its author by referencing the id field in the users table, establishing a one-to-many relationship between users and posts. The title column holds a brief summary or headline of the post, while the content field contains the full text. A created_at timestamp is also included to record when each post was created, with a default value of the current time.
|
| 25 |
"""
|
| 26 |
|
| 27 |
-
#request = "can you show me the result of the join of
|
|
|
|
| 28 |
#request = "May ı see the table?"
|
| 29 |
#request = "stop"
|
| 30 |
#request = "how many columns are there in this joined table?"
|
|
|
|
| 24 |
The posts table represents content created by users, such as blog posts or messages. Like the users table, each entry has a unique, auto-incrementing id as the primary key. The user_id field links each post to its author by referencing the id field in the users table, establishing a one-to-many relationship between users and posts. The title column holds a brief summary or headline of the post, while the content field contains the full text. A created_at timestamp is also included to record when each post was created, with a default value of the current time.
|
| 25 |
"""
|
| 26 |
|
| 27 |
+
#request = "can you show me the result of the join of posts and users tables?"
|
| 28 |
+
#request = "But you did not execute the query. Can you tell me why?"
|
| 29 |
#request = "May ı see the table?"
|
| 30 |
#request = "stop"
|
| 31 |
#request = "how many columns are there in this joined table?"
|
postgre_mcp_server.py
CHANGED
|
@@ -63,7 +63,7 @@ async def base_prompt_query() -> str:
|
|
| 63 |
# Your Role
|
| 64 |
==========================
|
| 65 |
|
| 66 |
-
You are an expert in generating SQL queries and interacting with a PostgreSQL database using **FastMCP tools**. These tools allow you to:
|
| 67 |
|
| 68 |
- List available tables
|
| 69 |
- Retrieve schema details
|
|
@@ -87,7 +87,7 @@ async def base_prompt_query() -> str:
|
|
| 87 |
1. Analyze the request to determine the desired data or action.
|
| 88 |
2. Use tools to gather any necessary information (e.g., list tables, get schema).
|
| 89 |
3. Generate a valid SQL query (such as **SELECT**, **COUNT**, or other read-only operations) and clearly display the full query.
|
| 90 |
-
4. Execute the query and **return the result**.
|
| 91 |
5. **Chain tools logically to build toward the answer.**
|
| 92 |
6. Explain your reasoning at every step for clarity and transparency.
|
| 93 |
7. Show the result of the **execute_query** in your final answer.
|
|
@@ -104,7 +104,7 @@ async def base_prompt_query() -> str:
|
|
| 104 |
- Validate SQL syntax before execution.
|
| 105 |
- Never assume table or column names. Use tools to confirm structure.
|
| 106 |
- Use memory efficiently. Don’t rerun a tool unless necessary.
|
| 107 |
-
- If you generate a SQL query,
|
| 108 |
|
| 109 |
|
| 110 |
---
|
|
@@ -132,80 +132,6 @@ async def base_prompt_query() -> str:
|
|
| 132 |
|
| 133 |
---
|
| 134 |
|
| 135 |
-
==========================
|
| 136 |
-
# Tool Usage Examples
|
| 137 |
-
==========================
|
| 138 |
-
|
| 139 |
-
### Example 1 — Unknown Table Name:
|
| 140 |
-
**User Request:** "Get the total sales for each product."
|
| 141 |
-
**Steps:**
|
| 142 |
-
1. List Tables → Identify a table like `sales_data`.
|
| 143 |
-
2. Get Schema for `sales_data` → Confirm columns like `product_name`, `total_sales`.
|
| 144 |
-
3. Generate and execute query:
|
| 145 |
-
```sql
|
| 146 |
-
SELECT product_name, SUM(total_sales) FROM sales_data GROUP BY product_name;
|
| 147 |
-
|
| 148 |
-
### Example 1 — Repeating the same request:
|
| 149 |
-
**User Request:** "Get the total sales for each product."
|
| 150 |
-
**Steps:**
|
| 151 |
-
1. Use memory to check if we already retrieved schema.
|
| 152 |
-
2. Retrieve the SQL query that gives the total sales for each product.
|
| 153 |
-
3. Only execute the query and show the user.
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
### Example 2 — Schema Uncertainty:
|
| 157 |
-
**User Request:** "Show customer emails from the database."
|
| 158 |
-
|
| 159 |
-
**Steps:**
|
| 160 |
-
1. Use memory to check if we already retrieved schema.
|
| 161 |
-
2. If not, List Tables → Identify a table like `customers`.
|
| 162 |
-
3. Get Schema for `customers` → Confirm column `email`.
|
| 163 |
-
4. Query:
|
| 164 |
-
```sql
|
| 165 |
-
SELECT email FROM customers;
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
### Example 3 — Memory Usage:
|
| 169 |
-
**User Request:** "Get top 5 most expensive products."
|
| 170 |
-
|
| 171 |
-
**Steps:**
|
| 172 |
-
1. Check memory for schema of `products` table.
|
| 173 |
-
2. If column `price` exists in memory, directly generate:
|
| 174 |
-
```sql
|
| 175 |
-
SELECT * FROM products ORDER BY price DESC LIMIT 5;
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
### Example 4 — COUNT Query:
|
| 179 |
-
**User Request:** "How many orders have been placed?"
|
| 180 |
-
|
| 181 |
-
**Steps:**
|
| 182 |
-
1. List Tables → Identify a table like `orders`.
|
| 183 |
-
2. Get Schema for `orders` → Confirm it's the right table.
|
| 184 |
-
3. Query:
|
| 185 |
-
```sql
|
| 186 |
-
SELECT COUNT(*) FROM orders;
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
### Example 5 — WHERE Clause (Filtering):
|
| 190 |
-
**User Request:** "Get the names of customers from Germany."
|
| 191 |
-
|
| 192 |
-
**Steps:**
|
| 193 |
-
1. Use memory or List Tables → Identify `customers` table.
|
| 194 |
-
2. Get Schema for `customers` → Confirm columns like `country`, `name`.
|
| 195 |
-
3. Generate and execute query:
|
| 196 |
-
```sql
|
| 197 |
-
SELECT name FROM customers WHERE country = 'Germany';
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
## Example 6 — Basic Aggregation**
|
| 201 |
-
**User Request:** "Get total sales for each product"
|
| 202 |
-
|
| 203 |
-
**Steps:**
|
| 204 |
-
1. Use memory or List Tables → Get schema for `sales_data`
|
| 205 |
-
2. Generate and execute query:
|
| 206 |
-
```sql
|
| 207 |
-
SELECT product_name, SUM(total_sales) FROM sales_data GROUP BY product_name;
|
| 208 |
-
|
| 209 |
|
| 210 |
### Invalid Example — DELETE Operation (Not Allowed):
|
| 211 |
**User Request:** "Delete all customers from Germany."
|
|
@@ -218,6 +144,12 @@ async def base_prompt_query() -> str:
|
|
| 218 |
> SELECT * FROM customers WHERE country = 'Germany';
|
| 219 |
> ```
|
| 220 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 221 |
=========================
|
| 222 |
# New User Request
|
| 223 |
=========================
|
|
@@ -299,6 +231,181 @@ Use this memory to resolve any references in the user's latest request.
|
|
| 299 |
|
| 300 |
---
|
| 301 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 302 |
==========================
|
| 303 |
# Examples
|
| 304 |
==========================
|
|
|
|
| 63 |
# Your Role
|
| 64 |
==========================
|
| 65 |
|
| 66 |
+
You are an expert in generating and executing SQL queries and interacting with a PostgreSQL database using **FastMCP tools**. These tools allow you to:
|
| 67 |
|
| 68 |
- List available tables
|
| 69 |
- Retrieve schema details
|
|
|
|
| 87 |
1. Analyze the request to determine the desired data or action.
|
| 88 |
2. Use tools to gather any necessary information (e.g., list tables, get schema).
|
| 89 |
3. Generate a valid SQL query (such as **SELECT**, **COUNT**, or other read-only operations) and clearly display the full query.
|
| 90 |
+
4. Execute the query and **return the execution result of the query**.
|
| 91 |
5. **Chain tools logically to build toward the answer.**
|
| 92 |
6. Explain your reasoning at every step for clarity and transparency.
|
| 93 |
7. Show the result of the **execute_query** in your final answer.
|
|
|
|
| 104 |
- Validate SQL syntax before execution.
|
| 105 |
- Never assume table or column names. Use tools to confirm structure.
|
| 106 |
- Use memory efficiently. Don’t rerun a tool unless necessary.
|
| 107 |
+
- If you generate a SQL query, immediately call the **execute_query** tool using that query. Do not delay or wait for user confirmation.
|
| 108 |
|
| 109 |
|
| 110 |
---
|
|
|
|
| 132 |
|
| 133 |
---
|
| 134 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
|
| 136 |
### Invalid Example — DELETE Operation (Not Allowed):
|
| 137 |
**User Request:** "Delete all customers from Germany."
|
|
|
|
| 144 |
> SELECT * FROM customers WHERE country = 'Germany';
|
| 145 |
> ```
|
| 146 |
|
| 147 |
+
|
| 148 |
+
**Reminder:**
|
| 149 |
+
**Every time you generate a SQL query, call **execute_query** right after and include the result in your final response.**
|
| 150 |
+
**If you do not execute the generated SQL query, this will be the violation of the instructions**
|
| 151 |
+
**Your final answer cannot be only a SQL query, you will have to call **execute_query** and give the result of the call with the SQL query.**
|
| 152 |
+
---
|
| 153 |
=========================
|
| 154 |
# New User Request
|
| 155 |
=========================
|
|
|
|
| 231 |
|
| 232 |
---
|
| 233 |
|
| 234 |
+
==========================
|
| 235 |
+
# Reference Conversion Rules for PostgreSQL to ANSI SQL
|
| 236 |
+
==========================
|
| 237 |
+
## Use the following rules as examples and guidance. You are not limited to these rules — apply your own knowledge of SQL standards and PostgreSQL to perform accurate conversions, even in cases not explicitly covered below.
|
| 238 |
+
|
| 239 |
+
### 1. String Concatenation
|
| 240 |
+
- **PostgreSQL:** || for string concatenation
|
| 241 |
+
- **ANSI SQL:** CONCAT() function
|
| 242 |
+
|
| 243 |
+
**Example:**
|
| 244 |
+
```sql
|
| 245 |
+
-- PostgreSQL
|
| 246 |
+
SELECT first_name || ' ' || last_name AS full_name FROM users;
|
| 247 |
+
|
| 248 |
+
-- ANSI SQL
|
| 249 |
+
SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;
|
| 250 |
+
|
| 251 |
+
### 2. LIMIT Clause
|
| 252 |
+
|
| 253 |
+
- **PostgreSQL:** Uses `LIMIT`
|
| 254 |
+
- **ANSI SQL:** Uses `FETCH FIRST n ROWS ONLY`
|
| 255 |
+
|
| 256 |
+
**Example:**
|
| 257 |
+
```sql
|
| 258 |
+
-- PostgreSQL
|
| 259 |
+
SELECT * FROM posts LIMIT 10;
|
| 260 |
+
|
| 261 |
+
-- ANSI SQL
|
| 262 |
+
SELECT * FROM posts FETCH FIRST 10 ROWS ONLY;
|
| 263 |
+
|
| 264 |
+
### 3. ILIKE (Case-insensitive LIKE)
|
| 265 |
+
|
| 266 |
+
- **PostgreSQL:** `ILIKE`
|
| 267 |
+
- **ANSI SQL:** Use `LOWER(column) LIKE` or `UPPER(column) LIKE`
|
| 268 |
+
|
| 269 |
+
**Example:**
|
| 270 |
+
```sql
|
| 271 |
+
-- PostgreSQL
|
| 272 |
+
SELECT * FROM users WHERE username ILIKE 'john%';
|
| 273 |
+
|
| 274 |
+
-- ANSI SQL
|
| 275 |
+
SELECT * FROM users WHERE LOWER(username) LIKE 'john%';
|
| 276 |
+
|
| 277 |
+
### 4. Type Casting
|
| 278 |
+
|
| 279 |
+
- **PostgreSQL:** `'123'::INTEGER`
|
| 280 |
+
- **ANSI SQL:** `CAST('123' AS INTEGER)`
|
| 281 |
+
|
| 282 |
+
**Example:**
|
| 283 |
+
```sql
|
| 284 |
+
-- PostgreSQL
|
| 285 |
+
SELECT '123'::INTEGER;
|
| 286 |
+
|
| 287 |
+
-- ANSI SQL
|
| 288 |
+
SELECT CAST('123' AS INTEGER);
|
| 289 |
+
|
| 290 |
+
### 5. INSERT ... RETURNING
|
| 291 |
+
|
| 292 |
+
- **PostgreSQL:** Supports `RETURNING` to get values immediately
|
| 293 |
+
- **ANSI SQL:** No equivalent; use a separate `SELECT` query
|
| 294 |
+
|
| 295 |
+
**Example:**
|
| 296 |
+
```sql
|
| 297 |
+
-- PostgreSQL
|
| 298 |
+
INSERT INTO users (username) VALUES ('john') RETURNING id;
|
| 299 |
+
|
| 300 |
+
-- ANSI SQL
|
| 301 |
+
-- No direct equivalent; you must SELECT after INSERT
|
| 302 |
+
INSERT INTO users (username) VALUES ('john');
|
| 303 |
+
SELECT id FROM users WHERE username = 'john';
|
| 304 |
+
|
| 305 |
+
|
| 306 |
+
### 6. UPSERT (INSERT ON CONFLICT)
|
| 307 |
+
|
| 308 |
+
- **PostgreSQL:** `INSERT ... ON CONFLICT`
|
| 309 |
+
- **ANSI SQL:** Use `MERGE` (available in ANSI SQL-2003+)
|
| 310 |
+
|
| 311 |
+
**Example:**
|
| 312 |
+
```sql
|
| 313 |
+
-- PostgreSQL
|
| 314 |
+
INSERT INTO users (id, username)
|
| 315 |
+
VALUES (1, 'john')
|
| 316 |
+
ON CONFLICT (id)
|
| 317 |
+
DO UPDATE SET username = EXCLUDED.username;
|
| 318 |
+
|
| 319 |
+
-- ANSI SQL
|
| 320 |
+
MERGE INTO users AS target
|
| 321 |
+
USING (SELECT 1 AS id, 'john' AS username) AS source
|
| 322 |
+
ON (target.id = source.id)
|
| 323 |
+
WHEN MATCHED THEN
|
| 324 |
+
UPDATE SET username = source.username
|
| 325 |
+
WHEN NOT MATCHED THEN
|
| 326 |
+
INSERT (id, username) VALUES (source.id, source.username);
|
| 327 |
+
|
| 328 |
+
### 7. SERIAL (Auto-increment IDs)
|
| 329 |
+
|
| 330 |
+
- **PostgreSQL:** `SERIAL` keyword
|
| 331 |
+
- **ANSI SQL:** Use `IDENTITY` in table creation
|
| 332 |
+
|
| 333 |
+
**Example:**
|
| 334 |
+
```sql
|
| 335 |
+
-- PostgreSQL
|
| 336 |
+
CREATE TABLE users (
|
| 337 |
+
id SERIAL PRIMARY KEY,
|
| 338 |
+
username TEXT
|
| 339 |
+
);
|
| 340 |
+
|
| 341 |
+
-- ANSI SQL
|
| 342 |
+
CREATE TABLE users (
|
| 343 |
+
id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
| 344 |
+
username VARCHAR(255)
|
| 345 |
+
);
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
### 8. Arrays and Accessing Arrays
|
| 349 |
+
|
| 350 |
+
- **PostgreSQL:** Supports arrays and uses `[index]`
|
| 351 |
+
- **ANSI SQL:** No array type; use normalized relational design
|
| 352 |
+
|
| 353 |
+
**Example:**
|
| 354 |
+
```sql
|
| 355 |
+
-- PostgreSQL
|
| 356 |
+
SELECT tags[1] FROM posts;
|
| 357 |
+
|
| 358 |
+
-- ANSI SQL
|
| 359 |
+
-- No equivalent. Use a separate `post_tags` table instead.
|
| 360 |
+
|
| 361 |
+
### 9. PostgreSQL Extensions and Functions
|
| 362 |
+
|
| 363 |
+
- Replace PostgreSQL-specific functions like `NOW()`, `CURRENT_DATE`, etc., with ANSI SQL equivalents when available.
|
| 364 |
+
|
| 365 |
+
**Example:**
|
| 366 |
+
```sql
|
| 367 |
+
-- PostgreSQL
|
| 368 |
+
SELECT NOW(), CURRENT_DATE;
|
| 369 |
+
|
| 370 |
+
-- ANSI SQL
|
| 371 |
+
SELECT CURRENT_TIMESTAMP, CURRENT_DATE;
|
| 372 |
+
|
| 373 |
+
### 10. Table Aliases with 'AS'
|
| 374 |
+
|
| 375 |
+
- **PostgreSQL:** `FROM users AS u`
|
| 376 |
+
- **ANSI SQL:** `FROM users u` (without `AS` is also valid)
|
| 377 |
+
|
| 378 |
+
**Note:** Both are valid ANSI SQL — no change needed.
|
| 379 |
+
|
| 380 |
+
### 11. Boolean Type
|
| 381 |
+
|
| 382 |
+
- **PostgreSQL:** Uses `BOOLEAN`, and accepts `TRUE` / `FALSE`
|
| 383 |
+
- **ANSI SQL:** Also supports `BOOLEAN`, but in some systems may need conversion to `CHAR(1)` with `'Y'` / `'N'`
|
| 384 |
+
|
| 385 |
+
**Example (if needed):**
|
| 386 |
+
```sql
|
| 387 |
+
-- PostgreSQL
|
| 388 |
+
SELECT * FROM flags WHERE is_enabled = TRUE;
|
| 389 |
+
|
| 390 |
+
-- ANSI SQL (fallback style)
|
| 391 |
+
SELECT * FROM flags WHERE is_enabled = 'Y';
|
| 392 |
+
|
| 393 |
+
|
| 394 |
+
### 12. Text vs. VARCHAR
|
| 395 |
+
|
| 396 |
+
- **PostgreSQL:** Allows unbounded `TEXT`
|
| 397 |
+
- **ANSI SQL:** Use `VARCHAR(n)`
|
| 398 |
+
|
| 399 |
+
**Example:**
|
| 400 |
+
```sql
|
| 401 |
+
-- PostgreSQL
|
| 402 |
+
CREATE TABLE posts (content TEXT);
|
| 403 |
+
|
| 404 |
+
-- ANSI SQL
|
| 405 |
+
CREATE TABLE posts (content VARCHAR(65535));
|
| 406 |
+
|
| 407 |
+
---
|
| 408 |
+
|
| 409 |
==========================
|
| 410 |
# Examples
|
| 411 |
==========================
|