{
  "schemaVersion": "1.0",
  "item": {
    "slug": "sql-query-generator",
    "name": "SQL Query Generator",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/cerbug45/sql-query-generator",
    "canonicalUrl": "https://clawhub.ai/cerbug45/sql-query-generator",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/sql-query-generator",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=sql-query-generator",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "README.md",
      "SECURITY_SUMMARY.md",
      "SKILL.md",
      "examples.py",
      "requirements.txt",
      "security_tests.py"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-07T17:22:31.273Z",
      "expiresAt": "2026-05-14T17:22:31.273Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
        "contentDisposition": "attachment; filename=\"afrexai-annual-report-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/sql-query-generator"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/sql-query-generator",
    "agentPageUrl": "https://openagent3.xyz/skills/sql-query-generator/agent",
    "manifestUrl": "https://openagent3.xyz/skills/sql-query-generator/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/sql-query-generator/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Overview",
        "body": "This skill enables AI agents to generate accurate, optimized SQL queries from natural language descriptions. It supports multiple database systems and follows best practices for query construction, security, and performance."
      },
      {
        "title": "Method 1: Direct Download",
        "body": "# Clone or download the repository\ngit clone https://github.com/yourusername/sql-query-generator.git\ncd sql-query-generator\n\n# No external dependencies required for core functionality\npython sql_query_generator.py"
      },
      {
        "title": "Method 2: Using as a Module",
        "body": "# Copy sql_query_generator.py to your project\ncp sql_query_generator.py /path/to/your/project/\n\n# Import in your code\nfrom sql_query_generator import SQLQueryGenerator, DatabaseType"
      },
      {
        "title": "Method 3: AI Agent Integration",
        "body": "For AI agents using this skill:\n\nRead this SKILL.md file completely before generating queries\nFollow all security guidelines strictly\nAlways use parameterized queries\nValidate all inputs before query generation\nInclude security warnings in responses"
      },
      {
        "title": "Optional Database Drivers",
        "body": "Install only the drivers you need:\n\n# PostgreSQL\npip install psycopg2-binary\n\n# MySQL\npip install mysql-connector-python\n\n# SQL Server\npip install pyodbc\n\n# Oracle\npip install cx_Oracle\n\n# For testing and development\npip install pytest pytest-cov"
      },
      {
        "title": "System Requirements",
        "body": "Python 3.7 or higher\nNo external dependencies for core query generation\nDatabase drivers only needed for actual query execution"
      },
      {
        "title": "Supported Database Systems",
        "body": "PostgreSQL\nMySQL\nSQLite\nMicrosoft SQL Server\nOracle Database\nMariaDB"
      },
      {
        "title": "1. Query Generation",
        "body": "SELECT Queries: Simple and complex data retrieval\nJOIN Operations: INNER, LEFT, RIGHT, FULL OUTER, CROSS\nAggregations: GROUP BY, HAVING, aggregate functions\nSubqueries: Correlated and non-correlated\nCTEs: Common Table Expressions (WITH clause)\nWindow Functions: OVER, PARTITION BY, ROW_NUMBER, RANK\nINSERT/UPDATE/DELETE: Data manipulation queries\nDDL: CREATE, ALTER, DROP statements"
      },
      {
        "title": "2. Query Optimization",
        "body": "Index usage recommendations\nQuery execution plan analysis\nPerformance optimization suggestions\nAvoiding N+1 query problems"
      },
      {
        "title": "3. Security Features",
        "body": "SQL injection prevention\nParameterized query generation\nInput validation patterns\nRole-based access control patterns"
      },
      {
        "title": "Basic Query Generation",
        "body": "When generating SQL queries, follow these steps:\n\nUnderstand the Request\n\nParse natural language input\nIdentify required tables\nDetermine join conditions\nExtract filter criteria\n\n\n\nGenerate Base Query\n-- Example structure\nSELECT \n    column1,\n    column2,\n    aggregate_function(column3) AS alias\nFROM \n    table1\nJOIN \n    table2 ON table1.id = table2.foreign_id\nWHERE \n    condition1 = value1\n    AND condition2 > value2\nGROUP BY \n    column1, column2\nHAVING \n    aggregate_condition\nORDER BY \n    column1 DESC\nLIMIT 100;\n\n\n\nApply Security Measures\n\nUse parameterized queries\nValidate all inputs\nEscape special characters"
      },
      {
        "title": "Query Patterns",
        "body": "Pattern 1: Simple SELECT\n\n-- Natural language: \"Get all users who registered after January 1, 2024\"\nSELECT \n    id,\n    username,\n    email,\n    registration_date\nFROM \n    users\nWHERE \n    registration_date > $1  -- Parameterized\nORDER BY \n    registration_date DESC;\n\nPattern 2: JOIN with Aggregation\n\n-- Natural language: \"Show total orders by customer in 2024\"\nSELECT \n    c.customer_name,\n    c.email,\n    COUNT(o.order_id) AS total_orders,\n    SUM(o.total_amount) AS total_spent\nFROM \n    customers c\nINNER JOIN \n    orders o ON c.customer_id = o.customer_id\nWHERE \n    EXTRACT(YEAR FROM o.order_date) = $1\nGROUP BY \n    c.customer_id,\n    c.customer_name,\n    c.email\nHAVING \n    COUNT(o.order_id) > 5\nORDER BY \n    total_spent DESC;\n\nPattern 3: Subquery\n\n-- Natural language: \"Find products with above-average prices\"\nSELECT \n    product_name,\n    price,\n    category\nFROM \n    products\nWHERE \n    price > (\n        SELECT AVG(price)\n        FROM products\n    )\nORDER BY \n    price DESC;\n\nPattern 4: CTE (Common Table Expression)\n\n-- Natural language: \"Get top 3 products per category by sales\"\nWITH product_sales AS (\n    SELECT \n        p.product_id,\n        p.product_name,\n        p.category_id,\n        c.category_name,\n        SUM(oi.quantity * oi.unit_price) AS total_sales,\n        ROW_NUMBER() OVER (\n            PARTITION BY p.category_id \n            ORDER BY SUM(oi.quantity * oi.unit_price) DESC\n        ) AS rank_in_category\n    FROM \n        products p\n    JOIN \n        order_items oi ON p.product_id = oi.product_id\n    JOIN \n        categories c ON p.category_id = c.category_id\n    GROUP BY \n        p.product_id,\n        p.product_name,\n        p.category_id,\n        c.category_name\n)\nSELECT \n    category_name,\n    product_name,\n    total_sales,\n    rank_in_category\nFROM \n    product_sales\nWHERE \n    rank_in_category <= 3\nORDER BY \n    category_name,\n    rank_in_category;\n\nPattern 5: Window Functions\n\n-- Natural language: \"Show running total of sales per day\"\nSELECT \n    sale_date,\n    daily_total,\n    SUM(daily_total) OVER (\n        ORDER BY sale_date \n        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\n    ) AS running_total,\n    AVG(daily_total) OVER (\n        ORDER BY sale_date \n        ROWS BETWEEN 6 PRECEDING AND CURRENT ROW\n    ) AS moving_average_7days\nFROM (\n    SELECT \n        DATE(order_date) AS sale_date,\n        SUM(total_amount) AS daily_total\n    FROM \n        orders\n    GROUP BY \n        DATE(order_date)\n) daily_sales\nORDER BY \n    sale_date;"
      },
      {
        "title": "1. Query Structure",
        "body": "Always use explicit column names (avoid SELECT *)\nUse meaningful table aliases\nIndent for readability\nComment complex logic"
      },
      {
        "title": "2. Performance",
        "body": "Create appropriate indexes\nAvoid SELECT DISTINCT when possible (use GROUP BY instead)\nUse EXISTS instead of IN for large datasets\nLimit result sets when appropriate\nUse EXPLAIN to analyze query plans"
      },
      {
        "title": "3. Security (CRITICAL)",
        "body": "3.1 MANDATORY Security Rules\n\nTHESE RULES ARE NON-NEGOTIABLE AND MUST ALWAYS BE FOLLOWED:\n\nNEVER CONCATENATE USER INPUT INTO SQL\n# WRONG - CRITICAL SECURITY VULNERABILITY\nquery = f\"SELECT * FROM users WHERE username = '{user_input}'\"\n\n# CORRECT - Always use parameters\nquery = \"SELECT * FROM users WHERE username = %s\"\ncursor.execute(query, (user_input,))\n\n\n\nALL VALUES MUST BE PARAMETERIZED\n\nEven seemingly \"safe\" values like numbers\nEven values from \"trusted\" sources\nEven internal application values\nNO EXCEPTIONS\n\n\n\nVALIDATE AND SANITIZE ALL INPUTS\n# Whitelist validation\nVALID_STATUSES = ['active', 'inactive', 'pending']\nif status not in VALID_STATUSES:\n    raise ValueError(\"Invalid status\")\n\n# Type validation\nif not isinstance(user_id, int):\n    raise TypeError(\"user_id must be integer\")\n\n# Length validation\nif len(username) > 50:\n    raise ValueError(\"username too long\")\n\n\n\nESCAPE DYNAMIC IDENTIFIERS PROPERLY\nfrom psycopg2 import sql\n\n# For table/column names that must be dynamic\nquery = sql.SQL(\"SELECT * FROM {} WHERE id = %s\").format(\n    sql.Identifier(table_name)\n)\ncursor.execute(query, (user_id,))\n\n3.2 Input Validation Framework\n\nimport re\nfrom typing import Any, List, Optional\n\nclass SQLInputValidator:\n    \"\"\"Comprehensive input validation for SQL queries\"\"\"\n    \n    @staticmethod\n    def validate_identifier(identifier: str, max_length: int = 63) -> str:\n        \"\"\"Validate table/column names\"\"\"\n        # Check length\n        if len(identifier) > max_length:\n            raise ValueError(f\"Identifier too long: {len(identifier)} > {max_length}\")\n        \n        # Only alphanumeric and underscore\n        if not re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', identifier):\n            raise ValueError(f\"Invalid identifier: {identifier}\")\n        \n        # Prevent SQL keywords as identifiers\n        SQL_KEYWORDS = {\n            'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'DROP', 'CREATE',\n            'ALTER', 'TRUNCATE', 'UNION', 'JOIN', 'WHERE', 'FROM'\n        }\n        if identifier.upper() in SQL_KEYWORDS:\n            raise ValueError(f\"SQL keyword not allowed: {identifier}\")\n        \n        return identifier\n    \n    @staticmethod\n    def validate_integer(value: Any, min_val: Optional[int] = None, \n                        max_val: Optional[int] = None) -> int:\n        \"\"\"Validate integer values\"\"\"\n        try:\n            int_value = int(value)\n        except (ValueError, TypeError):\n            raise ValueError(f\"Invalid integer: {value}\")\n        \n        if min_val is not None and int_value < min_val:\n            raise ValueError(f\"Value {int_value} below minimum {min_val}\")\n        \n        if max_val is not None and int_value > max_val:\n            raise ValueError(f\"Value {int_value} above maximum {max_val}\")\n        \n        return int_value\n    \n    @staticmethod\n    def validate_string(value: str, max_length: int = 255, \n                       allow_empty: bool = False) -> str:\n        \"\"\"Validate string values\"\"\"\n        if not isinstance(value, str):\n            raise TypeError(\"Value must be string\")\n        \n        if not allow_empty and len(value) == 0:\n            raise ValueError(\"Empty string not allowed\")\n        \n        if len(value) > max_length:\n            raise ValueError(f\"String too long: {len(value)} > {max_length}\")\n        \n        # Check for null bytes\n        if '\\x00' in value:\n            raise ValueError(\"Null bytes not allowed in string\")\n        \n        return value\n    \n    @staticmethod\n    def validate_email(email: str) -> str:\n        \"\"\"Validate email format\"\"\"\n        email = SQLInputValidator.validate_string(email, max_length=254)\n        \n        # Basic email validation\n        if not re.match(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$', email):\n            raise ValueError(f\"Invalid email format: {email}\")\n        \n        return email\n    \n    @staticmethod\n    def validate_date(date_str: str) -> str:\n        \"\"\"Validate date format (YYYY-MM-DD)\"\"\"\n        if not re.match(r'^\\d{4}-\\d{2}-\\d{2}$', date_str):\n            raise ValueError(f\"Invalid date format: {date_str}\")\n        \n        return date_str\n    \n    @staticmethod\n    def validate_enum(value: str, allowed_values: List[str]) -> str:\n        \"\"\"Validate value against whitelist\"\"\"\n        if value not in allowed_values:\n            raise ValueError(f\"Invalid value: {value}. Allowed: {allowed_values}\")\n        \n        return value\n\n3.3 SQL Injection Attack Patterns to Prevent\n\n# Detect common SQL injection patterns\nINJECTION_PATTERNS = [\n    r\"('|(\\\\')|(--)|(\\#)|(%23)|(;))\",  # Basic SQL injection\n    r\"((\\%27)|(\\'))\",                   # Single quote variations\n    r\"(union.*select)\",                 # UNION-based injection\n    r\"(insert.*into)\",                  # INSERT injection\n    r\"(update.*set)\",                   # UPDATE injection\n    r\"(delete.*from)\",                  # DELETE injection\n    r\"(drop.*table)\",                   # DROP TABLE\n    r\"(exec(\\s|\\+)+(s|x)p\\w+)\",        # Stored procedure execution\n    r\"(script.*>)\",                     # XSS attempts\n]\n\ndef detect_injection_attempt(value: str) -> bool:\n    \"\"\"Detect potential SQL injection attempts\"\"\"\n    value_lower = value.lower()\n    for pattern in INJECTION_PATTERNS:\n        if re.search(pattern, value_lower):\n            return True\n    return False\n\n3.4 Secure Query Builder\n\nclass SecureQueryBuilder:\n    \"\"\"Build SQL queries with mandatory security checks\"\"\"\n    \n    def __init__(self, db_type: DatabaseType):\n        self.db_type = db_type\n        self.validator = SQLInputValidator()\n        self.params = []\n    \n    def build_select(self, table: str, columns: List[str], \n                    conditions: dict) -> tuple:\n        \"\"\"Build SELECT query with validation\"\"\"\n        # Validate table name\n        table = self.validator.validate_identifier(table)\n        \n        # Validate columns\n        validated_columns = [\n            self.validator.validate_identifier(col) \n            for col in columns\n        ]\n        \n        # Build query\n        query = f\"SELECT {', '.join(validated_columns)} FROM {table}\"\n        \n        # Add WHERE clause with parameters\n        if conditions:\n            where_parts = []\n            for key, value in conditions.items():\n                key = self.validator.validate_identifier(key)\n                where_parts.append(f\"{key} = %s\")\n                self.params.append(value)\n            \n            query += \" WHERE \" + \" AND \".join(where_parts)\n        \n        return query, tuple(self.params)\n\n3.5 Database Connection Security\n\nimport ssl\nfrom typing import Optional\n\nclass SecureConnection:\n    \"\"\"Secure database connection configuration\"\"\"\n    \n    @staticmethod\n    def get_postgresql_ssl_config() -> dict:\n        \"\"\"PostgreSQL SSL configuration\"\"\"\n        return {\n            'sslmode': 'require',  # or 'verify-full' for production\n            'sslrootcert': '/path/to/ca-cert.pem',\n            'sslcert': '/path/to/client-cert.pem',\n            'sslkey': '/path/to/client-key.pem'\n        }\n    \n    @staticmethod\n    def get_connection_timeout() -> dict:\n        \"\"\"Connection timeout settings\"\"\"\n        return {\n            'connect_timeout': 10,\n            'command_timeout': 30,\n            'keepalives': 1,\n            'keepalives_idle': 30,\n            'keepalives_interval': 10,\n            'keepalives_count': 5\n        }\n    \n    @staticmethod\n    def create_secure_connection(database_url: str) -> Any:\n        \"\"\"Create connection with security settings\"\"\"\n        import psycopg2\n        \n        # Parse connection string securely\n        # NEVER log the connection string (contains credentials)\n        \n        conn = psycopg2.connect(\n            database_url,\n            **SecureConnection.get_postgresql_ssl_config(),\n            **SecureConnection.get_connection_timeout()\n        )\n        \n        # Set session security parameters\n        cursor = conn.cursor()\n        cursor.execute(\"SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE\")\n        cursor.execute(\"SET statement_timeout = 30000\")  # 30 seconds\n        cursor.close()\n        \n        return conn\n\n3.6 Rate Limiting\n\nimport time\nfrom collections import defaultdict\nfrom threading import Lock\n\nclass RateLimiter:\n    \"\"\"Prevent query flooding attacks\"\"\"\n    \n    def __init__(self, max_requests: int = 100, window_seconds: int = 60):\n        self.max_requests = max_requests\n        self.window_seconds = window_seconds\n        self.requests = defaultdict(list)\n        self.lock = Lock()\n    \n    def is_allowed(self, identifier: str) -> bool:\n        \"\"\"Check if request is allowed\"\"\"\n        with self.lock:\n            now = time.time()\n            window_start = now - self.window_seconds\n            \n            # Clean old requests\n            self.requests[identifier] = [\n                req_time for req_time in self.requests[identifier]\n                if req_time > window_start\n            ]\n            \n            # Check limit\n            if len(self.requests[identifier]) >= self.max_requests:\n                return False\n            \n            # Add new request\n            self.requests[identifier].append(now)\n            return True\n\n3.7 Audit Logging\n\nimport logging\nimport json\nfrom datetime import datetime\nfrom typing import Any, Dict\n\nclass SecurityAuditLogger:\n    \"\"\"Log all database operations for security auditing\"\"\"\n    \n    def __init__(self, log_file: str = '/var/log/sql_audit.log'):\n        self.logger = logging.getLogger('sql_audit')\n        handler = logging.FileHandler(log_file)\n        handler.setFormatter(logging.Formatter(\n            '%(asctime)s - %(levelname)s - %(message)s'\n        ))\n        self.logger.addHandler(handler)\n        self.logger.setLevel(logging.INFO)\n    \n    def log_query(self, query: str, params: tuple, user_id: str,\n                  ip_address: str, result_count: int = None):\n        \"\"\"Log query execution\"\"\"\n        log_entry = {\n            'timestamp': datetime.utcnow().isoformat(),\n            'user_id': user_id,\n            'ip_address': ip_address,\n            'query': query,\n            'param_count': len(params),\n            'result_count': result_count\n        }\n        self.logger.info(json.dumps(log_entry))\n    \n    def log_security_event(self, event_type: str, details: Dict[str, Any],\n                          severity: str = 'WARNING'):\n        \"\"\"Log security events\"\"\"\n        log_entry = {\n            'timestamp': datetime.utcnow().isoformat(),\n            'event_type': event_type,\n            'severity': severity,\n            'details': details\n        }\n        \n        if severity == 'CRITICAL':\n            self.logger.critical(json.dumps(log_entry))\n        elif severity == 'ERROR':\n            self.logger.error(json.dumps(log_entry))\n        else:\n            self.logger.warning(json.dumps(log_entry))\n\n3.8 Prepared Statement Pool\n\nfrom typing import Dict, Any\nimport hashlib\n\nclass PreparedStatementPool:\n    \"\"\"Reuse prepared statements for better performance and security\"\"\"\n    \n    def __init__(self, connection):\n        self.connection = connection\n        self.statements: Dict[str, Any] = {}\n    \n    def get_statement(self, query: str):\n        \"\"\"Get or create prepared statement\"\"\"\n        # Create hash of query for lookup\n        query_hash = hashlib.sha256(query.encode()).hexdigest()[:16]\n        \n        if query_hash not in self.statements:\n            # Create new prepared statement\n            cursor = self.connection.cursor()\n            statement_name = f\"stmt_{query_hash}\"\n            cursor.execute(f\"PREPARE {statement_name} AS {query}\")\n            self.statements[query_hash] = statement_name\n        \n        return self.statements[query_hash]\n    \n    def execute(self, query: str, params: tuple):\n        \"\"\"Execute using prepared statement\"\"\"\n        stmt_name = self.get_statement(query)\n        cursor = self.connection.cursor()\n        param_list = ', '.join(['%s'] * len(params))\n        cursor.execute(f\"EXECUTE {stmt_name}({param_list})\", params)\n        return cursor"
      },
      {
        "title": "4. Parameterization Examples",
        "body": "PostgreSQL/Python (psycopg2)\n\n# CORRECT - Parameterized\ncursor.execute(\n    \"SELECT * FROM users WHERE email = %s AND status = %s\",\n    (user_email, status)\n)\n\n# WRONG - String concatenation (SQL injection risk)\ncursor.execute(\n    f\"SELECT * FROM users WHERE email = '{user_email}'\"\n)\n\nMySQL/Python (mysql-connector)\n\n# CORRECT\ncursor.execute(\n    \"SELECT * FROM products WHERE price > %s\",\n    (min_price,)\n)\n\nSQLite/Python\n\n# CORRECT\ncursor.execute(\n    \"SELECT * FROM orders WHERE order_date > ?\",\n    (start_date,)\n)\n\nNode.js (PostgreSQL)\n\n// CORRECT\nconst result = await client.query(\n    'SELECT * FROM users WHERE id = $1',\n    [userId]\n);"
      },
      {
        "title": "5. Database-Specific Syntax",
        "body": "PostgreSQL\n\nUse $1, $2, $3 for parameters\nSupports advanced features: JSONB, arrays, full-text search\nUse RETURNING clause for INSERT/UPDATE/DELETE\nCase-sensitive text search with ILIKE\n\nMySQL\n\nUse ? for parameters\nLIMIT syntax: LIMIT offset, count\nUse backticks for identifiers with spaces\nDate functions: DATE_FORMAT, CURDATE()\n\nSQL Server\n\nUse @param1, @param2 for parameters\nTOP instead of LIMIT\nUse square brackets for identifiers\nDate functions: GETDATE(), DATEADD()\n\nSQLite\n\nUse ? for parameters\nLimited ALTER TABLE support\nNo RIGHT JOIN or FULL OUTER JOIN\nDate functions as strings"
      },
      {
        "title": "Error Handling",
        "body": "When generating queries, include error handling recommendations:\n\nimport psycopg2\nfrom psycopg2 import sql\n\ntry:\n    cursor.execute(\n        sql.SQL(\"SELECT * FROM {} WHERE id = %s\").format(\n            sql.Identifier('users')\n        ),\n        (user_id,)\n    )\n    results = cursor.fetchall()\nexcept psycopg2.Error as e:\n    print(f\"Database error: {e}\")\n    # Log error, return appropriate response\nfinally:\n    cursor.close()"
      },
      {
        "title": "Query Validation Checklist",
        "body": "Before providing a query, verify:\n\nAll table and column names are valid\n JOIN conditions are correct\n WHERE clause logic is accurate\n Parameters are used (not string concatenation)\n Appropriate indexes exist or are recommended\n Query is optimized for the expected dataset size\n Results will be properly limited if needed\n Error handling is included in implementation code"
      },
      {
        "title": "Response Format",
        "body": "When responding to a query request, provide:\n\nThe SQL Query (properly formatted and commented)\nExplanation of what the query does\nParameters that need to be passed\nExpected Result structure\nPerformance Notes (if applicable)\nSecurity Warnings (if applicable)\nImplementation Example in the requested language"
      },
      {
        "title": "Example Response Structure",
        "body": "### SQL Query\n```sql\n-- Get active users with their order counts\nSELECT \n    u.user_id,\n    u.username,\n    u.email,\n    COUNT(o.order_id) AS order_count,\n    COALESCE(SUM(o.total_amount), 0) AS lifetime_value\nFROM \n    users u\nLEFT JOIN \n    orders o ON u.user_id = o.user_id\nWHERE \n    u.status = $1\n    AND u.created_at >= $2\nGROUP BY \n    u.user_id,\n    u.username,\n    u.email\nHAVING \n    COUNT(o.order_id) >= $3\nORDER BY \n    lifetime_value DESC\nLIMIT $4;"
      },
      {
        "title": "Parameters",
        "body": "$1: status (string, e.g., 'active')\n$2: created_at (date, e.g., '2024-01-01')\n$3: min_orders (integer, e.g., 5)\n$4: limit (integer, e.g., 100)"
      },
      {
        "title": "Explanation",
        "body": "This query retrieves active users who joined after a specified date and have placed a minimum number of orders. It calculates their total order count and lifetime value, sorted by highest spending customers first."
      },
      {
        "title": "Expected Result",
        "body": "user_idusernameemailorder_countlifetime_value123john_doejohn@example.com152500.00"
      },
      {
        "title": "Performance Notes",
        "body": "Ensure index on users.status and users.created_at\nEnsure index on orders.user_id\nFor large datasets, consider pagination"
      },
      {
        "title": "Implementation Example (Python/psycopg2)",
        "body": "cursor.execute(query, ('active', '2024-01-01', 5, 100))\nresults = cursor.fetchall()\n\n## Advanced Topics\n\n### 1. Query Optimization Techniques\n- Use EXPLAIN ANALYZE to understand query plans\n- Create covering indexes\n- Partition large tables\n- Use materialized views for complex aggregations\n- Implement query result caching\n\n### 2. Complex Scenarios\n- Recursive CTEs for hierarchical data\n- Pivot/Unpivot operations\n- Full-text search\n- Geospatial queries\n- Time-series analysis\n\n### 3. Migration Support\n- Generate queries for data migration\n- Schema comparison queries\n- Data validation queries\n- Backup and restore scripts\n\n## Testing Recommendations\n\nAlways suggest testing generated queries with:\n1. Small dataset first\n2. EXPLAIN or EXPLAIN ANALYZE\n3. Various edge cases (NULL values, empty sets)\n4. Performance benchmarks\n5. Security scanning tools\n\n## Common Pitfalls to Avoid\n\n1. **N+1 Query Problem**: Use JOINs instead of multiple queries\n2. **SELECT ***: Specify needed columns explicitly\n3. **Missing Indexes**: Recommend indexes on filter/join columns\n4. **Cartesian Products**: Ensure proper JOIN conditions\n5. **Implicit Type Conversions**: Cast explicitly when needed\n6. **Timezone Issues**: Always use timezone-aware timestamps\n\n## Integration Examples\n\n### REST API\n```python\nfrom flask import Flask, request, jsonify\nimport psycopg2\n\n@app.route('/api/users', methods=['GET'])\ndef get_users():\n    status = request.args.get('status', 'active')\n    \n    # Validate input\n    if status not in ['active', 'inactive', 'suspended']:\n        return jsonify({'error': 'Invalid status'}), 400\n    \n    try:\n        cursor.execute(\n            \"SELECT id, username, email FROM users WHERE status = %s\",\n            (status,)\n        )\n        users = cursor.fetchall()\n        return jsonify(users)\n    except Exception as e:\n        return jsonify({'error': str(e)}), 500"
      },
      {
        "title": "GraphQL Resolver",
        "body": "const resolvers = {\n  Query: {\n    users: async (_, { status, limit }, { db }) => {\n      const result = await db.query(\n        'SELECT * FROM users WHERE status = $1 LIMIT $2',\n        [status, limit]\n      );\n      return result.rows;\n    }\n  }\n};"
      },
      {
        "title": "Conclusion",
        "body": "This skill provides comprehensive SQL query generation capabilities with a focus on security, performance, and best practices. Always prioritize parameterized queries and provide clear documentation with generated SQL."
      }
    ],
    "body": "SQL Query Generator Skill\nOverview\n\nThis skill enables AI agents to generate accurate, optimized SQL queries from natural language descriptions. It supports multiple database systems and follows best practices for query construction, security, and performance.\n\nInstallation\nMethod 1: Direct Download\n# Clone or download the repository\ngit clone https://github.com/yourusername/sql-query-generator.git\ncd sql-query-generator\n\n# No external dependencies required for core functionality\npython sql_query_generator.py\n\nMethod 2: Using as a Module\n# Copy sql_query_generator.py to your project\ncp sql_query_generator.py /path/to/your/project/\n\n# Import in your code\nfrom sql_query_generator import SQLQueryGenerator, DatabaseType\n\nMethod 3: AI Agent Integration\n\nFor AI agents using this skill:\n\nRead this SKILL.md file completely before generating queries\nFollow all security guidelines strictly\nAlways use parameterized queries\nValidate all inputs before query generation\nInclude security warnings in responses\nOptional Database Drivers\n\nInstall only the drivers you need:\n\n# PostgreSQL\npip install psycopg2-binary\n\n# MySQL\npip install mysql-connector-python\n\n# SQL Server\npip install pyodbc\n\n# Oracle\npip install cx_Oracle\n\n# For testing and development\npip install pytest pytest-cov\n\nSystem Requirements\nPython 3.7 or higher\nNo external dependencies for core query generation\nDatabase drivers only needed for actual query execution\nSupported Database Systems\nPostgreSQL\nMySQL\nSQLite\nMicrosoft SQL Server\nOracle Database\nMariaDB\nCore Capabilities\n1. Query Generation\nSELECT Queries: Simple and complex data retrieval\nJOIN Operations: INNER, LEFT, RIGHT, FULL OUTER, CROSS\nAggregations: GROUP BY, HAVING, aggregate functions\nSubqueries: Correlated and non-correlated\nCTEs: Common Table Expressions (WITH clause)\nWindow Functions: OVER, PARTITION BY, ROW_NUMBER, RANK\nINSERT/UPDATE/DELETE: Data manipulation queries\nDDL: CREATE, ALTER, DROP statements\n2. Query Optimization\nIndex usage recommendations\nQuery execution plan analysis\nPerformance optimization suggestions\nAvoiding N+1 query problems\n3. Security Features\nSQL injection prevention\nParameterized query generation\nInput validation patterns\nRole-based access control patterns\nUsage Instructions\nBasic Query Generation\n\nWhen generating SQL queries, follow these steps:\n\nUnderstand the Request\n\nParse natural language input\nIdentify required tables\nDetermine join conditions\nExtract filter criteria\n\nGenerate Base Query\n\n-- Example structure\nSELECT \n    column1,\n    column2,\n    aggregate_function(column3) AS alias\nFROM \n    table1\nJOIN \n    table2 ON table1.id = table2.foreign_id\nWHERE \n    condition1 = value1\n    AND condition2 > value2\nGROUP BY \n    column1, column2\nHAVING \n    aggregate_condition\nORDER BY \n    column1 DESC\nLIMIT 100;\n\n\nApply Security Measures\n\nUse parameterized queries\nValidate all inputs\nEscape special characters\nQuery Patterns\nPattern 1: Simple SELECT\n-- Natural language: \"Get all users who registered after January 1, 2024\"\nSELECT \n    id,\n    username,\n    email,\n    registration_date\nFROM \n    users\nWHERE \n    registration_date > $1  -- Parameterized\nORDER BY \n    registration_date DESC;\n\nPattern 2: JOIN with Aggregation\n-- Natural language: \"Show total orders by customer in 2024\"\nSELECT \n    c.customer_name,\n    c.email,\n    COUNT(o.order_id) AS total_orders,\n    SUM(o.total_amount) AS total_spent\nFROM \n    customers c\nINNER JOIN \n    orders o ON c.customer_id = o.customer_id\nWHERE \n    EXTRACT(YEAR FROM o.order_date) = $1\nGROUP BY \n    c.customer_id,\n    c.customer_name,\n    c.email\nHAVING \n    COUNT(o.order_id) > 5\nORDER BY \n    total_spent DESC;\n\nPattern 3: Subquery\n-- Natural language: \"Find products with above-average prices\"\nSELECT \n    product_name,\n    price,\n    category\nFROM \n    products\nWHERE \n    price > (\n        SELECT AVG(price)\n        FROM products\n    )\nORDER BY \n    price DESC;\n\nPattern 4: CTE (Common Table Expression)\n-- Natural language: \"Get top 3 products per category by sales\"\nWITH product_sales AS (\n    SELECT \n        p.product_id,\n        p.product_name,\n        p.category_id,\n        c.category_name,\n        SUM(oi.quantity * oi.unit_price) AS total_sales,\n        ROW_NUMBER() OVER (\n            PARTITION BY p.category_id \n            ORDER BY SUM(oi.quantity * oi.unit_price) DESC\n        ) AS rank_in_category\n    FROM \n        products p\n    JOIN \n        order_items oi ON p.product_id = oi.product_id\n    JOIN \n        categories c ON p.category_id = c.category_id\n    GROUP BY \n        p.product_id,\n        p.product_name,\n        p.category_id,\n        c.category_name\n)\nSELECT \n    category_name,\n    product_name,\n    total_sales,\n    rank_in_category\nFROM \n    product_sales\nWHERE \n    rank_in_category <= 3\nORDER BY \n    category_name,\n    rank_in_category;\n\nPattern 5: Window Functions\n-- Natural language: \"Show running total of sales per day\"\nSELECT \n    sale_date,\n    daily_total,\n    SUM(daily_total) OVER (\n        ORDER BY sale_date \n        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW\n    ) AS running_total,\n    AVG(daily_total) OVER (\n        ORDER BY sale_date \n        ROWS BETWEEN 6 PRECEDING AND CURRENT ROW\n    ) AS moving_average_7days\nFROM (\n    SELECT \n        DATE(order_date) AS sale_date,\n        SUM(total_amount) AS daily_total\n    FROM \n        orders\n    GROUP BY \n        DATE(order_date)\n) daily_sales\nORDER BY \n    sale_date;\n\nBest Practices\n1. Query Structure\nAlways use explicit column names (avoid SELECT *)\nUse meaningful table aliases\nIndent for readability\nComment complex logic\n2. Performance\nCreate appropriate indexes\nAvoid SELECT DISTINCT when possible (use GROUP BY instead)\nUse EXISTS instead of IN for large datasets\nLimit result sets when appropriate\nUse EXPLAIN to analyze query plans\n3. Security (CRITICAL)\n3.1 MANDATORY Security Rules\n\nTHESE RULES ARE NON-NEGOTIABLE AND MUST ALWAYS BE FOLLOWED:\n\nNEVER CONCATENATE USER INPUT INTO SQL\n\n# WRONG - CRITICAL SECURITY VULNERABILITY\nquery = f\"SELECT * FROM users WHERE username = '{user_input}'\"\n\n# CORRECT - Always use parameters\nquery = \"SELECT * FROM users WHERE username = %s\"\ncursor.execute(query, (user_input,))\n\n\nALL VALUES MUST BE PARAMETERIZED\n\nEven seemingly \"safe\" values like numbers\nEven values from \"trusted\" sources\nEven internal application values\nNO EXCEPTIONS\n\nVALIDATE AND SANITIZE ALL INPUTS\n\n# Whitelist validation\nVALID_STATUSES = ['active', 'inactive', 'pending']\nif status not in VALID_STATUSES:\n    raise ValueError(\"Invalid status\")\n\n# Type validation\nif not isinstance(user_id, int):\n    raise TypeError(\"user_id must be integer\")\n\n# Length validation\nif len(username) > 50:\n    raise ValueError(\"username too long\")\n\n\nESCAPE DYNAMIC IDENTIFIERS PROPERLY\n\nfrom psycopg2 import sql\n\n# For table/column names that must be dynamic\nquery = sql.SQL(\"SELECT * FROM {} WHERE id = %s\").format(\n    sql.Identifier(table_name)\n)\ncursor.execute(query, (user_id,))\n\n3.2 Input Validation Framework\nimport re\nfrom typing import Any, List, Optional\n\nclass SQLInputValidator:\n    \"\"\"Comprehensive input validation for SQL queries\"\"\"\n    \n    @staticmethod\n    def validate_identifier(identifier: str, max_length: int = 63) -> str:\n        \"\"\"Validate table/column names\"\"\"\n        # Check length\n        if len(identifier) > max_length:\n            raise ValueError(f\"Identifier too long: {len(identifier)} > {max_length}\")\n        \n        # Only alphanumeric and underscore\n        if not re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', identifier):\n            raise ValueError(f\"Invalid identifier: {identifier}\")\n        \n        # Prevent SQL keywords as identifiers\n        SQL_KEYWORDS = {\n            'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'DROP', 'CREATE',\n            'ALTER', 'TRUNCATE', 'UNION', 'JOIN', 'WHERE', 'FROM'\n        }\n        if identifier.upper() in SQL_KEYWORDS:\n            raise ValueError(f\"SQL keyword not allowed: {identifier}\")\n        \n        return identifier\n    \n    @staticmethod\n    def validate_integer(value: Any, min_val: Optional[int] = None, \n                        max_val: Optional[int] = None) -> int:\n        \"\"\"Validate integer values\"\"\"\n        try:\n            int_value = int(value)\n        except (ValueError, TypeError):\n            raise ValueError(f\"Invalid integer: {value}\")\n        \n        if min_val is not None and int_value < min_val:\n            raise ValueError(f\"Value {int_value} below minimum {min_val}\")\n        \n        if max_val is not None and int_value > max_val:\n            raise ValueError(f\"Value {int_value} above maximum {max_val}\")\n        \n        return int_value\n    \n    @staticmethod\n    def validate_string(value: str, max_length: int = 255, \n                       allow_empty: bool = False) -> str:\n        \"\"\"Validate string values\"\"\"\n        if not isinstance(value, str):\n            raise TypeError(\"Value must be string\")\n        \n        if not allow_empty and len(value) == 0:\n            raise ValueError(\"Empty string not allowed\")\n        \n        if len(value) > max_length:\n            raise ValueError(f\"String too long: {len(value)} > {max_length}\")\n        \n        # Check for null bytes\n        if '\\x00' in value:\n            raise ValueError(\"Null bytes not allowed in string\")\n        \n        return value\n    \n    @staticmethod\n    def validate_email(email: str) -> str:\n        \"\"\"Validate email format\"\"\"\n        email = SQLInputValidator.validate_string(email, max_length=254)\n        \n        # Basic email validation\n        if not re.match(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$', email):\n            raise ValueError(f\"Invalid email format: {email}\")\n        \n        return email\n    \n    @staticmethod\n    def validate_date(date_str: str) -> str:\n        \"\"\"Validate date format (YYYY-MM-DD)\"\"\"\n        if not re.match(r'^\\d{4}-\\d{2}-\\d{2}$', date_str):\n            raise ValueError(f\"Invalid date format: {date_str}\")\n        \n        return date_str\n    \n    @staticmethod\n    def validate_enum(value: str, allowed_values: List[str]) -> str:\n        \"\"\"Validate value against whitelist\"\"\"\n        if value not in allowed_values:\n            raise ValueError(f\"Invalid value: {value}. Allowed: {allowed_values}\")\n        \n        return value\n\n3.3 SQL Injection Attack Patterns to Prevent\n# Detect common SQL injection patterns\nINJECTION_PATTERNS = [\n    r\"('|(\\\\')|(--)|(\\#)|(%23)|(;))\",  # Basic SQL injection\n    r\"((\\%27)|(\\'))\",                   # Single quote variations\n    r\"(union.*select)\",                 # UNION-based injection\n    r\"(insert.*into)\",                  # INSERT injection\n    r\"(update.*set)\",                   # UPDATE injection\n    r\"(delete.*from)\",                  # DELETE injection\n    r\"(drop.*table)\",                   # DROP TABLE\n    r\"(exec(\\s|\\+)+(s|x)p\\w+)\",        # Stored procedure execution\n    r\"(script.*>)\",                     # XSS attempts\n]\n\ndef detect_injection_attempt(value: str) -> bool:\n    \"\"\"Detect potential SQL injection attempts\"\"\"\n    value_lower = value.lower()\n    for pattern in INJECTION_PATTERNS:\n        if re.search(pattern, value_lower):\n            return True\n    return False\n\n3.4 Secure Query Builder\nclass SecureQueryBuilder:\n    \"\"\"Build SQL queries with mandatory security checks\"\"\"\n    \n    def __init__(self, db_type: DatabaseType):\n        self.db_type = db_type\n        self.validator = SQLInputValidator()\n        self.params = []\n    \n    def build_select(self, table: str, columns: List[str], \n                    conditions: dict) -> tuple:\n        \"\"\"Build SELECT query with validation\"\"\"\n        # Validate table name\n        table = self.validator.validate_identifier(table)\n        \n        # Validate columns\n        validated_columns = [\n            self.validator.validate_identifier(col) \n            for col in columns\n        ]\n        \n        # Build query\n        query = f\"SELECT {', '.join(validated_columns)} FROM {table}\"\n        \n        # Add WHERE clause with parameters\n        if conditions:\n            where_parts = []\n            for key, value in conditions.items():\n                key = self.validator.validate_identifier(key)\n                where_parts.append(f\"{key} = %s\")\n                self.params.append(value)\n            \n            query += \" WHERE \" + \" AND \".join(where_parts)\n        \n        return query, tuple(self.params)\n\n3.5 Database Connection Security\nimport ssl\nfrom typing import Optional\n\nclass SecureConnection:\n    \"\"\"Secure database connection configuration\"\"\"\n    \n    @staticmethod\n    def get_postgresql_ssl_config() -> dict:\n        \"\"\"PostgreSQL SSL configuration\"\"\"\n        return {\n            'sslmode': 'require',  # or 'verify-full' for production\n            'sslrootcert': '/path/to/ca-cert.pem',\n            'sslcert': '/path/to/client-cert.pem',\n            'sslkey': '/path/to/client-key.pem'\n        }\n    \n    @staticmethod\n    def get_connection_timeout() -> dict:\n        \"\"\"Connection timeout settings\"\"\"\n        return {\n            'connect_timeout': 10,\n            'command_timeout': 30,\n            'keepalives': 1,\n            'keepalives_idle': 30,\n            'keepalives_interval': 10,\n            'keepalives_count': 5\n        }\n    \n    @staticmethod\n    def create_secure_connection(database_url: str) -> Any:\n        \"\"\"Create connection with security settings\"\"\"\n        import psycopg2\n        \n        # Parse connection string securely\n        # NEVER log the connection string (contains credentials)\n        \n        conn = psycopg2.connect(\n            database_url,\n            **SecureConnection.get_postgresql_ssl_config(),\n            **SecureConnection.get_connection_timeout()\n        )\n        \n        # Set session security parameters\n        cursor = conn.cursor()\n        cursor.execute(\"SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE\")\n        cursor.execute(\"SET statement_timeout = 30000\")  # 30 seconds\n        cursor.close()\n        \n        return conn\n\n3.6 Rate Limiting\nimport time\nfrom collections import defaultdict\nfrom threading import Lock\n\nclass RateLimiter:\n    \"\"\"Prevent query flooding attacks\"\"\"\n    \n    def __init__(self, max_requests: int = 100, window_seconds: int = 60):\n        self.max_requests = max_requests\n        self.window_seconds = window_seconds\n        self.requests = defaultdict(list)\n        self.lock = Lock()\n    \n    def is_allowed(self, identifier: str) -> bool:\n        \"\"\"Check if request is allowed\"\"\"\n        with self.lock:\n            now = time.time()\n            window_start = now - self.window_seconds\n            \n            # Clean old requests\n            self.requests[identifier] = [\n                req_time for req_time in self.requests[identifier]\n                if req_time > window_start\n            ]\n            \n            # Check limit\n            if len(self.requests[identifier]) >= self.max_requests:\n                return False\n            \n            # Add new request\n            self.requests[identifier].append(now)\n            return True\n\n3.7 Audit Logging\nimport logging\nimport json\nfrom datetime import datetime\nfrom typing import Any, Dict\n\nclass SecurityAuditLogger:\n    \"\"\"Log all database operations for security auditing\"\"\"\n    \n    def __init__(self, log_file: str = '/var/log/sql_audit.log'):\n        self.logger = logging.getLogger('sql_audit')\n        handler = logging.FileHandler(log_file)\n        handler.setFormatter(logging.Formatter(\n            '%(asctime)s - %(levelname)s - %(message)s'\n        ))\n        self.logger.addHandler(handler)\n        self.logger.setLevel(logging.INFO)\n    \n    def log_query(self, query: str, params: tuple, user_id: str,\n                  ip_address: str, result_count: int = None):\n        \"\"\"Log query execution\"\"\"\n        log_entry = {\n            'timestamp': datetime.utcnow().isoformat(),\n            'user_id': user_id,\n            'ip_address': ip_address,\n            'query': query,\n            'param_count': len(params),\n            'result_count': result_count\n        }\n        self.logger.info(json.dumps(log_entry))\n    \n    def log_security_event(self, event_type: str, details: Dict[str, Any],\n                          severity: str = 'WARNING'):\n        \"\"\"Log security events\"\"\"\n        log_entry = {\n            'timestamp': datetime.utcnow().isoformat(),\n            'event_type': event_type,\n            'severity': severity,\n            'details': details\n        }\n        \n        if severity == 'CRITICAL':\n            self.logger.critical(json.dumps(log_entry))\n        elif severity == 'ERROR':\n            self.logger.error(json.dumps(log_entry))\n        else:\n            self.logger.warning(json.dumps(log_entry))\n\n3.8 Prepared Statement Pool\nfrom typing import Dict, Any\nimport hashlib\n\nclass PreparedStatementPool:\n    \"\"\"Reuse prepared statements for better performance and security\"\"\"\n    \n    def __init__(self, connection):\n        self.connection = connection\n        self.statements: Dict[str, Any] = {}\n    \n    def get_statement(self, query: str):\n        \"\"\"Get or create prepared statement\"\"\"\n        # Create hash of query for lookup\n        query_hash = hashlib.sha256(query.encode()).hexdigest()[:16]\n        \n        if query_hash not in self.statements:\n            # Create new prepared statement\n            cursor = self.connection.cursor()\n            statement_name = f\"stmt_{query_hash}\"\n            cursor.execute(f\"PREPARE {statement_name} AS {query}\")\n            self.statements[query_hash] = statement_name\n        \n        return self.statements[query_hash]\n    \n    def execute(self, query: str, params: tuple):\n        \"\"\"Execute using prepared statement\"\"\"\n        stmt_name = self.get_statement(query)\n        cursor = self.connection.cursor()\n        param_list = ', '.join(['%s'] * len(params))\n        cursor.execute(f\"EXECUTE {stmt_name}({param_list})\", params)\n        return cursor\n\n4. Parameterization Examples\n\nPostgreSQL/Python (psycopg2)\n\n# CORRECT - Parameterized\ncursor.execute(\n    \"SELECT * FROM users WHERE email = %s AND status = %s\",\n    (user_email, status)\n)\n\n# WRONG - String concatenation (SQL injection risk)\ncursor.execute(\n    f\"SELECT * FROM users WHERE email = '{user_email}'\"\n)\n\n\nMySQL/Python (mysql-connector)\n\n# CORRECT\ncursor.execute(\n    \"SELECT * FROM products WHERE price > %s\",\n    (min_price,)\n)\n\n\nSQLite/Python\n\n# CORRECT\ncursor.execute(\n    \"SELECT * FROM orders WHERE order_date > ?\",\n    (start_date,)\n)\n\n\nNode.js (PostgreSQL)\n\n// CORRECT\nconst result = await client.query(\n    'SELECT * FROM users WHERE id = $1',\n    [userId]\n);\n\n5. Database-Specific Syntax\n\nPostgreSQL\n\nUse $1, $2, $3 for parameters\nSupports advanced features: JSONB, arrays, full-text search\nUse RETURNING clause for INSERT/UPDATE/DELETE\nCase-sensitive text search with ILIKE\n\nMySQL\n\nUse ? for parameters\nLIMIT syntax: LIMIT offset, count\nUse backticks for identifiers with spaces\nDate functions: DATE_FORMAT, CURDATE()\n\nSQL Server\n\nUse @param1, @param2 for parameters\nTOP instead of LIMIT\nUse square brackets for identifiers\nDate functions: GETDATE(), DATEADD()\n\nSQLite\n\nUse ? for parameters\nLimited ALTER TABLE support\nNo RIGHT JOIN or FULL OUTER JOIN\nDate functions as strings\nError Handling\n\nWhen generating queries, include error handling recommendations:\n\nimport psycopg2\nfrom psycopg2 import sql\n\ntry:\n    cursor.execute(\n        sql.SQL(\"SELECT * FROM {} WHERE id = %s\").format(\n            sql.Identifier('users')\n        ),\n        (user_id,)\n    )\n    results = cursor.fetchall()\nexcept psycopg2.Error as e:\n    print(f\"Database error: {e}\")\n    # Log error, return appropriate response\nfinally:\n    cursor.close()\n\nQuery Validation Checklist\n\nBefore providing a query, verify:\n\n All table and column names are valid\n JOIN conditions are correct\n WHERE clause logic is accurate\n Parameters are used (not string concatenation)\n Appropriate indexes exist or are recommended\n Query is optimized for the expected dataset size\n Results will be properly limited if needed\n Error handling is included in implementation code\nResponse Format\n\nWhen responding to a query request, provide:\n\nThe SQL Query (properly formatted and commented)\nExplanation of what the query does\nParameters that need to be passed\nExpected Result structure\nPerformance Notes (if applicable)\nSecurity Warnings (if applicable)\nImplementation Example in the requested language\nExample Response Structure\n### SQL Query\n```sql\n-- Get active users with their order counts\nSELECT \n    u.user_id,\n    u.username,\n    u.email,\n    COUNT(o.order_id) AS order_count,\n    COALESCE(SUM(o.total_amount), 0) AS lifetime_value\nFROM \n    users u\nLEFT JOIN \n    orders o ON u.user_id = o.user_id\nWHERE \n    u.status = $1\n    AND u.created_at >= $2\nGROUP BY \n    u.user_id,\n    u.username,\n    u.email\nHAVING \n    COUNT(o.order_id) >= $3\nORDER BY \n    lifetime_value DESC\nLIMIT $4;\n\nParameters\n$1: status (string, e.g., 'active')\n$2: created_at (date, e.g., '2024-01-01')\n$3: min_orders (integer, e.g., 5)\n$4: limit (integer, e.g., 100)\nExplanation\n\nThis query retrieves active users who joined after a specified date and have placed a minimum number of orders. It calculates their total order count and lifetime value, sorted by highest spending customers first.\n\nExpected Result\nuser_id\tusername\temail\torder_count\tlifetime_value\n123\tjohn_doe\tjohn@example.com\t15\t2500.00\nPerformance Notes\nEnsure index on users.status and users.created_at\nEnsure index on orders.user_id\nFor large datasets, consider pagination\nImplementation Example (Python/psycopg2)\ncursor.execute(query, ('active', '2024-01-01', 5, 100))\nresults = cursor.fetchall()\n\n\n## Advanced Topics\n\n### 1. Query Optimization Techniques\n- Use EXPLAIN ANALYZE to understand query plans\n- Create covering indexes\n- Partition large tables\n- Use materialized views for complex aggregations\n- Implement query result caching\n\n### 2. Complex Scenarios\n- Recursive CTEs for hierarchical data\n- Pivot/Unpivot operations\n- Full-text search\n- Geospatial queries\n- Time-series analysis\n\n### 3. Migration Support\n- Generate queries for data migration\n- Schema comparison queries\n- Data validation queries\n- Backup and restore scripts\n\n## Testing Recommendations\n\nAlways suggest testing generated queries with:\n1. Small dataset first\n2. EXPLAIN or EXPLAIN ANALYZE\n3. Various edge cases (NULL values, empty sets)\n4. Performance benchmarks\n5. Security scanning tools\n\n## Common Pitfalls to Avoid\n\n1. **N+1 Query Problem**: Use JOINs instead of multiple queries\n2. **SELECT ***: Specify needed columns explicitly\n3. **Missing Indexes**: Recommend indexes on filter/join columns\n4. **Cartesian Products**: Ensure proper JOIN conditions\n5. **Implicit Type Conversions**: Cast explicitly when needed\n6. **Timezone Issues**: Always use timezone-aware timestamps\n\n## Integration Examples\n\n### REST API\n```python\nfrom flask import Flask, request, jsonify\nimport psycopg2\n\n@app.route('/api/users', methods=['GET'])\ndef get_users():\n    status = request.args.get('status', 'active')\n    \n    # Validate input\n    if status not in ['active', 'inactive', 'suspended']:\n        return jsonify({'error': 'Invalid status'}), 400\n    \n    try:\n        cursor.execute(\n            \"SELECT id, username, email FROM users WHERE status = %s\",\n            (status,)\n        )\n        users = cursor.fetchall()\n        return jsonify(users)\n    except Exception as e:\n        return jsonify({'error': str(e)}), 500\n\nGraphQL Resolver\nconst resolvers = {\n  Query: {\n    users: async (_, { status, limit }, { db }) => {\n      const result = await db.query(\n        'SELECT * FROM users WHERE status = $1 LIMIT $2',\n        [status, limit]\n      );\n      return result.rows;\n    }\n  }\n};\n\nConclusion\n\nThis skill provides comprehensive SQL query generation capabilities with a focus on security, performance, and best practices. Always prioritize parameterized queries and provide clear documentation with generated SQL."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/cerbug45/sql-query-generator",
    "publisherUrl": "https://clawhub.ai/cerbug45/sql-query-generator",
    "owner": "cerbug45",
    "version": "0.3.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/sql-query-generator",
    "downloadUrl": "https://openagent3.xyz/downloads/sql-query-generator",
    "agentUrl": "https://openagent3.xyz/skills/sql-query-generator/agent",
    "manifestUrl": "https://openagent3.xyz/skills/sql-query-generator/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/sql-query-generator/agent.md"
  }
}